diff options
Diffstat (limited to 'src/client/react/reducers')
-rw-r--r-- | src/client/react/reducers/search.js | 109 | ||||
-rw-r--r-- | src/client/react/reducers/search.test.js | 198 | ||||
-rw-r--r-- | src/client/react/reducers/view.js | 73 |
3 files changed, 0 insertions, 380 deletions
diff --git a/src/client/react/reducers/search.js b/src/client/react/reducers/search.js deleted file mode 100644 index dcc7ec6..0000000 --- a/src/client/react/reducers/search.js +++ /dev/null @@ -1,109 +0,0 @@ -/** - * Copyright (C) 2018 Noah Loomans - * - * This file is part of rooster.hetmml.nl. - * - * rooster.hetmml.nl is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * rooster.hetmml.nl is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with rooster.hetmml.nl. If not, see <http://www.gnu.org/licenses/>. - * - */ - -import FuzzySearch from 'fuzzy-search'; -import uniqBy from 'lodash/uniqBy'; -import users from '../users'; - -const DEFAULT_STATE = { - // results: [ - // 's/18562', - // ], - results: [], - searchText: '', - selectedResult: null, -}; - -function getSearchResults(allUsers, query) { - const searcher = new FuzzySearch(allUsers, ['value', 'alt']); - - if (query.trim() === '') { - return []; - } - - const allResults = searcher.search(query); - const uniqResults = uniqBy(allResults, result => result.id); - const firstResults = uniqResults.splice(0, 4); - - const userIds = firstResults.map(result => result.id); - - return userIds; -} - -const search = (state = DEFAULT_STATE, action) => { - switch (action.type) { - case 'SEARCH/SET_USER': { - const { user } = action; - - if (user == null) { - return DEFAULT_STATE; - } - - return { - ...state, - results: [], - searchText: users.byId[user].value, - selectedResult: user, - }; - } - - case 'SEARCH/INPUT_CHANGE': - return { - ...state, - results: getSearchResults(users.allUsers, action.searchText), - searchText: action.searchText, - selectedResult: null, - }; - - case 'SEARCH/CHANGE_SELECTED_RESULT': { - const { results } = state; - - const prevSelectedResult = state.selectedResult; - const prevSelectedResultIndex = results.indexOf(prevSelectedResult); - let nextSelectedResultIndex = - prevSelectedResultIndex + action.relativeChange; - - if (nextSelectedResultIndex < -1) { - nextSelectedResultIndex = results.length - 1; - } else if (nextSelectedResultIndex > results.length - 1) { - nextSelectedResultIndex = -1; - } - - const nextSelectedResult = - nextSelectedResultIndex === -1 - ? null - : results[nextSelectedResultIndex]; - - return { - ...state, - selectedResult: nextSelectedResult, - }; - } - - default: - return state; - } -}; - -export default search; - -export const _test = { - DEFAULT_STATE, -}; diff --git a/src/client/react/reducers/search.test.js b/src/client/react/reducers/search.test.js deleted file mode 100644 index 48ca05a..0000000 --- a/src/client/react/reducers/search.test.js +++ /dev/null @@ -1,198 +0,0 @@ -/** - * Copyright (C) 2018 Noah Loomans - * - * This file is part of rooster.hetmml.nl. - * - * rooster.hetmml.nl is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * rooster.hetmml.nl is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with rooster.hetmml.nl. If not, see <http://www.gnu.org/licenses/>. - * - */ - -window.USERS = [ - { type: 's', value: '18561' }, - { type: 's', value: '18562' }, - { type: 's', value: '18563' }, - { type: 's', value: '18564' }, - { type: 's', value: '18565' }, - { type: 's', value: '18566' }, - { type: 's', value: '18567' }, - { type: 's', value: '18568' }, - { type: 's', value: '18569' }, -]; - -const deepFreeze = require('deep-freeze'); -const search = require('./search').default; -const { _test } = require('./search'); - -describe('reducers', () => { - describe('search', () => { - describe('SEARCH/SET_USER', () => { - it('Resets to the default state if the user is null', () => { - expect(search({ foo: 'bar' }, { type: 'SEARCH/SET_USER', user: null })).toEqual(_test.DEFAULT_STATE); - }); - - it('Sets all the values of that user properly', () => { - expect(search(undefined, { type: 'SEARCH/SET_USER', user: 's/18561' })).toEqual({ - results: [], - searchText: '18561', - selectedResult: 's/18561', - }); - }); - }); - - describe('SEARCH/INPUT_CHANGE', () => { - it('Returns no results when nothing is typed in', () => { - expect(search(undefined, { type: 'SEARCH/INPUT_CHANGE', searchText: '' })).toEqual({ - results: [], - searchText: '', - selectedResult: null, - }); - }); - - it('Returns no results when a space is typed in', () => { - expect(search(undefined, { type: 'SEARCH/INPUT_CHANGE', searchText: ' ' })).toEqual({ - results: [], - searchText: ' ', - selectedResult: null, - }); - }); - - it('Preforms a basic search, only returning four results', () => { - expect(search(undefined, { type: 'SEARCH/INPUT_CHANGE', searchText: '18' })).toEqual({ - results: [ - 's/18561', - 's/18562', - 's/18563', - 's/18564', - ], - searchText: '18', - selectedResult: null, - }); - }); - }); - - describe('SEARCH/CHANGE_SELECTED_RESULT', () => { - it('Does nothing when there are no results', () => { - const prevState = { - results: [], - searchText: '', - selectedResult: null, - }; - - const actionPlus = { type: 'SEARCH/CHANGE_SELECTED_RESULT', relativeChange: +1 }; - const actionMin = { type: 'SEARCH/CHANGE_SELECTED_RESULT', relativeChange: -1 }; - - deepFreeze([prevState, actionPlus, actionMin]); - - const nextStatePlus = search(prevState, actionPlus); - const nextStateMin = search(prevState, actionMin); - expect(nextStatePlus).toEqual(prevState); - expect(nextStateMin).toEqual(prevState); - }); - - it('Switches to the correct selectedResult when no selected result is selected', () => { - const prevState = { - results: ['s/18561', 's/18562', 's/18563'], - searchText: '1856', - selectedResult: null, - }; - - const actionPlus = { type: 'SEARCH/CHANGE_SELECTED_RESULT', relativeChange: +1 }; - const actionMin = { type: 'SEARCH/CHANGE_SELECTED_RESULT', relativeChange: -1 }; - - deepFreeze([prevState, actionPlus, actionMin]); - - const nextStatePlus = search(prevState, actionPlus); - const nextStateMin = search(prevState, actionMin); - - expect(nextStatePlus).toEqual({ - ...prevState, - selectedResult: 's/18561', - }); - expect(nextStateMin).toEqual({ - ...prevState, - selectedResult: 's/18563', - }); - }); - - it('Switches to the correct selectedResult when there is a selected result selected', () => { - const prevState = { - results: ['s/18561', 's/18562', 's/18563'], - searchText: '1856', - selectedResult: 's/18562', - }; - - const actionPlus = { type: 'SEARCH/CHANGE_SELECTED_RESULT', relativeChange: +1 }; - const actionMin = { type: 'SEARCH/CHANGE_SELECTED_RESULT', relativeChange: -1 }; - - deepFreeze([prevState, actionPlus, actionMin]); - - const nextStatePlus = search(prevState, actionPlus); - const nextStateMin = search(prevState, actionMin); - - expect(nextStatePlus).toEqual({ - ...prevState, - selectedResult: 's/18563', - }); - expect(nextStateMin).toEqual({ - ...prevState, - selectedResult: 's/18561', - }); - }); - - it('Properly wraps around when incrementing', () => { - expect(search({ - results: ['s/18561', 's/18562', 's/18563'], - searchText: '1856', - selectedResult: 's/18563', - }, { type: 'SEARCH/CHANGE_SELECTED_RESULT', relativeChange: +1 })).toEqual({ - results: ['s/18561', 's/18562', 's/18563'], - searchText: '1856', - selectedResult: null, - }); - - expect(search({ - results: ['s/18561', 's/18562', 's/18563'], - searchText: '1856', - selectedResult: null, - }, { type: 'SEARCH/CHANGE_SELECTED_RESULT', relativeChange: +1 })).toEqual({ - results: ['s/18561', 's/18562', 's/18563'], - searchText: '1856', - selectedResult: 's/18561', - }); - }); - - it('Properly wraps around when decrementing', () => { - expect(search({ - results: ['s/18561', 's/18562', 's/18563'], - searchText: '1856', - selectedResult: 's/18561', - }, { type: 'SEARCH/CHANGE_SELECTED_RESULT', relativeChange: -1 })).toEqual({ - results: ['s/18561', 's/18562', 's/18563'], - searchText: '1856', - selectedResult: null, - }); - - expect(search({ - results: ['s/18561', 's/18562', 's/18563'], - searchText: '1856', - selectedResult: null, - }, { type: 'SEARCH/CHANGE_SELECTED_RESULT', relativeChange: -1 })).toEqual({ - results: ['s/18561', 's/18562', 's/18563'], - searchText: '1856', - selectedResult: 's/18563', - }); - }); - }); - }); -}); diff --git a/src/client/react/reducers/view.js b/src/client/react/reducers/view.js deleted file mode 100644 index 8fa56b8..0000000 --- a/src/client/react/reducers/view.js +++ /dev/null @@ -1,73 +0,0 @@ -/** - * Copyright (C) 2018 Noah Loomans - * - * This file is part of rooster.hetmml.nl. - * - * rooster.hetmml.nl is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * rooster.hetmml.nl is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with rooster.hetmml.nl. If not, see <http://www.gnu.org/licenses/>. - * - */ - -const schedule = (state = {}, action) => { - switch (action.type) { - case 'VIEW/FETCH_SCHEDULE_REQUEST': - return { - ...state, - state: 'FETCHING', - }; - case 'VIEW/FETCH_SCHEDULE_SUCCESS': - return { - ...state, - state: 'FINISHED', - htmlStr: action.htmlStr, - }; - default: - return state; - } -}; - -const DEFAULT_STATE = { - schedules: {}, -}; - -const view = (state = DEFAULT_STATE, action) => { - switch (action.type) { - case 'VIEW/FETCH_SCHEDULE_REQUEST': - case 'VIEW/FETCH_SCHEDULE_SUCCESS': - return { - ...state, - schedules: { - ...state.schedules, - [action.user]: - state.schedules[action.user] - ? { - // This user already exists in our state, extend it. - ...state.schedules[action.user], - [action.week]: schedule(state.schedules[action.user][action.week], action), - } - : { - // This user does not already exist in our state. - [action.week]: schedule(undefined, action), - }, - }, - }; - default: - return state; - } -}; - -export default view; - -export const _test = { - DEFAULT_STATE, -}; |