From 1ffde6bf1034d1a1d9b7bca62fe66fe64527314c Mon Sep 17 00:00:00 2001 From: Alina Beck Date: Wed, 11 Mar 2020 16:43:13 +0100 Subject: [PATCH] refactor: CategoriesFilter to not use ds-flex Co-authored-by: mattwr18 - introduce LabeledButton component - rename FilterMenu to HashtagsFilter and FilterPosts to FilterMenu --- webapp/assets/_new/styles/resets.scss | 7 + .../FilterMenu/CategoriesFilter.vue | 125 +++++++++++++ .../components/FilterMenu/FilterMenu.spec.js | 164 ++++++++++++++--- webapp/components/FilterMenu/FilterMenu.vue | 64 ++++--- .../GeneralFilter.vue} | 18 +- .../LanguageFilter.vue} | 9 +- .../FilterPosts/CategoriesFilterMenuItems.vue | 103 ----------- .../FilterPosts/FilterPosts.spec.js | 167 ------------------ webapp/components/FilterPosts/FilterPosts.vue | 52 ------ .../HashtagsFilter/HashtagsFilter.spec.js | 43 +++++ .../HashtagsFilter/HashtagsFilter.vue | 36 ++++ .../generic/LabeledButton/LabeledButton.vue | 40 +++++ webapp/layouts/default.vue | 28 +-- webapp/locales/de.json | 4 +- webapp/locales/en.json | 4 +- webapp/locales/es.json | 4 +- webapp/locales/fr.json | 4 +- webapp/locales/it.json | 4 +- webapp/locales/pl.json | 2 +- webapp/locales/pt.json | 4 +- webapp/locales/ru.json | 4 +- webapp/pages/index.spec.js | 4 +- webapp/pages/index.vue | 6 +- 23 files changed, 467 insertions(+), 429 deletions(-) create mode 100644 webapp/components/FilterMenu/CategoriesFilter.vue rename webapp/components/{FilterPosts/GeneralFilterMenuItems.vue => FilterMenu/GeneralFilter.vue} (83%) rename webapp/components/{FilterPosts/LanguageFilterMenuItems.vue => FilterMenu/LanguageFilter.vue} (90%) delete mode 100644 webapp/components/FilterPosts/CategoriesFilterMenuItems.vue delete mode 100644 webapp/components/FilterPosts/FilterPosts.spec.js delete mode 100644 webapp/components/FilterPosts/FilterPosts.vue create mode 100644 webapp/components/HashtagsFilter/HashtagsFilter.spec.js create mode 100644 webapp/components/HashtagsFilter/HashtagsFilter.vue create mode 100644 webapp/components/_new/generic/LabeledButton/LabeledButton.vue diff --git a/webapp/assets/_new/styles/resets.scss b/webapp/assets/_new/styles/resets.scss index 144f22d10..72a6184b3 100644 --- a/webapp/assets/_new/styles/resets.scss +++ b/webapp/assets/_new/styles/resets.scss @@ -19,3 +19,10 @@ h6, p { margin: 0; } + +ul, +ol { + list-style-type: none; + padding: 0; + margin: 0; +} diff --git a/webapp/components/FilterMenu/CategoriesFilter.vue b/webapp/components/FilterMenu/CategoriesFilter.vue new file mode 100644 index 000000000..f9474dc57 --- /dev/null +++ b/webapp/components/FilterMenu/CategoriesFilter.vue @@ -0,0 +1,125 @@ + + + + + diff --git a/webapp/components/FilterMenu/FilterMenu.spec.js b/webapp/components/FilterMenu/FilterMenu.spec.js index 283db979e..ec94e8ea5 100644 --- a/webapp/components/FilterMenu/FilterMenu.spec.js +++ b/webapp/components/FilterMenu/FilterMenu.spec.js @@ -1,42 +1,166 @@ import { mount } from '@vue/test-utils' + +import Vuex from 'vuex' import FilterMenu from './FilterMenu.vue' +import locales from '~/locales' +import orderBy from 'lodash/orderBy' const localVue = global.localVue +let mutations +let getters + +const languages = orderBy(locales, 'name') + describe('FilterMenu.vue', () => { - let wrapper let mocks let propsData + let menuToggle + let allCategoriesButton + let environmentAndNatureButton + let democracyAndPoliticsButton + let happyEmotionButton + let englishButton + let spanishButton beforeEach(() => { - mocks = { $t: () => {} } + mocks = { + $apollo: { + query: jest + .fn() + .mockResolvedValueOnce({ + data: { Post: { title: 'Post with Category', category: [{ id: 'cat4' }] } }, + }) + .mockRejectedValue({ message: 'We were unable to filter' }), + }, + $t: jest.fn(), + $i18n: { + locale: () => 'en', + }, + $toast: { + error: jest.fn(), + }, + } + propsData = { + categories: [ + { id: 'cat4', name: 'Environment & Nature', icon: 'tree' }, + { id: 'cat15', name: 'Consumption & Sustainability', icon: 'shopping-cart' }, + { id: 'cat9', name: 'Democracy & Politics', icon: 'university' }, + ], + } }) - describe('given a hashtag', () => { - beforeEach(() => { - propsData = { - hashtag: 'Frieden', - } + describe('mount', () => { + mutations = { + 'posts/TOGGLE_FILTER_BY_FOLLOWED': jest.fn(), + 'posts/RESET_CATEGORIES': jest.fn(), + 'posts/TOGGLE_CATEGORY': jest.fn(), + 'posts/TOGGLE_EMOTION': jest.fn(), + 'posts/TOGGLE_LANGUAGE': jest.fn(), + 'posts/RESET_LANGUAGES': jest.fn(), + } + getters = { + 'posts/isActive': () => false, + 'auth/isModerator': () => false, + 'auth/user': () => { + return { id: 'u34' } + }, + 'posts/filteredCategoryIds': jest.fn(() => []), + 'posts/filteredByUsersFollowed': jest.fn(), + 'posts/filteredByEmotions': jest.fn(() => []), + 'posts/filteredLanguageCodes': jest.fn(() => []), + } + const openFilterMenu = () => { + const store = new Vuex.Store({ mutations, getters }) + const wrapper = mount(FilterMenu, { mocks, localVue, propsData, store }) + menuToggle = wrapper.findAll('button').at(0) + menuToggle.trigger('click') + return wrapper + } + + it('groups the categories by pair', () => { + const wrapper = openFilterMenu() + expect(wrapper.vm.chunk).toEqual([ + [ + { id: 'cat4', name: 'Environment & Nature', icon: 'tree' }, + { id: 'cat15', name: 'Consumption & Sustainability', icon: 'shopping-cart' }, + ], + [{ id: 'cat9', name: 'Democracy & Politics', icon: 'university' }], + ]) }) - describe('mount', () => { - const Wrapper = () => { - return mount(FilterMenu, { mocks, localVue, propsData }) - } + it('starts with all categories button active', () => { + const wrapper = openFilterMenu() + allCategoriesButton = wrapper.findAll('button').at(1) + expect(allCategoriesButton.attributes().class).toContain('--filled') + }) + + it('calls TOGGLE_CATEGORY when clicked', () => { + const wrapper = openFilterMenu() + environmentAndNatureButton = wrapper.findAll('button').at(2) + environmentAndNatureButton.trigger('click') + expect(mutations['posts/TOGGLE_CATEGORY']).toHaveBeenCalledWith({}, 'cat4') + }) + + it('calls TOGGLE_LANGUAGE when clicked', () => { + const wrapper = openFilterMenu() + englishButton = wrapper + .findAll('button.language-buttons') + .at(languages.findIndex(l => l.code === 'en')) + englishButton.trigger('click') + expect(mutations['posts/TOGGLE_LANGUAGE']).toHaveBeenCalledWith({}, 'en') + }) + + it('sets category button attribute `filled` when corresponding category is filtered', () => { + getters['posts/filteredCategoryIds'] = jest.fn(() => ['cat9']) + const wrapper = openFilterMenu() + democracyAndPoliticsButton = wrapper.findAll('button').at(4) + expect(democracyAndPoliticsButton.attributes().class).toContain('--filled') + }) + + it('sets language button attribute `filled` when corresponding language is filtered', () => { + getters['posts/filteredLanguageCodes'] = jest.fn(() => ['es']) + const wrapper = openFilterMenu() + spanishButton = wrapper + .findAll('button.language-buttons') + .at(languages.findIndex(l => l.code === 'es')) + expect(spanishButton.attributes().class).toContain('--filled') + }) + + it('sets "filter-by-followed" button attribute `filled`', () => { + getters['posts/filteredByUsersFollowed'] = jest.fn(() => true) + const wrapper = openFilterMenu() + expect(wrapper.find('.base-button[data-test="filter-by-followed"]').classes('--filled')).toBe( + true, + ) + }) + + describe('click "filter-by-followed" button', () => { + let wrapper beforeEach(() => { - wrapper = Wrapper() + wrapper = openFilterMenu() + wrapper.find('.base-button[data-test="filter-by-followed"]').trigger('click') }) - it('renders a card', () => { - wrapper = Wrapper() - expect(wrapper.is('.base-card')).toBe(true) + it('calls TOGGLE_FILTER_BY_FOLLOWED', () => { + expect(mutations['posts/TOGGLE_FILTER_BY_FOLLOWED']).toHaveBeenCalledWith({}, 'u34') + }) + }) + + describe('click on an "emotions-buttons" button', () => { + it('calls TOGGLE_EMOTION when clicked', () => { + const wrapper = openFilterMenu() + happyEmotionButton = wrapper.findAll('.emotion-button .base-button').at(1) + happyEmotionButton.trigger('click') + expect(mutations['posts/TOGGLE_EMOTION']).toHaveBeenCalledWith({}, 'happy') }) - describe('click clear search button', () => { - it('emits clearSearch', () => { - wrapper.find('.base-button').trigger('click') - expect(wrapper.emitted().clearSearch).toHaveLength(1) - }) + it('sets the attribute `src` to colorized image', () => { + getters['posts/filteredByEmotions'] = jest.fn(() => ['happy']) + const wrapper = openFilterMenu() + happyEmotionButton = wrapper.findAll('.emotion-button .base-button').at(1) + const happyEmotionButtonImage = happyEmotionButton.find('img') + expect(happyEmotionButtonImage.attributes().src).toEqual('/img/svg/emoji/happy_color.svg') }) }) }) diff --git a/webapp/components/FilterMenu/FilterMenu.vue b/webapp/components/FilterMenu/FilterMenu.vue index afe6a3d7a..0cc21f04d 100644 --- a/webapp/components/FilterMenu/FilterMenu.vue +++ b/webapp/components/FilterMenu/FilterMenu.vue @@ -1,36 +1,46 @@ - - - diff --git a/webapp/components/FilterPosts/GeneralFilterMenuItems.vue b/webapp/components/FilterMenu/GeneralFilter.vue similarity index 83% rename from webapp/components/FilterPosts/GeneralFilterMenuItems.vue rename to webapp/components/FilterMenu/GeneralFilter.vue index f1cf6adae..f13e6b778 100644 --- a/webapp/components/FilterPosts/GeneralFilterMenuItems.vue +++ b/webapp/components/FilterMenu/GeneralFilter.vue @@ -1,7 +1,7 @@