diff --git a/webapp/store/postsFilter.js b/webapp/store/postsFilter.js new file mode 100644 index 000000000..682c658c1 --- /dev/null +++ b/webapp/store/postsFilter.js @@ -0,0 +1,50 @@ +import get from 'lodash/get' +import update from 'lodash/update' +import xor from 'lodash/xor' +import isEmpty from 'lodash/isEmpty' +import clone from 'lodash/clone' + +export const state = () => { + return { + filter: {}, + } +} + +export const mutations = { + TOGGLE_FILTER_BY_FOLLOWED(state, currentUserId) { + const filter = clone(state.filter) + const id = get(filter, 'author.followedBy_some.id') + if (id) { + delete filter.author + state.filter = filter + } else { + state.filter = { + ...filter, + author: { followedBy_some: { id: currentUserId } }, + } + } + }, + RESET_CATEGORIES(state) { + const filter = clone(state.filter) + delete filter.categories_some + state.filter = filter + }, + TOGGLE_CATEGORY(state, categoryId) { + const filter = clone(state.filter) + update(filter, 'categories_some.id_in', categoryIds => xor(categoryIds, [categoryId])) + if (isEmpty(get(filter, 'categories_some.id_in'))) delete filter.categories_some + state.filter = filter + }, +} + +export const getters = { + postsFilter(state) { + return state.filter + }, + filteredCategoryIds(state) { + return get(state.filter, 'categories_some.id_in') || [] + }, + filteredByUsersFollowed(state) { + return !!get(state.filter, 'author.followedBy_some.id') + }, +} diff --git a/webapp/store/postsFilter.spec.js b/webapp/store/postsFilter.spec.js new file mode 100644 index 000000000..46b5f075c --- /dev/null +++ b/webapp/store/postsFilter.spec.js @@ -0,0 +1,126 @@ +import { getters, mutations } from './postsFilter.js' + +let state +let testAction + +describe('getters', () => { + describe('filteredCategoryIds', () => { + it('returns category ids if filter is set', () => { + state = { filter: { categories_some: { id_in: [24] } } } + expect(getters.filteredCategoryIds(state)).toEqual([24]) + }) + + it('returns empty array if filter is not set', () => { + state = { filter: { author: { followedBy_some: { id: 7 } } } } + expect(getters.filteredCategoryIds(state)).toEqual([]) + }) + }) + + describe('postsFilter', () => { + it('returns filter', () => { + state = { filter: { author: { followedBy_some: { id: 7 } } } } + expect(getters.postsFilter(state)).toEqual({ author: { followedBy_some: { id: 7 } } }) + }) + }) + + describe('filteredByUsersFollowed', () => { + it('returns true if filter is set', () => { + state = { filter: { author: { followedBy_some: { id: 7 } } } } + expect(getters.filteredByUsersFollowed(state)).toBe(true) + }) + + it('returns false if filter is not set', () => { + state = { filter: { categories_some: { id_in: [23] } } } + expect(getters.filteredByUsersFollowed(state)).toBe(false) + }) + }) +}) + +describe('mutations', () => { + describe('RESET_CATEGORIES', () => { + beforeEach(() => { + testAction = categoryId => { + mutations.RESET_CATEGORIES(state, categoryId) + return getters.postsFilter(state) + } + }) + it('resets the categories filter', () => { + state = { + filter: { + author: { followedBy_some: { id: 7 } }, + categories_some: { id_in: [23] }, + }, + } + expect(testAction(23)).toEqual({ author: { followedBy_some: { id: 7 } } }) + }) + }) + + describe('TOGGLE_CATEGORY', () => { + beforeEach(() => { + testAction = categoryId => { + mutations.TOGGLE_CATEGORY(state, categoryId) + return getters.postsFilter(state) + } + }) + + it('creates category filter if empty', () => { + state = { filter: {} } + expect(testAction(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] } }) + }) + + it('removes category id if present', () => { + state = { filter: { categories_some: { id_in: [23, 24] } } } + const result = testAction(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({}) + }) + + it('does not get in the way of other filters', () => { + state = { + filter: { + author: { followedBy_some: { id: 7 } }, + categories_some: { id_in: [23] }, + }, + } + expect(testAction(23)).toEqual({ author: { followedBy_some: { id: 7 } } }) + }) + }) + + describe('TOGGLE_FILTER_BY_FOLLOWED', () => { + beforeEach(() => { + testAction = userId => { + mutations.TOGGLE_FILTER_BY_FOLLOWED(state, userId) + return getters.postsFilter(state) + } + }) + + describe('given empty filter', () => { + beforeEach(() => { + state = { filter: {} } + }) + + it('attaches the id of the current user to the filter object', () => { + expect(testAction(4711)).toEqual({ author: { followedBy_some: { id: 4711 } } }) + }) + }) + + describe('already filtered', () => { + beforeEach(() => { + state = { filter: { author: { followedBy_some: { id: 4711 } } } } + }) + + it('remove the id of the current user from the filter object', () => { + expect(testAction(4711)).toEqual({}) + }) + }) + }) +})