Commit d545a0cd authored by Nathan Friend's avatar Nathan Friend

Merge branch '221101-implement-gitlab-ui-component-for-sorting-releases' into 'master'

Resolve "Implement gitlab-ui component for sorting Releases"

See merge request gitlab-org/gitlab!43963
parents 58735e25 15fd4688
...@@ -6,6 +6,7 @@ import { __ } from '~/locale'; ...@@ -6,6 +6,7 @@ import { __ } from '~/locale';
import ReleaseBlock from './release_block.vue'; import ReleaseBlock from './release_block.vue';
import ReleasesPagination from './releases_pagination.vue'; import ReleasesPagination from './releases_pagination.vue';
import ReleaseSkeletonLoader from './release_skeleton_loader.vue'; import ReleaseSkeletonLoader from './release_skeleton_loader.vue';
import ReleasesSort from './releases_sort.vue';
export default { export default {
name: 'ReleasesApp', name: 'ReleasesApp',
...@@ -16,6 +17,7 @@ export default { ...@@ -16,6 +17,7 @@ export default {
ReleaseBlock, ReleaseBlock,
ReleasesPagination, ReleasesPagination,
ReleaseSkeletonLoader, ReleaseSkeletonLoader,
ReleasesSort,
}, },
computed: { computed: {
...mapState('list', [ ...mapState('list', [
...@@ -62,16 +64,20 @@ export default { ...@@ -62,16 +64,20 @@ export default {
</script> </script>
<template> <template>
<div class="flex flex-column mt-2"> <div class="flex flex-column mt-2">
<gl-button <div class="gl-align-self-end gl-mb-3">
v-if="newReleasePath" <releases-sort class="gl-mr-2" @sort:changed="fetchReleases" />
:href="newReleasePath"
:aria-describedby="shouldRenderEmptyState && 'releases-description'" <gl-button
category="primary" v-if="newReleasePath"
variant="success" :href="newReleasePath"
class="align-self-end mb-2 js-new-release-btn" :aria-describedby="shouldRenderEmptyState && 'releases-description'"
> category="primary"
{{ __('New release') }} variant="success"
</gl-button> class="js-new-release-btn"
>
{{ __('New release') }}
</gl-button>
</div>
<release-skeleton-loader v-if="isLoading" class="js-loading" /> <release-skeleton-loader v-if="isLoading" class="js-loading" />
......
<script>
import { GlSorting, GlSortingItem } from '@gitlab/ui';
import { mapState, mapActions } from 'vuex';
import { ASCENDING_ODER, DESCENDING_ORDER, SORT_OPTIONS } from '../constants';
export default {
name: 'ReleasesSort',
components: {
GlSorting,
GlSortingItem,
},
computed: {
...mapState('list', {
orderBy: state => state.sorting.orderBy,
sort: state => state.sorting.sort,
}),
sortOptions() {
return SORT_OPTIONS;
},
sortText() {
const option = this.sortOptions.find(s => s.orderBy === this.orderBy);
return option.label;
},
isSortAscending() {
return this.sort === ASCENDING_ODER;
},
},
methods: {
...mapActions('list', ['setSorting']),
onDirectionChange() {
const sort = this.isSortAscending ? DESCENDING_ORDER : ASCENDING_ODER;
this.setSorting({ sort });
this.$emit('sort:changed');
},
onSortItemClick(item) {
this.setSorting({ orderBy: item });
this.$emit('sort:changed');
},
isActiveSortItem(item) {
return this.orderBy === item;
},
},
};
</script>
<template>
<gl-sorting
:text="sortText"
:is-ascending="isSortAscending"
data-testid="releases-sort"
@sortDirectionChange="onDirectionChange"
>
<gl-sorting-item
v-for="item in sortOptions"
:key="item.orderBy"
:active="isActiveSortItem(item.orderBy)"
@click="onSortItemClick(item.orderBy)"
>
{{ item.label }}
</gl-sorting-item>
</gl-sorting>
</template>
import { __ } from '~/locale';
export const MAX_MILESTONES_TO_DISPLAY = 5; export const MAX_MILESTONES_TO_DISPLAY = 5;
export const BACK_URL_PARAM = 'back_url'; export const BACK_URL_PARAM = 'back_url';
...@@ -12,3 +14,19 @@ export const ASSET_LINK_TYPE = Object.freeze({ ...@@ -12,3 +14,19 @@ export const ASSET_LINK_TYPE = Object.freeze({
export const DEFAULT_ASSET_LINK_TYPE = ASSET_LINK_TYPE.OTHER; export const DEFAULT_ASSET_LINK_TYPE = ASSET_LINK_TYPE.OTHER;
export const PAGE_SIZE = 20; export const PAGE_SIZE = 20;
export const ASCENDING_ODER = 'asc';
export const DESCENDING_ORDER = 'desc';
export const RELEASED_AT = 'released_at';
export const CREATED_AT = 'created_at';
export const SORT_OPTIONS = [
{
orderBy: RELEASED_AT,
label: __('Released date'),
},
{
orderBy: CREATED_AT,
label: __('Created date'),
},
];
#import "./release.fragment.graphql" #import "./release.fragment.graphql"
query allReleases($fullPath: ID!, $first: Int, $last: Int, $before: String, $after: String) { query allReleases(
$fullPath: ID!
$first: Int
$last: Int
$before: String
$after: String
$sort: ReleaseSort
) {
project(fullPath: $fullPath) { project(fullPath: $fullPath) {
releases(first: $first, last: $last, before: $before, after: $after) { releases(first: $first, last: $last, before: $before, after: $after, sort: $sort) {
nodes { nodes {
...Release ...Release
} }
......
...@@ -4,6 +4,7 @@ fragment Release on Release { ...@@ -4,6 +4,7 @@ fragment Release on Release {
tagPath tagPath
descriptionHtml descriptionHtml
releasedAt releasedAt
createdAt
upcomingRelease upcomingRelease
assets { assets {
count count
......
...@@ -42,6 +42,10 @@ export const fetchReleasesGraphQl = ( ...@@ -42,6 +42,10 @@ export const fetchReleasesGraphQl = (
) => { ) => {
commit(types.REQUEST_RELEASES); commit(types.REQUEST_RELEASES);
const { sort, orderBy } = state.sorting;
const orderByParam = orderBy === 'created_at' ? 'created' : orderBy;
const sortParams = `${orderByParam}_${sort}`.toUpperCase();
let paginationParams; let paginationParams;
if (!before && !after) { if (!before && !after) {
paginationParams = { first: PAGE_SIZE }; paginationParams = { first: PAGE_SIZE };
...@@ -60,6 +64,7 @@ export const fetchReleasesGraphQl = ( ...@@ -60,6 +64,7 @@ export const fetchReleasesGraphQl = (
query: allReleasesQuery, query: allReleasesQuery,
variables: { variables: {
fullPath: state.projectPath, fullPath: state.projectPath,
sort: sortParams,
...paginationParams, ...paginationParams,
}, },
}) })
...@@ -80,8 +85,10 @@ export const fetchReleasesGraphQl = ( ...@@ -80,8 +85,10 @@ export const fetchReleasesGraphQl = (
export const fetchReleasesRest = ({ dispatch, commit, state }, { page }) => { export const fetchReleasesRest = ({ dispatch, commit, state }, { page }) => {
commit(types.REQUEST_RELEASES); commit(types.REQUEST_RELEASES);
const { sort, orderBy } = state.sorting;
api api
.releases(state.projectId, { page }) .releases(state.projectId, { page, sort, order_by: orderBy })
.then(({ data, headers }) => { .then(({ data, headers }) => {
const restPageInfo = parseIntPagination(normalizeHeaders(headers)); const restPageInfo = parseIntPagination(normalizeHeaders(headers));
const camelCasedReleases = convertObjectPropsToCamelCase(data, { deep: true }); const camelCasedReleases = convertObjectPropsToCamelCase(data, { deep: true });
...@@ -98,3 +105,5 @@ export const receiveReleasesError = ({ commit }) => { ...@@ -98,3 +105,5 @@ export const receiveReleasesError = ({ commit }) => {
commit(types.RECEIVE_RELEASES_ERROR); commit(types.RECEIVE_RELEASES_ERROR);
createFlash(__('An error occurred while fetching the releases. Please try again.')); createFlash(__('An error occurred while fetching the releases. Please try again.'));
}; };
export const setSorting = ({ commit }, data) => commit(types.SET_SORTING, data);
export const REQUEST_RELEASES = 'REQUEST_RELEASES'; export const REQUEST_RELEASES = 'REQUEST_RELEASES';
export const RECEIVE_RELEASES_SUCCESS = 'RECEIVE_RELEASES_SUCCESS'; export const RECEIVE_RELEASES_SUCCESS = 'RECEIVE_RELEASES_SUCCESS';
export const RECEIVE_RELEASES_ERROR = 'RECEIVE_RELEASES_ERROR'; export const RECEIVE_RELEASES_ERROR = 'RECEIVE_RELEASES_ERROR';
export const SET_SORTING = 'SET_SORTING';
...@@ -39,4 +39,8 @@ export default { ...@@ -39,4 +39,8 @@ export default {
state.restPageInfo = {}; state.restPageInfo = {};
state.graphQlPageInfo = {}; state.graphQlPageInfo = {};
}, },
[types.SET_SORTING](state, sorting) {
state.sorting = { ...state.sorting, ...sorting };
},
}; };
import { DESCENDING_ORDER, RELEASED_AT } from '../../../constants';
export default ({ export default ({
projectId, projectId,
projectPath, projectPath,
...@@ -16,4 +18,8 @@ export default ({ ...@@ -16,4 +18,8 @@ export default ({
releases: [], releases: [],
restPageInfo: {}, restPageInfo: {},
graphQlPageInfo: {}, graphQlPageInfo: {},
sorting: {
sort: DESCENDING_ORDER,
orderBy: RELEASED_AT,
},
}); });
---
title: Add ability to sort releases on Releases page
merge_request: 43963
author:
type: added
...@@ -43,6 +43,13 @@ To view a list of releases: ...@@ -43,6 +43,13 @@ To view a list of releases:
- On private projects, this number is visible to users with Reporter - On private projects, this number is visible to users with Reporter
[permissions](../../permissions.md#project-members-permissions) or higher. [permissions](../../permissions.md#project-members-permissions) or higher.
### Sort Releases
On the top right of the **Releases** page, you can use the sorting button to order releases by
**Released date** or **Created date**. You can sort releases in ascending or descending order.
![Sort Releases dropdown button](img/releases_sort_v13_6.png)
## Create a release ## Create a release
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32812) in GitLab 12.9. Releases can be created directly in the GitLab UI. > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32812) in GitLab 12.9. Releases can be created directly in the GitLab UI.
......
...@@ -22328,6 +22328,9 @@ msgstr "" ...@@ -22328,6 +22328,9 @@ msgstr ""
msgid "ReleaseAssetLinkType|Runbooks" msgid "ReleaseAssetLinkType|Runbooks"
msgstr "" msgstr ""
msgid "Released date"
msgstr ""
msgid "Releases" msgid "Releases"
msgstr "" msgstr ""
......
...@@ -3,8 +3,14 @@ ...@@ -3,8 +3,14 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'User views releases', :js do RSpec.describe 'User views releases', :js do
let_it_be(:today) { Time.zone.now }
let_it_be(:yesterday) { today - 1.day }
let_it_be(:tomorrow) { today + 1.day }
let_it_be(:project) { create(:project, :repository, :private) } let_it_be(:project) { create(:project, :repository, :private) }
let_it_be(:release) { create(:release, project: project, name: 'The first release' ) } let_it_be(:release_v1) { create(:release, project: project, tag: 'v1', name: 'The first release', released_at: yesterday, created_at: today) }
let_it_be(:release_v2) { create(:release, project: project, tag: 'v2-with-a/slash', name: 'The second release', released_at: today, created_at: yesterday) }
let_it_be(:release_v3) { create(:release, project: project, tag: 'v3', name: 'The third release', released_at: tomorrow, created_at: tomorrow) }
let_it_be(:maintainer) { create(:user) } let_it_be(:maintainer) { create(:user) }
let_it_be(:guest) { create(:user) } let_it_be(:guest) { create(:user) }
...@@ -17,38 +23,36 @@ RSpec.describe 'User views releases', :js do ...@@ -17,38 +23,36 @@ RSpec.describe 'User views releases', :js do
context('when the user is a maintainer') do context('when the user is a maintainer') do
before do before do
sign_in(maintainer) sign_in(maintainer)
end
it 'sees the release' do
visit project_releases_path(project) visit project_releases_path(project)
end
expect(page).to have_content(release.name) it 'sees the release' do
expect(page).to have_content(release.tag) page.within("##{release_v1.tag}") do
expect(page).not_to have_content('Upcoming Release') expect(page).to have_content(release_v1.name)
expect(page).to have_content(release_v1.tag)
expect(page).not_to have_content('Upcoming Release')
end
end end
context 'when there is a link as an asset' do context 'when there is a link as an asset' do
let!(:release_link) { create(:release_link, release: release, url: url ) } let!(:release_link) { create(:release_link, release: release_v1, url: url ) }
let(:url) { "#{project.web_url}/-/jobs/1/artifacts/download" } let(:url) { "#{project.web_url}/-/jobs/1/artifacts/download" }
let(:direct_asset_link) { Gitlab::Routing.url_helpers.project_release_url(project, release) << release_link.filepath } let(:direct_asset_link) { Gitlab::Routing.url_helpers.project_release_url(project, release_v1) << release_link.filepath }
it 'sees the link' do it 'sees the link' do
visit project_releases_path(project) page.within("##{release_v1.tag} .js-assets-list") do
page.within('.js-assets-list') do
expect(page).to have_link release_link.name, href: direct_asset_link expect(page).to have_link release_link.name, href: direct_asset_link
expect(page).not_to have_css('[data-testid="external-link-indicator"]') expect(page).not_to have_css('[data-testid="external-link-indicator"]')
end end
end end
context 'when there is a link redirect' do context 'when there is a link redirect' do
let!(:release_link) { create(:release_link, release: release, name: 'linux-amd64 binaries', filepath: '/binaries/linux-amd64', url: url) } let!(:release_link) { create(:release_link, release: release_v1, name: 'linux-amd64 binaries', filepath: '/binaries/linux-amd64', url: url) }
let(:url) { "#{project.web_url}/-/jobs/1/artifacts/download" } let(:url) { "#{project.web_url}/-/jobs/1/artifacts/download" }
it 'sees the link' do it 'sees the link' do
visit project_releases_path(project) page.within("##{release_v1.tag} .js-assets-list") do
page.within('.js-assets-list') do
expect(page).to have_link release_link.name, href: direct_asset_link expect(page).to have_link release_link.name, href: direct_asset_link
expect(page).not_to have_css('[data-testid="external-link-indicator"]') expect(page).not_to have_css('[data-testid="external-link-indicator"]')
end end
...@@ -59,9 +63,7 @@ RSpec.describe 'User views releases', :js do ...@@ -59,9 +63,7 @@ RSpec.describe 'User views releases', :js do
let(:url) { 'http://google.com/download' } let(:url) { 'http://google.com/download' }
it 'sees that the link is external resource' do it 'sees that the link is external resource' do
visit project_releases_path(project) page.within("##{release_v1.tag} .js-assets-list") do
page.within('.js-assets-list') do
expect(page).to have_css('[data-testid="external-link-indicator"]') expect(page).to have_css('[data-testid="external-link-indicator"]')
end end
end end
...@@ -69,23 +71,57 @@ RSpec.describe 'User views releases', :js do ...@@ -69,23 +71,57 @@ RSpec.describe 'User views releases', :js do
end end
context 'with an upcoming release' do context 'with an upcoming release' do
let(:tomorrow) { Time.zone.now + 1.day }
let!(:release) { create(:release, project: project, released_at: tomorrow ) }
it 'sees the upcoming tag' do it 'sees the upcoming tag' do
visit project_releases_path(project) page.within("##{release_v3.tag}") do
expect(page).to have_content('Upcoming Release')
expect(page).to have_content('Upcoming Release') end
end end
end end
context 'with a tag containing a slash' do context 'with a tag containing a slash' do
it 'sees the release' do it 'sees the release' do
release = create :release, project: project, tag: 'debian/2.4.0-1' page.within("##{release_v2.tag.parameterize}") do
visit project_releases_path(project) expect(page).to have_content(release_v2.name)
expect(page).to have_content(release_v2.tag)
end
end
end
context 'sorting' do
def sort_page(by:, direction:)
within '[data-testid="releases-sort"]' do
find('.dropdown-toggle').click
click_button(by, class: 'dropdown-item')
find('.sorting-direction-button').click if direction == :ascending
end
end
shared_examples 'releases sort order' do
it "sorts the releases #{description}" do
card_titles = page.all('.release-block .card-title', minimum: expected_releases.count)
card_titles.each_with_index do |title, index|
expect(title).to have_content(expected_releases[index].name)
end
end
end
context "when the page is sorted by the default sort order" do
let(:expected_releases) { [release_v3, release_v2, release_v1] }
it_behaves_like 'releases sort order'
end
context "when the page is sorted by created_at ascending " do
let(:expected_releases) { [release_v2, release_v1, release_v3] }
before do
sort_page by: 'Created date', direction: :ascending
end
expect(page).to have_content(release.name) it_behaves_like 'releases sort order'
expect(page).to have_content(release.tag)
end end
end end
end end
...@@ -98,14 +134,14 @@ RSpec.describe 'User views releases', :js do ...@@ -98,14 +134,14 @@ RSpec.describe 'User views releases', :js do
it 'renders release info except for Git-related data' do it 'renders release info except for Git-related data' do
visit project_releases_path(project) visit project_releases_path(project)
within('.release-block') do within('.release-block', match: :first) do
expect(page).to have_content(release.description) expect(page).to have_content(release_v3.description)
# The following properties (sometimes) include Git info, # The following properties (sometimes) include Git info,
# so they are not rendered for Guest users # so they are not rendered for Guest users
expect(page).not_to have_content(release.name) expect(page).not_to have_content(release_v3.name)
expect(page).not_to have_content(release.tag) expect(page).not_to have_content(release_v3.tag)
expect(page).not_to have_content(release.commit.short_id) expect(page).not_to have_content(release_v3.commit.short_id)
end end
end end
end end
......
import Vuex from 'vuex';
import { GlSorting, GlSortingItem } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import ReleasesSort from '~/releases/components/releases_sort.vue';
import createStore from '~/releases/stores';
import createListModule from '~/releases/stores/modules/list';
const localVue = createLocalVue();
localVue.use(Vuex);
describe('~/releases/components/releases_sort.vue', () => {
let wrapper;
let store;
let listModule;
const projectId = 8;
const createComponent = () => {
listModule = createListModule({ projectId });
store = createStore({
modules: {
list: listModule,
},
});
store.dispatch = jest.fn();
wrapper = shallowMount(ReleasesSort, {
store,
stubs: {
GlSortingItem,
},
localVue,
});
};
const findReleasesSorting = () => wrapper.find(GlSorting);
const findSortingItems = () => wrapper.findAll(GlSortingItem);
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
beforeEach(() => {
createComponent();
});
it('has all the sortable items', () => {
expect(findSortingItems()).toHaveLength(wrapper.vm.sortOptions.length);
});
it('on sort change set sorting in vuex and emit event', () => {
findReleasesSorting().vm.$emit('sortDirectionChange');
expect(store.dispatch).toHaveBeenCalledWith('list/setSorting', { sort: 'asc' });
expect(wrapper.emitted('sort:changed')).toBeTruthy();
});
it('on sort item click set sorting and emit event', () => {
const item = findSortingItems().at(0);
const { orderBy } = wrapper.vm.sortOptions[0];
item.vm.$emit('click');
expect(store.dispatch).toHaveBeenCalledWith('list/setSorting', { orderBy });
expect(wrapper.emitted('sort:changed')).toBeTruthy();
});
});
...@@ -6,6 +6,7 @@ import { ...@@ -6,6 +6,7 @@ import {
fetchReleasesGraphQl, fetchReleasesGraphQl,
fetchReleasesRest, fetchReleasesRest,
receiveReleasesError, receiveReleasesError,
setSorting,
} from '~/releases/stores/modules/list/actions'; } from '~/releases/stores/modules/list/actions';
import createState from '~/releases/stores/modules/list/state'; import createState from '~/releases/stores/modules/list/state';
import * as types from '~/releases/stores/modules/list/mutation_types'; import * as types from '~/releases/stores/modules/list/mutation_types';
...@@ -114,7 +115,7 @@ describe('Releases State actions', () => { ...@@ -114,7 +115,7 @@ describe('Releases State actions', () => {
it('makes a GraphQl query with a first variable', () => { it('makes a GraphQl query with a first variable', () => {
expect(gqClient.query).toHaveBeenCalledWith({ expect(gqClient.query).toHaveBeenCalledWith({
query: allReleasesQuery, query: allReleasesQuery,
variables: { fullPath: projectPath, first: PAGE_SIZE }, variables: { fullPath: projectPath, first: PAGE_SIZE, sort: 'RELEASED_AT_DESC' },
}); });
}); });
}); });
...@@ -127,7 +128,7 @@ describe('Releases State actions', () => { ...@@ -127,7 +128,7 @@ describe('Releases State actions', () => {
it('makes a GraphQl query with last and before variables', () => { it('makes a GraphQl query with last and before variables', () => {
expect(gqClient.query).toHaveBeenCalledWith({ expect(gqClient.query).toHaveBeenCalledWith({
query: allReleasesQuery, query: allReleasesQuery,
variables: { fullPath: projectPath, last: PAGE_SIZE, before }, variables: { fullPath: projectPath, last: PAGE_SIZE, before, sort: 'RELEASED_AT_DESC' },
}); });
}); });
}); });
...@@ -140,7 +141,7 @@ describe('Releases State actions', () => { ...@@ -140,7 +141,7 @@ describe('Releases State actions', () => {
it('makes a GraphQl query with first and after variables', () => { it('makes a GraphQl query with first and after variables', () => {
expect(gqClient.query).toHaveBeenCalledWith({ expect(gqClient.query).toHaveBeenCalledWith({
query: allReleasesQuery, query: allReleasesQuery,
variables: { fullPath: projectPath, first: PAGE_SIZE, after }, variables: { fullPath: projectPath, first: PAGE_SIZE, after, sort: 'RELEASED_AT_DESC' },
}); });
}); });
}); });
...@@ -156,6 +157,29 @@ describe('Releases State actions', () => { ...@@ -156,6 +157,29 @@ describe('Releases State actions', () => {
); );
}); });
}); });
describe('when the sort parameters are provided', () => {
it.each`
sort | orderBy | ReleaseSort
${'asc'} | ${'released_at'} | ${'RELEASED_AT_ASC'}
${'desc'} | ${'released_at'} | ${'RELEASED_AT_DESC'}
${'asc'} | ${'created_at'} | ${'CREATED_ASC'}
${'desc'} | ${'created_at'} | ${'CREATED_DESC'}
`(
'correctly sets $ReleaseSort based on $sort and $orderBy',
({ sort, orderBy, ReleaseSort }) => {
mockedState.sorting.sort = sort;
mockedState.sorting.orderBy = orderBy;
fetchReleasesGraphQl(vuexParams, { before: undefined, after: undefined });
expect(gqClient.query).toHaveBeenCalledWith({
query: allReleasesQuery,
variables: { fullPath: projectPath, first: PAGE_SIZE, sort: ReleaseSort },
});
},
);
});
}); });
describe('when the request is successful', () => { describe('when the request is successful', () => {
...@@ -230,7 +254,11 @@ describe('Releases State actions', () => { ...@@ -230,7 +254,11 @@ describe('Releases State actions', () => {
}); });
it('makes a REST query with a page query parameter', () => { it('makes a REST query with a page query parameter', () => {
expect(api.releases).toHaveBeenCalledWith(projectId, { page }); expect(api.releases).toHaveBeenCalledWith(projectId, {
page,
order_by: 'released_at',
sort: 'desc',
});
}); });
}); });
}); });
...@@ -302,4 +330,16 @@ describe('Releases State actions', () => { ...@@ -302,4 +330,16 @@ describe('Releases State actions', () => {
); );
}); });
}); });
describe('setSorting', () => {
it('should commit SET_SORTING', () => {
return testAction(
setSorting,
{ orderBy: 'released_at', sort: 'asc' },
null,
[{ type: types.SET_SORTING, payload: { orderBy: 'released_at', sort: 'asc' } }],
[],
);
});
});
}); });
...@@ -80,4 +80,16 @@ describe('Releases Store Mutations', () => { ...@@ -80,4 +80,16 @@ describe('Releases Store Mutations', () => {
expect(stateCopy.graphQlPageInfo).toEqual({}); expect(stateCopy.graphQlPageInfo).toEqual({});
}); });
}); });
describe('SET_SORTING', () => {
it('should merge the sorting object with sort value', () => {
mutations[types.SET_SORTING](stateCopy, { sort: 'asc' });
expect(stateCopy.sorting).toEqual({ ...stateCopy.sorting, sort: 'asc' });
});
it('should merge the sorting object with order_by value', () => {
mutations[types.SET_SORTING](stateCopy, { orderBy: 'created_at' });
expect(stateCopy.sorting).toEqual({ ...stateCopy.sorting, orderBy: 'created_at' });
});
});
}); });
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment