From 7330987a698c3f8cdb1497ff0a2ee70dae32d477 Mon Sep 17 00:00:00 2001 From: Nimit Bhargava Date: Thu, 10 Oct 2019 20:32:12 +0530 Subject: [PATCH 1/2] fix - maintaining sorting after navigation --- webapp/pages/index.vue | 26 +++++++++++++++++--------- webapp/store/postsFilter.js | 12 ++++++++++++ 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/webapp/pages/index.vue b/webapp/pages/index.vue index 91acb288c..2443bc037 100644 --- a/webapp/pages/index.vue +++ b/webapp/pages/index.vue @@ -11,7 +11,7 @@ :options="sortingOptions" size="large" v-bind:icon-right="sortingIcon" - @input="toggleOnlySorting" + @input="updateOrder" > @@ -62,7 +62,7 @@ import HcPostCard from '~/components/PostCard' import HcLoadMore from '~/components/LoadMore.vue' import MasonryGrid from '~/components/MasonryGrid/MasonryGrid.vue' import MasonryGridItem from '~/components/MasonryGrid/MasonryGridItem.vue' -import { mapGetters } from 'vuex' +import { mapGetters, mapMutations } from 'vuex' import { filterPosts } from '~/graphql/PostQuery.js' export default { @@ -83,10 +83,8 @@ export default { offset: 0, pageSize: 12, hashtag, - placeholder: this.$t('sorting.newest'), - selected: this.$t('sorting.newest'), sortingIcon: 'sort-amount-desc', - sorting: 'createdAt_desc', + selected: this.$t('sorting.newest'), sortingOptions: [ { label: this.$t('sorting.newest'), @@ -103,9 +101,15 @@ export default { ], } }, + mounted() { + if(this.postsOrder.label) { + this.selected = this.postsOrder.label + } + }, computed: { ...mapGetters({ postsFilter: 'postsFilter/postsFilter', + postsOrder: 'postsFilter/postsOrder', }), finalFilters() { let filter = this.postsFilter @@ -122,11 +126,15 @@ export default { }, }, methods: { - toggleOnlySorting(x) { + ...mapMutations({ + setPostsOrder: 'postsFilter/UPDATE_ORDER', + }), + updateOrder(sortingOptions) { this.offset = 0 this.posts = [] - this.sortingIcon = x.icons - this.sorting = x.order + this.sortingIcon = sortingOptions.icons + this.selected = sortingOptions.label + this.setPostsOrder(sortingOptions) }, clearSearch() { this.$router.push({ path: '/' }) @@ -176,7 +184,7 @@ export default { return { filter: this.finalFilters, first: this.pageSize, - orderBy: this.sorting, + orderBy: this.postsOrder.order, offset: 0, } }, diff --git a/webapp/store/postsFilter.js b/webapp/store/postsFilter.js index 964b265c0..8bdf1a238 100644 --- a/webapp/store/postsFilter.js +++ b/webapp/store/postsFilter.js @@ -12,6 +12,12 @@ export const state = () => { filter: { ...defaultFilter, }, + postsOrder: { + label: null, + value: 'Newest', + icons: 'sort-amount-desc', + order: 'createdAt_desc', + } } } @@ -46,6 +52,9 @@ export const mutations = { if (isEmpty(get(filter, 'emotions_some.emotion_in'))) delete filter.emotions_some state.filter = filter }, + UPDATE_ORDER(state, postsOrder) { + state.postsOrder = postsOrder + } } export const getters = { @@ -64,4 +73,7 @@ export const getters = { filteredByEmotions(state) { return get(state.filter, 'emotions_some.emotion_in') || [] }, + postsOrder(state) { + return state.postsOrder + } } From 16d07bd3ba66e61c414787fcc8ac84e2920a3525 Mon Sep 17 00:00:00 2001 From: roschaefer Date: Fri, 18 Oct 2019 16:08:11 +0200 Subject: [PATCH 2/2] refactor: lint, frontend tests, vuex store This fixes the lint errors and failing frontend tests. Also, when the user chooses another orderBy, the menu gets translated. The refactoring moves code and complexity into the vuex store where it can be tested separately. --- .../FilterPosts/CategoriesFilterMenuItems.vue | 6 +- .../FilterPosts/FilterPosts.spec.js | 28 +++--- webapp/components/FilterPosts/FilterPosts.vue | 2 +- .../FilterPosts/GeneralFilterMenuItems.vue | 8 +- webapp/locales/de.json | 16 +++- webapp/locales/en.json | 16 +++- webapp/pages/index.spec.js | 28 +++++- webapp/pages/index.vue | 57 +++++-------- webapp/store/{postsFilter.js => posts.js} | 50 ++++++++--- .../{postsFilter.spec.js => posts.spec.js} | 85 +++++++++++++++---- 10 files changed, 197 insertions(+), 99 deletions(-) rename webapp/store/{postsFilter.js => posts.js} (69%) rename webapp/store/{postsFilter.spec.js => posts.spec.js} (63%) diff --git a/webapp/components/FilterPosts/CategoriesFilterMenuItems.vue b/webapp/components/FilterPosts/CategoriesFilterMenuItems.vue index 7a35bf3cc..72835a660 100644 --- a/webapp/components/FilterPosts/CategoriesFilterMenuItems.vue +++ b/webapp/components/FilterPosts/CategoriesFilterMenuItems.vue @@ -67,13 +67,13 @@ export default { }, computed: { ...mapGetters({ - filteredCategoryIds: 'postsFilter/filteredCategoryIds', + filteredCategoryIds: 'posts/filteredCategoryIds', }), }, methods: { ...mapMutations({ - resetCategories: 'postsFilter/RESET_CATEGORIES', - toggleCategory: 'postsFilter/TOGGLE_CATEGORY', + resetCategories: 'posts/RESET_CATEGORIES', + toggleCategory: 'posts/TOGGLE_CATEGORY', }), }, } diff --git a/webapp/components/FilterPosts/FilterPosts.spec.js b/webapp/components/FilterPosts/FilterPosts.spec.js index 0cbd3e962..1f0ee920d 100644 --- a/webapp/components/FilterPosts/FilterPosts.spec.js +++ b/webapp/components/FilterPosts/FilterPosts.spec.js @@ -50,20 +50,20 @@ describe('FilterPosts.vue', () => { describe('mount', () => { mutations = { - 'postsFilter/TOGGLE_FILTER_BY_FOLLOWED': jest.fn(), - 'postsFilter/RESET_CATEGORIES': jest.fn(), - 'postsFilter/TOGGLE_CATEGORY': jest.fn(), - 'postsFilter/TOGGLE_EMOTION': jest.fn(), + 'posts/TOGGLE_FILTER_BY_FOLLOWED': jest.fn(), + 'posts/RESET_CATEGORIES': jest.fn(), + 'posts/TOGGLE_CATEGORY': jest.fn(), + 'posts/TOGGLE_EMOTION': jest.fn(), } getters = { - 'postsFilter/isActive': () => false, + 'posts/isActive': () => false, 'auth/isModerator': () => false, 'auth/user': () => { return { id: 'u34' } }, - 'postsFilter/filteredCategoryIds': jest.fn(() => []), - 'postsFilter/filteredByUsersFollowed': jest.fn(), - 'postsFilter/filteredByEmotions': jest.fn(() => []), + 'posts/filteredCategoryIds': jest.fn(() => []), + 'posts/filteredByUsersFollowed': jest.fn(), + 'posts/filteredByEmotions': jest.fn(() => []), } const openFilterPosts = () => { const store = new Vuex.Store({ mutations, getters }) @@ -94,18 +94,18 @@ describe('FilterPosts.vue', () => { const wrapper = openFilterPosts() environmentAndNatureButton = wrapper.findAll('button').at(2) environmentAndNatureButton.trigger('click') - expect(mutations['postsFilter/TOGGLE_CATEGORY']).toHaveBeenCalledWith({}, 'cat4') + expect(mutations['posts/TOGGLE_CATEGORY']).toHaveBeenCalledWith({}, 'cat4') }) it('sets category button attribute `primary` when corresponding category is filtered', () => { - getters['postsFilter/filteredCategoryIds'] = jest.fn(() => ['cat9']) + getters['posts/filteredCategoryIds'] = jest.fn(() => ['cat9']) const wrapper = openFilterPosts() democracyAndPoliticsButton = wrapper.findAll('button').at(4) expect(democracyAndPoliticsButton.attributes().class).toContain('ds-button-primary') }) it('sets "filter-by-followed-authors-only" button attribute `primary`', () => { - getters['postsFilter/filteredByUsersFollowed'] = jest.fn(() => true) + getters['posts/filteredByUsersFollowed'] = jest.fn(() => true) const wrapper = openFilterPosts() expect( wrapper.find({ name: 'filter-by-followed-authors-only' }).classes('ds-button-primary'), @@ -120,7 +120,7 @@ describe('FilterPosts.vue', () => { }) it('calls TOGGLE_FILTER_BY_FOLLOWED', () => { - expect(mutations['postsFilter/TOGGLE_FILTER_BY_FOLLOWED']).toHaveBeenCalledWith({}, 'u34') + expect(mutations['posts/TOGGLE_FILTER_BY_FOLLOWED']).toHaveBeenCalledWith({}, 'u34') }) }) @@ -129,11 +129,11 @@ describe('FilterPosts.vue', () => { const wrapper = openFilterPosts() happyEmotionButton = wrapper.findAll('button.emotions-buttons').at(1) happyEmotionButton.trigger('click') - expect(mutations['postsFilter/TOGGLE_EMOTION']).toHaveBeenCalledWith({}, 'happy') + expect(mutations['posts/TOGGLE_EMOTION']).toHaveBeenCalledWith({}, 'happy') }) it('sets the attribute `src` to colorized image', () => { - getters['postsFilter/filteredByEmotions'] = jest.fn(() => ['happy']) + getters['posts/filteredByEmotions'] = jest.fn(() => ['happy']) const wrapper = openFilterPosts() happyEmotionButton = wrapper.findAll('button.emotions-buttons').at(1) const happyEmotionButtonImage = happyEmotionButton.find('img') diff --git a/webapp/components/FilterPosts/FilterPosts.vue b/webapp/components/FilterPosts/FilterPosts.vue index 8a12ac633..58f0794d2 100644 --- a/webapp/components/FilterPosts/FilterPosts.vue +++ b/webapp/components/FilterPosts/FilterPosts.vue @@ -39,7 +39,7 @@ export default { computed: { ...mapGetters({ currentUser: 'auth/user', - filterActive: 'postsFilter/isActive', + filterActive: 'posts/isActive', }), chunk() { return chunk(this.categories, 2) diff --git a/webapp/components/FilterPosts/GeneralFilterMenuItems.vue b/webapp/components/FilterPosts/GeneralFilterMenuItems.vue index 0c8db9d22..96b050713 100644 --- a/webapp/components/FilterPosts/GeneralFilterMenuItems.vue +++ b/webapp/components/FilterPosts/GeneralFilterMenuItems.vue @@ -68,14 +68,14 @@ export default { }, computed: { ...mapGetters({ - filteredByUsersFollowed: 'postsFilter/filteredByUsersFollowed', - filteredByEmotions: 'postsFilter/filteredByEmotions', + filteredByUsersFollowed: 'posts/filteredByUsersFollowed', + filteredByEmotions: 'posts/filteredByEmotions', }), }, methods: { ...mapMutations({ - toggleFilteredByFollowed: 'postsFilter/TOGGLE_FILTER_BY_FOLLOWED', - toogleFilteredByEmotions: 'postsFilter/TOGGLE_EMOTION', + toggleFilteredByFollowed: 'posts/TOGGLE_FILTER_BY_FOLLOWED', + toogleFilteredByEmotions: 'posts/TOGGLE_EMOTION', }), iconPath(emotion) { if (this.filteredByEmotions.includes(emotion)) { diff --git a/webapp/locales/de.json b/webapp/locales/de.json index 9f10d929d..7ba85ddab 100644 --- a/webapp/locales/de.json +++ b/webapp/locales/de.json @@ -50,6 +50,18 @@ } } }, + "store": { + "posts": { + "orderBy": { + "newest": { + "label": "Neueste" + }, + "oldest": { + "label": "Älteste" + } + } + } + }, "maintenance": { "title": "Human Connection befindet sich in der Wartung", "explanation": "Zurzeit führen wir einige geplante Wartungsarbeiten durch, bitte versuch es später erneut.", @@ -95,10 +107,6 @@ "code-of-conduct": "Verhaltenscodex", "back-to-login": "Zurück zur Anmeldung" }, - "sorting": { - "newest": "Neueste", - "oldest": "Älteste" - }, "login": { "copy": "Wenn Du bereits ein Konto bei Human Connection hast, melde Dich bitte hier an.", "login": "Einloggen", diff --git a/webapp/locales/en.json b/webapp/locales/en.json index 9860aa457..e752aa850 100644 --- a/webapp/locales/en.json +++ b/webapp/locales/en.json @@ -51,6 +51,18 @@ } } }, + "store": { + "posts": { + "orderBy": { + "newest": { + "label": "Newest" + }, + "oldest": { + "label": "Oldest" + } + } + } + }, "maintenance": { "title": "Human Connection is under maintenance", "explanation": "At the moment we are doing some scheduled maintenance, please try again later.", @@ -96,10 +108,6 @@ "code-of-conduct": "Code of Conduct", "back-to-login": "Back to login page" }, - "sorting": { - "newest": "Newest", - "oldest": "Oldest" - }, "login": { "copy": "If you already have a human-connection account, please login.", "login": "Login", diff --git a/webapp/pages/index.spec.js b/webapp/pages/index.spec.js index 5e38897c1..0433957bb 100644 --- a/webapp/pages/index.spec.js +++ b/webapp/pages/index.spec.js @@ -24,15 +24,37 @@ describe('PostIndex', () => { let Wrapper let store let mocks + let mutations beforeEach(() => { + mutations = { + 'posts/SELECT_ORDER': jest.fn(), + } store = new Vuex.Store({ getters: { - 'postsFilter/postsFilter': () => ({}), + 'posts/filter': () => ({}), + 'posts/orderOptions': () => () => [ + { + key: 'store.posts.orderBy.oldest.label', + label: 'store.posts.orderBy.oldest.label', + icon: 'sort-amount-asc', + value: 'createdAt_asc', + }, + { + key: 'store.posts.orderBy.newest.label', + label: 'store.posts.orderBy.newest.label', + icon: 'sort-amount-desc', + value: 'createdAt_desc', + }, + ], + 'posts/selectedOrder': () => () => 'createdAt_desc', + 'posts/orderIcon': () => 'sort-amount-desc', + 'posts/orderBy': () => 'createdAt_desc', 'auth/user': () => { return { id: 'u23' } }, }, + mutations, }) mocks = { $t: key => key, @@ -103,12 +125,12 @@ describe('PostIndex', () => { }) }) - it('sets the post in the store when there are posts', () => { + it('calls store when using order by menu', () => { wrapper .findAll('li') .at(0) .trigger('click') - expect(wrapper.vm.sorting).toEqual('createdAt_desc') + expect(mutations['posts/SELECT_ORDER']).toHaveBeenCalledWith({}, 'createdAt_asc') }) it('updates offset when a user clicks on the load more button', () => { diff --git a/webapp/pages/index.vue b/webapp/pages/index.vue index 2443bc037..ec3b02e4b 100644 --- a/webapp/pages/index.vue +++ b/webapp/pages/index.vue @@ -10,8 +10,7 @@ v-model="selected" :options="sortingOptions" size="large" - v-bind:icon-right="sortingIcon" - @input="updateOrder" + :icon-right="sortingIcon" > @@ -83,34 +82,29 @@ export default { offset: 0, pageSize: 12, hashtag, - sortingIcon: 'sort-amount-desc', - selected: this.$t('sorting.newest'), - sortingOptions: [ - { - label: this.$t('sorting.newest'), - value: 'Newest', - icons: 'sort-amount-desc', - order: 'createdAt_desc', - }, - { - label: this.$t('sorting.oldest'), - value: 'Oldest', - icons: 'sort-amount-asc', - order: 'createdAt_asc', - }, - ], - } - }, - mounted() { - if(this.postsOrder.label) { - this.selected = this.postsOrder.label } }, computed: { ...mapGetters({ - postsFilter: 'postsFilter/postsFilter', - postsOrder: 'postsFilter/postsOrder', + postsFilter: 'posts/filter', + orderOptions: 'posts/orderOptions', + orderBy: 'posts/orderBy', + selectedOrder: 'posts/selectedOrder', + sortingIcon: 'posts/orderIcon', }), + selected: { + get() { + return this.selectedOrder(this) + }, + set({ value }) { + this.offset = 0 + this.posts = [] + this.selectOrder(value) + }, + }, + sortingOptions() { + return this.orderOptions(this) + }, finalFilters() { let filter = this.postsFilter if (this.hashtag) { @@ -127,15 +121,8 @@ export default { }, methods: { ...mapMutations({ - setPostsOrder: 'postsFilter/UPDATE_ORDER', + selectOrder: 'posts/SELECT_ORDER', }), - updateOrder(sortingOptions) { - this.offset = 0 - this.posts = [] - this.sortingIcon = sortingOptions.icons - this.selected = sortingOptions.label - this.setPostsOrder(sortingOptions) - }, clearSearch() { this.$router.push({ path: '/' }) this.hashtag = null @@ -156,7 +143,7 @@ export default { offset: this.offset, filter: this.finalFilters, first: this.pageSize, - orderBy: this.sorting, + orderBy: this.orderBy, }, updateQuery: (previousResult, { fetchMoreResult }) => { if (!fetchMoreResult || fetchMoreResult.Post.length < this.pageSize) { @@ -184,7 +171,7 @@ export default { return { filter: this.finalFilters, first: this.pageSize, - orderBy: this.postsOrder.order, + orderBy: this.orderBy, offset: 0, } }, diff --git a/webapp/store/postsFilter.js b/webapp/store/posts.js similarity index 69% rename from webapp/store/postsFilter.js rename to webapp/store/posts.js index 8bdf1a238..97c0e1245 100644 --- a/webapp/store/postsFilter.js +++ b/webapp/store/posts.js @@ -7,17 +7,25 @@ import clone from 'lodash/clone' const defaultFilter = {} +const orderOptions = { + createdAt_asc: { + value: 'createdAt_asc', + key: 'store.posts.orderBy.oldest.label', + icon: 'sort-amount-asc', + }, + createdAt_desc: { + value: 'createdAt_desc', + key: 'store.posts.orderBy.newest.label', + icon: 'sort-amount-desc', + }, +} + export const state = () => { return { filter: { ...defaultFilter, }, - postsOrder: { - label: null, - value: 'Newest', - icons: 'sort-amount-desc', - order: 'createdAt_desc', - } + order: orderOptions['createdAt_desc'], } } @@ -52,16 +60,16 @@ export const mutations = { if (isEmpty(get(filter, 'emotions_some.emotion_in'))) delete filter.emotions_some state.filter = filter }, - UPDATE_ORDER(state, postsOrder) { - state.postsOrder = postsOrder - } + SELECT_ORDER(state, value) { + state.order = orderOptions[value] + }, } export const getters = { isActive(state) { return !isEqual(state.filter, defaultFilter) }, - postsFilter(state) { + filter(state) { return state.filter }, filteredCategoryIds(state) { @@ -73,7 +81,23 @@ export const getters = { filteredByEmotions(state) { return get(state.filter, 'emotions_some.emotion_in') || [] }, - postsOrder(state) { - return state.postsOrder - } + orderOptions: state => ({ $t }) => + Object.values(orderOptions).map(option => { + return { + ...option, + label: $t(option.key), + } + }), + selectedOrder: state => ({ $t }) => { + return { + ...state.order, + label: $t(state.order.key), + } + }, + orderBy(state) { + return state.order.value + }, + orderIcon(state) { + return state.order.icon + }, } diff --git a/webapp/store/postsFilter.spec.js b/webapp/store/posts.spec.js similarity index 63% rename from webapp/store/postsFilter.spec.js rename to webapp/store/posts.spec.js index 68a3dbd6e..536c4c924 100644 --- a/webapp/store/postsFilter.spec.js +++ b/webapp/store/posts.spec.js @@ -1,7 +1,7 @@ -import { getters, mutations } from './postsFilter.js' +import { getters, mutations } from './posts.js' let state -let testAction +let testMutation describe('getters', () => { describe('isActive', () => { @@ -25,10 +25,10 @@ describe('getters', () => { }) }) - describe('postsFilter', () => { + describe('filter', () => { it('returns filter', () => { state = { filter: { author: { followedBy_some: { id: 7 } } } } - expect(getters.postsFilter(state)).toEqual({ author: { followedBy_some: { id: 7 } } }) + expect(getters.filter(state)).toEqual({ author: { followedBy_some: { id: 7 } } }) }) }) @@ -67,14 +67,48 @@ describe('getters', () => { expect(getters.filteredByEmotions(state)).toEqual([]) }) }) + + describe('orderByOptions', () => { + it('returns all options regardless of current state', () => { + const $t = jest.fn(t => t) + expect(getters.orderOptions()({ $t })).toEqual([ + { + key: 'store.posts.orderBy.oldest.label', + label: 'store.posts.orderBy.oldest.label', + icon: 'sort-amount-asc', + value: 'createdAt_asc', + }, + { + key: 'store.posts.orderBy.newest.label', + label: 'store.posts.orderBy.newest.label', + icon: 'sort-amount-desc', + value: 'createdAt_desc', + }, + ]) + }) + }) + + describe('orderBy', () => { + it('returns value for graphql query', () => { + state = { + order: { + key: 'store.posts.orderBy.newest.label', + label: 'store.posts.orderBy.newest.label', + icon: 'sort-amount-desc', + value: 'createdAt_desc', + }, + } + expect(getters.orderBy(state)).toEqual('createdAt_desc') + }) + }) }) describe('mutations', () => { describe('RESET_CATEGORIES', () => { beforeEach(() => { - testAction = categoryId => { + testMutation = categoryId => { mutations.RESET_CATEGORIES(state, categoryId) - return getters.postsFilter(state) + return getters.filter(state) } }) it('resets the categories filter', () => { @@ -84,37 +118,37 @@ describe('mutations', () => { categories_some: { id_in: [23] }, }, } - expect(testAction(23)).toEqual({ author: { followedBy_some: { id: 7 } } }) + expect(testMutation(23)).toEqual({ author: { followedBy_some: { id: 7 } } }) }) }) describe('TOGGLE_CATEGORY', () => { beforeEach(() => { - testAction = categoryId => { + testMutation = categoryId => { mutations.TOGGLE_CATEGORY(state, categoryId) - return getters.postsFilter(state) + return getters.filter(state) } }) it('creates category filter if empty', () => { state = { filter: {} } - expect(testAction(23)).toEqual({ categories_some: { id_in: [23] } }) + expect(testMutation(23)).toEqual({ categories_some: { id_in: [23] } }) }) it('adds category id not present', () => { state = { filter: { categories_some: { id_in: [24] } } } - expect(testAction(23)).toEqual({ categories_some: { id_in: [24, 23] } }) + expect(testMutation(23)).toEqual({ categories_some: { id_in: [24, 23] } }) }) it('removes category id if present', () => { state = { filter: { categories_some: { id_in: [23, 24] } } } - const result = testAction(23) + const result = testMutation(23) expect(result).toEqual({ categories_some: { id_in: [24] } }) }) it('removes category filter if empty', () => { state = { filter: { categories_some: { id_in: [23] } } } - expect(testAction(23)).toEqual({}) + expect(testMutation(23)).toEqual({}) }) it('does not get in the way of other filters', () => { @@ -124,15 +158,15 @@ describe('mutations', () => { categories_some: { id_in: [23] }, }, } - expect(testAction(23)).toEqual({ author: { followedBy_some: { id: 7 } } }) + expect(testMutation(23)).toEqual({ author: { followedBy_some: { id: 7 } } }) }) }) describe('TOGGLE_FILTER_BY_FOLLOWED', () => { beforeEach(() => { - testAction = userId => { + testMutation = userId => { mutations.TOGGLE_FILTER_BY_FOLLOWED(state, userId) - return getters.postsFilter(state) + return getters.filter(state) } }) @@ -142,7 +176,7 @@ describe('mutations', () => { }) it('attaches the id of the current user to the filter object', () => { - expect(testAction(4711)).toEqual({ author: { followedBy_some: { id: 4711 } } }) + expect(testMutation(4711)).toEqual({ author: { followedBy_some: { id: 4711 } } }) }) }) @@ -152,8 +186,23 @@ describe('mutations', () => { }) it('remove the id of the current user from the filter object', () => { - expect(testAction(4711)).toEqual({}) + expect(testMutation(4711)).toEqual({}) }) }) }) + + describe('SELECT_ORDER', () => { + beforeEach(() => { + testMutation = key => { + mutations.SELECT_ORDER(state, key) + return getters.orderBy(state) + } + }) + it('switches the currently selected order', () => { + state = { + // does not matter + } + expect(testMutation('createdAt_asc')).toEqual('createdAt_asc') + }) + }) })