diff options
Diffstat (limited to 'spec/frontend/search')
25 files changed, 518 insertions, 284 deletions
diff --git a/spec/frontend/search/mock_data.js b/spec/frontend/search/mock_data.js index 3f23803bbf6..a063f20aca6 100644 --- a/spec/frontend/search/mock_data.js +++ b/spec/frontend/search/mock_data.js @@ -884,23 +884,4 @@ export const MOCK_FILTERED_LABELS = [ }, ]; -export const MOCK_FILTERED_UNAPPLIED_SELECTED_LABELS = [ - { - key: '6', - count: 12, - title: 'Cosche', - color: '#cea786', - type: 'GroupLabel', - parent_full_name: 'Toolbox', - }, - { - key: '73', - count: 12, - title: 'Accent', - color: '#a5c6fb', - type: 'ProjectLabel', - parent_full_name: 'Toolbox / Gitlab Smoke Tests', - }, -]; - export const CURRENT_SCOPE = 'blobs'; diff --git a/spec/frontend/search/sidebar/components/app_spec.js b/spec/frontend/search/sidebar/components/app_spec.js index ba492833ec4..a4559c2dc34 100644 --- a/spec/frontend/search/sidebar/components/app_spec.js +++ b/spec/frontend/search/sidebar/components/app_spec.js @@ -1,12 +1,15 @@ import { shallowMount } from '@vue/test-utils'; import Vue from 'vue'; +// eslint-disable-next-line no-restricted-imports import Vuex from 'vuex'; import { MOCK_QUERY } from 'jest/search/mock_data'; import GlobalSearchSidebar from '~/search/sidebar/components/app.vue'; import IssuesFilters from '~/search/sidebar/components/issues_filters.vue'; +import MergeRequestsFilters from '~/search/sidebar/components/merge_requests_filters.vue'; +import BlobsFilters from '~/search/sidebar/components/blobs_filters.vue'; +import ProjectsFilters from '~/search/sidebar/components/projects_filters.vue'; import ScopeLegacyNavigation from '~/search/sidebar/components/scope_legacy_navigation.vue'; import ScopeSidebarNavigation from '~/search/sidebar/components/scope_sidebar_navigation.vue'; -import LanguageFilter from '~/search/sidebar/components/language_filter/index.vue'; Vue.use(Vuex); @@ -17,7 +20,7 @@ describe('GlobalSearchSidebar', () => { currentScope: jest.fn(() => 'issues'), }; - const createComponent = (initialState = {}, featureFlags = {}) => { + const createComponent = (initialState = {}, ff = false) => { const store = new Vuex.Store({ state: { urlQuery: MOCK_QUERY, @@ -30,17 +33,19 @@ describe('GlobalSearchSidebar', () => { store, provide: { glFeatures: { - ...featureFlags, + searchProjectsHideArchived: ff, }, }, }); }; const findSidebarSection = () => wrapper.find('section'); - const findFilters = () => wrapper.findComponent(IssuesFilters); + const findIssuesFilters = () => wrapper.findComponent(IssuesFilters); + const findMergeRequestsFilters = () => wrapper.findComponent(MergeRequestsFilters); + const findBlobsFilters = () => wrapper.findComponent(BlobsFilters); + const findProjectsFilters = () => wrapper.findComponent(ProjectsFilters); const findScopeLegacyNavigation = () => wrapper.findComponent(ScopeLegacyNavigation); const findScopeSidebarNavigation = () => wrapper.findComponent(ScopeSidebarNavigation); - const findLanguageAggregation = () => wrapper.findComponent(LanguageFilter); describe('renders properly', () => { describe('always', () => { @@ -53,23 +58,33 @@ describe('GlobalSearchSidebar', () => { }); describe.each` - scope | showFilters | showsLanguage - ${'issues'} | ${true} | ${false} - ${'merge_requests'} | ${true} | ${false} - ${'projects'} | ${false} | ${false} - ${'blobs'} | ${false} | ${true} - `('sidebar scope: $scope', ({ scope, showFilters, showsLanguage }) => { + scope | filter + ${'issues'} | ${findIssuesFilters} + ${'merge_requests'} | ${findMergeRequestsFilters} + ${'blobs'} | ${findBlobsFilters} + `('with sidebar $scope scope:', ({ scope, filter }) => { beforeEach(() => { getterSpies.currentScope = jest.fn(() => scope); createComponent({ urlQuery: { scope } }); }); - it(`${!showFilters ? "doesn't" : ''} shows filters`, () => { - expect(findFilters().exists()).toBe(showFilters); + it(`shows filter ${filter.name.replace('find', '')}`, () => { + expect(filter().exists()).toBe(true); + }); + }); + + describe.each` + featureFlag + ${false} + ${true} + `('with sidebar $scope scope:', ({ featureFlag }) => { + beforeEach(() => { + getterSpies.currentScope = jest.fn(() => 'projects'); + createComponent({ urlQuery: { scope: 'projects' } }, featureFlag); }); - it(`${!showsLanguage ? "doesn't" : ''} shows language filters`, () => { - expect(findLanguageAggregation().exists()).toBe(showsLanguage); + it(`shows filter ProjectsFilters}`, () => { + expect(findProjectsFilters().exists()).toBe(featureFlag); }); }); diff --git a/spec/frontend/search/sidebar/components/archived_filter_spec.js b/spec/frontend/search/sidebar/components/archived_filter_spec.js new file mode 100644 index 00000000000..69bf2ebd72e --- /dev/null +++ b/spec/frontend/search/sidebar/components/archived_filter_spec.js @@ -0,0 +1,73 @@ +import { shallowMount } from '@vue/test-utils'; +import Vue from 'vue'; +// eslint-disable-next-line no-restricted-imports +import Vuex from 'vuex'; +import { GlFormCheckboxGroup } from '@gitlab/ui'; +import ArchivedFilter from '~/search/sidebar/components/archived_filter/index.vue'; + +import { archivedFilterData } from '~/search/sidebar/components/archived_filter/data'; + +Vue.use(Vuex); + +describe('ArchivedFilter', () => { + let wrapper; + + const createComponent = (state) => { + const store = new Vuex.Store({ + state, + }); + + wrapper = shallowMount(ArchivedFilter, { + store, + }); + }; + + const findCheckboxFilter = () => wrapper.findComponent(GlFormCheckboxGroup); + const findH5 = () => wrapper.findComponent('h5'); + + describe('old sidebar', () => { + beforeEach(() => { + createComponent({ useNewNavigation: false }); + }); + + it('renders the component', () => { + expect(findCheckboxFilter().exists()).toBe(true); + }); + + it('renders the divider', () => { + expect(findH5().exists()).toBe(true); + expect(findH5().text()).toBe(archivedFilterData.headerLabel); + }); + }); + + describe('new sidebar', () => { + beforeEach(() => { + createComponent({ useNewNavigation: true }); + }); + + it('renders the component', () => { + expect(findCheckboxFilter().exists()).toBe(true); + }); + + it("doesn't render the divider", () => { + expect(findH5().exists()).toBe(true); + expect(findH5().text()).toBe(archivedFilterData.headerLabel); + }); + }); + + describe.each` + include_archived | checkboxState + ${''} | ${'false'} + ${'false'} | ${'false'} + ${'true'} | ${'true'} + ${'sdfsdf'} | ${'false'} + `('selectedFilter', ({ include_archived, checkboxState }) => { + beforeEach(() => { + createComponent({ urlQuery: { include_archived } }); + }); + + it('renders the component', () => { + expect(findCheckboxFilter().attributes('checked')).toBe(checkboxState); + }); + }); +}); diff --git a/spec/frontend/search/sidebar/components/blobs_filters_spec.js b/spec/frontend/search/sidebar/components/blobs_filters_spec.js new file mode 100644 index 00000000000..ff93e6f32e4 --- /dev/null +++ b/spec/frontend/search/sidebar/components/blobs_filters_spec.js @@ -0,0 +1,28 @@ +import { shallowMount } from '@vue/test-utils'; +import BlobsFilters from '~/search/sidebar/components/blobs_filters.vue'; +import LanguageFilter from '~/search/sidebar/components/language_filter/index.vue'; +import FiltersTemplate from '~/search/sidebar/components/filters_template.vue'; + +describe('GlobalSearch BlobsFilters', () => { + let wrapper; + + const findLanguageFilter = () => wrapper.findComponent(LanguageFilter); + const findFiltersTemplate = () => wrapper.findComponent(FiltersTemplate); + + const createComponent = () => { + wrapper = shallowMount(BlobsFilters); + }; + + describe('Renders correctly', () => { + beforeEach(() => { + createComponent(); + }); + it('renders FiltersTemplate', () => { + expect(findLanguageFilter().exists()).toBe(true); + }); + + it('renders ConfidentialityFilter', () => { + expect(findFiltersTemplate().exists()).toBe(true); + }); + }); +}); diff --git a/spec/frontend/search/sidebar/components/checkbox_filter_spec.js b/spec/frontend/search/sidebar/components/checkbox_filter_spec.js index 54fdf6e869e..b551e8c659c 100644 --- a/spec/frontend/search/sidebar/components/checkbox_filter_spec.js +++ b/spec/frontend/search/sidebar/components/checkbox_filter_spec.js @@ -1,5 +1,6 @@ import { GlFormCheckboxGroup, GlFormCheckbox } from '@gitlab/ui'; import Vue from 'vue'; +// eslint-disable-next-line no-restricted-imports import Vuex from 'vuex'; import { mockTracking, unmockTracking } from 'helpers/tracking_helper'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; diff --git a/spec/frontend/search/sidebar/components/confidentiality_filter_spec.js b/spec/frontend/search/sidebar/components/confidentiality_filter_spec.js index 1f65884e959..6444ec10466 100644 --- a/spec/frontend/search/sidebar/components/confidentiality_filter_spec.js +++ b/spec/frontend/search/sidebar/components/confidentiality_filter_spec.js @@ -1,7 +1,8 @@ import { shallowMount } from '@vue/test-utils'; import Vue from 'vue'; +// eslint-disable-next-line no-restricted-imports import Vuex from 'vuex'; -import ConfidentialityFilter from '~/search/sidebar/components/confidentiality_filter.vue'; +import ConfidentialityFilter from '~/search/sidebar/components/confidentiality_filter/index.vue'; import RadioFilter from '~/search/sidebar/components/radio_filter.vue'; Vue.use(Vuex); @@ -20,33 +21,24 @@ describe('ConfidentialityFilter', () => { }; const findRadioFilter = () => wrapper.findComponent(RadioFilter); - const findHR = () => wrapper.findComponent('hr'); describe('old sidebar', () => { beforeEach(() => { - createComponent({ useNewNavigation: false }); + createComponent({ useSidebarNavigation: false }); }); it('renders the component', () => { expect(findRadioFilter().exists()).toBe(true); }); - - it('renders the divider', () => { - expect(findHR().exists()).toBe(true); - }); }); describe('new sidebar', () => { beforeEach(() => { - createComponent({ useNewNavigation: true }); + createComponent({ useSidebarNavigation: true }); }); it('renders the component', () => { expect(findRadioFilter().exists()).toBe(true); }); - - it("doesn't render the divider", () => { - expect(findHR().exists()).toBe(false); - }); }); }); diff --git a/spec/frontend/search/sidebar/components/filters_spec.js b/spec/frontend/search/sidebar/components/filters_spec.js index a92fafd3508..d3c774929f5 100644 --- a/spec/frontend/search/sidebar/components/filters_spec.js +++ b/spec/frontend/search/sidebar/components/filters_spec.js @@ -1,11 +1,11 @@ -import { GlButton, GlLink } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import Vue from 'vue'; +// eslint-disable-next-line no-restricted-imports import Vuex from 'vuex'; import { MOCK_QUERY } from 'jest/search/mock_data'; import IssuesFilters from '~/search/sidebar/components/issues_filters.vue'; -import ConfidentialityFilter from '~/search/sidebar/components/confidentiality_filter.vue'; -import StatusFilter from '~/search/sidebar/components/status_filter.vue'; +import ConfidentialityFilter from '~/search/sidebar/components/confidentiality_filter/index.vue'; +import StatusFilter from '~/search/sidebar/components/status_filter/index.vue'; Vue.use(Vuex); @@ -36,11 +36,8 @@ describe('GlobalSearchSidebarFilters', () => { }); }; - const findSidebarForm = () => wrapper.find('form'); const findStatusFilter = () => wrapper.findComponent(StatusFilter); const findConfidentialityFilter = () => wrapper.findComponent(ConfidentialityFilter); - const findApplyButton = () => wrapper.findComponent(GlButton); - const findResetLinkButton = () => wrapper.findComponent(GlLink); describe('Renders correctly', () => { beforeEach(() => { @@ -53,82 +50,6 @@ describe('GlobalSearchSidebarFilters', () => { it('renders ConfidentialityFilter', () => { expect(findConfidentialityFilter().exists()).toBe(true); }); - - it('renders ApplyButton', () => { - expect(findApplyButton().exists()).toBe(true); - }); - }); - - describe('ApplyButton', () => { - describe('when sidebarDirty is false', () => { - beforeEach(() => { - createComponent({ sidebarDirty: false }); - }); - - it('disables the button', () => { - expect(findApplyButton().attributes('disabled')).toBeDefined(); - }); - }); - - describe('when sidebarDirty is true', () => { - beforeEach(() => { - createComponent({ sidebarDirty: true }); - }); - - it('enables the button', () => { - expect(findApplyButton().attributes('disabled')).toBe(undefined); - }); - }); - }); - - describe('ResetLinkButton', () => { - describe('with no filter selected', () => { - beforeEach(() => { - createComponent({ urlQuery: {} }); - }); - - it('does not render', () => { - expect(findResetLinkButton().exists()).toBe(false); - }); - }); - - describe('with filter selected', () => { - beforeEach(() => { - createComponent({ urlQuery: MOCK_QUERY }); - }); - - it('does render', () => { - expect(findResetLinkButton().exists()).toBe(true); - }); - }); - - describe('with filter selected and user updated query back to default', () => { - beforeEach(() => { - createComponent({ urlQuery: MOCK_QUERY, query: {} }); - }); - - it('does render', () => { - expect(findResetLinkButton().exists()).toBe(true); - }); - }); - }); - - describe('actions', () => { - beforeEach(() => { - createComponent({}); - }); - - it('clicking ApplyButton calls applyQuery', () => { - findSidebarForm().trigger('submit'); - - expect(actionSpies.applyQuery).toHaveBeenCalled(); - }); - - it('clicking ResetLinkButton calls resetQuery', () => { - findResetLinkButton().vm.$emit('click'); - - expect(actionSpies.resetQuery).toHaveBeenCalled(); - }); }); describe.each` diff --git a/spec/frontend/search/sidebar/components/filters_template_spec.js b/spec/frontend/search/sidebar/components/filters_template_spec.js new file mode 100644 index 00000000000..f1a807c5ceb --- /dev/null +++ b/spec/frontend/search/sidebar/components/filters_template_spec.js @@ -0,0 +1,168 @@ +import { GlForm, GlButton, GlLink } from '@gitlab/ui'; +import Vue from 'vue'; +// eslint-disable-next-line no-restricted-imports +import Vuex from 'vuex'; + +import { mockTracking, unmockTracking } from 'helpers/tracking_helper'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; +import { MOCK_QUERY, MOCK_AGGREGATIONS } from 'jest/search/mock_data'; + +import FiltersTemplate from '~/search/sidebar/components/filters_template.vue'; + +import { + TRACKING_ACTION_CLICK, + TRACKING_LABEL_APPLY, + TRACKING_LABEL_RESET, +} from '~/search/sidebar/constants/index'; + +Vue.use(Vuex); + +describe('GlobalSearchSidebarLanguageFilter', () => { + let wrapper; + let trackingSpy; + + const actionSpies = { + applyQuery: jest.fn(), + resetQuery: jest.fn(), + }; + + const getterSpies = { + currentScope: jest.fn(() => 'issues'), + }; + + const createComponent = (initialState) => { + const store = new Vuex.Store({ + state: { + query: MOCK_QUERY, + urlQuery: MOCK_QUERY, + aggregations: MOCK_AGGREGATIONS, + sidebarDirty: false, + ...initialState, + }, + actions: actionSpies, + getters: getterSpies, + }); + + wrapper = shallowMountExtended(FiltersTemplate, { + store, + slots: { + default: '<p>Filters Content</p>', + }, + }); + }; + + const findForm = () => wrapper.findComponent(GlForm); + const findDividers = () => wrapper.findAll('hr'); + const findApplyButton = () => wrapper.findComponent(GlButton); + const findResetButton = () => wrapper.findComponent(GlLink); + const findSlotContent = () => wrapper.findByText('Filters Content'); + + describe('Renders correctly', () => { + beforeEach(() => { + createComponent(); + }); + + it('renders form', () => { + expect(findForm().exists()).toBe(true); + }); + + it('renders dividers', () => { + expect(findDividers()).toHaveLength(2); + }); + + it('renders slot content', () => { + expect(findSlotContent().exists()).toBe(true); + }); + + it('renders ApplyButton', () => { + expect(findApplyButton().exists()).toBe(true); + }); + + it('renders reset button', () => { + expect(findResetButton().exists()).toBe(false); + }); + }); + + describe('resetButton', () => { + describe.each` + description | sidebarDirty | queryLangFilters | exists + ${'sidebar dirty only'} | ${true} | ${[]} | ${true} + ${'query filters only'} | ${false} | ${['JSON', 'C']} | ${false} + ${'sidebar dirty and query filters'} | ${true} | ${['JSON', 'C']} | ${true} + ${'sidebar not dirty and no query filters'} | ${false} | ${[]} | ${false} + `('$description', ({ sidebarDirty, queryLangFilters, exists }) => { + beforeEach(() => { + getterSpies.queryLanguageFilters = jest.fn(() => queryLangFilters); + + const query = { + ...MOCK_QUERY, + language: queryLangFilters, + state: undefined, + labels: undefined, + confidential: undefined, + }; + + createComponent({ + sidebarDirty, + query, + urlQuery: query, + }); + }); + + it(`button is ${exists ? 'shown' : 'hidden'}`, () => { + expect(findResetButton().exists()).toBe(exists); + }); + }); + }); + + describe('ApplyButton', () => { + describe('when sidebarDirty is false', () => { + beforeEach(() => { + createComponent({ sidebarDirty: false }); + }); + + it('disables the button', () => { + expect(findApplyButton().attributes('disabled')).toBeDefined(); + }); + }); + + describe('when sidebarDirty is true', () => { + beforeEach(() => { + createComponent({ sidebarDirty: true }); + }); + + it('enables the button', () => { + expect(findApplyButton().attributes('disabled')).toBe(undefined); + }); + }); + }); + + describe('actions', () => { + beforeEach(() => { + createComponent({ sidebarDirty: true }); + trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn); + }); + + afterEach(() => { + unmockTracking(); + }); + + it('clicking ApplyButton calls applyQuery', () => { + findForm().vm.$emit('submit', { preventDefault: () => {} }); + + expect(actionSpies.applyQuery).toHaveBeenCalled(); + expect(trackingSpy).toHaveBeenCalledWith(TRACKING_ACTION_CLICK, TRACKING_LABEL_APPLY, { + label: getterSpies.currentScope(), + }); + }); + + it('clicking resetButton calls resetQuery', () => { + findResetButton().vm.$emit('click'); + + expect(actionSpies.resetQuery).toHaveBeenCalled(); + expect(trackingSpy).toHaveBeenCalledWith(TRACKING_ACTION_CLICK, TRACKING_LABEL_RESET, { + label: getterSpies.currentScope(), + }); + }); + }); +}); diff --git a/spec/frontend/search/sidebar/components/issues_filters_spec.js b/spec/frontend/search/sidebar/components/issues_filters_spec.js new file mode 100644 index 00000000000..84c4258cbdb --- /dev/null +++ b/spec/frontend/search/sidebar/components/issues_filters_spec.js @@ -0,0 +1,107 @@ +import { shallowMount } from '@vue/test-utils'; +import Vue from 'vue'; +// eslint-disable-next-line no-restricted-imports +import Vuex from 'vuex'; +import { MOCK_QUERY } from 'jest/search/mock_data'; +import IssuesFilters from '~/search/sidebar/components/issues_filters.vue'; +import ConfidentialityFilter from '~/search/sidebar/components/confidentiality_filter/index.vue'; +import StatusFilter from '~/search/sidebar/components/status_filter/index.vue'; +import LabelFilter from '~/search/sidebar/components/label_filter/index.vue'; + +Vue.use(Vuex); + +describe('GlobalSearch IssuesFilters', () => { + let wrapper; + + const defaultGetters = { + currentScope: () => 'issues', + }; + + const createComponent = (initialState, ff = true) => { + const store = new Vuex.Store({ + state: { + urlQuery: MOCK_QUERY, + ...initialState, + }, + getters: defaultGetters, + }); + + wrapper = shallowMount(IssuesFilters, { + store, + provide: { + glFeatures: { + searchIssueLabelAggregation: ff, + }, + }, + }); + }; + + const findStatusFilter = () => wrapper.findComponent(StatusFilter); + const findConfidentialityFilter = () => wrapper.findComponent(ConfidentialityFilter); + const findLabelFilter = () => wrapper.findComponent(LabelFilter); + const findDividers = () => wrapper.findAll('hr'); + + describe('Renders correctly with FF enabled', () => { + beforeEach(() => { + createComponent({ urlQuery: MOCK_QUERY }); + }); + it('renders StatusFilter', () => { + expect(findStatusFilter().exists()).toBe(true); + }); + + it('renders ConfidentialityFilter', () => { + expect(findConfidentialityFilter().exists()).toBe(true); + }); + + it('renders LabelFilter', () => { + expect(findLabelFilter().exists()).toBe(true); + }); + + it('renders dividers correctly', () => { + expect(findDividers()).toHaveLength(2); + }); + }); + + describe('Renders correctly with FF disabled', () => { + beforeEach(() => { + createComponent({ urlQuery: MOCK_QUERY }, false); + }); + it('renders StatusFilter', () => { + expect(findStatusFilter().exists()).toBe(true); + }); + + it('renders ConfidentialityFilter', () => { + expect(findConfidentialityFilter().exists()).toBe(true); + }); + + it("doesn't render LabelFilter", () => { + expect(findLabelFilter().exists()).toBe(false); + }); + + it('renders divider correctly', () => { + expect(findDividers()).toHaveLength(1); + }); + }); + + describe('Renders correctly with wrong scope', () => { + beforeEach(() => { + defaultGetters.currentScope = () => 'blobs'; + createComponent({ urlQuery: MOCK_QUERY }); + }); + it("doesn't render StatusFilter", () => { + expect(findStatusFilter().exists()).toBe(false); + }); + + it("doesn't render ConfidentialityFilter", () => { + expect(findConfidentialityFilter().exists()).toBe(false); + }); + + it("doesn't render LabelFilter", () => { + expect(findLabelFilter().exists()).toBe(false); + }); + + it("doesn't render dividers", () => { + expect(findDividers()).toHaveLength(0); + }); + }); +}); diff --git a/spec/frontend/search/sidebar/components/label_dropdown_items_spec.js b/spec/frontend/search/sidebar/components/label_dropdown_items_spec.js index 135b12956b2..9124da5cfe1 100644 --- a/spec/frontend/search/sidebar/components/label_dropdown_items_spec.js +++ b/spec/frontend/search/sidebar/components/label_dropdown_items_spec.js @@ -1,5 +1,6 @@ import { GlFormCheckbox } from '@gitlab/ui'; import Vue from 'vue'; +// eslint-disable-next-line no-restricted-imports import Vuex from 'vuex'; import { shallowMount } from '@vue/test-utils'; import { PROCESS_LABELS_DATA } from 'jest/search/mock_data'; diff --git a/spec/frontend/search/sidebar/components/label_filter_spec.js b/spec/frontend/search/sidebar/components/label_filter_spec.js index 2a5b3a96045..07b2e176610 100644 --- a/spec/frontend/search/sidebar/components/label_filter_spec.js +++ b/spec/frontend/search/sidebar/components/label_filter_spec.js @@ -9,6 +9,7 @@ import { GlDropdownDivider, } from '@gitlab/ui'; import Vue from 'vue'; +// eslint-disable-next-line no-restricted-imports import Vuex from 'vuex'; import { mockTracking, unmockTracking } from 'helpers/tracking_helper'; import { mountExtended } from 'helpers/vue_test_utils_helper'; diff --git a/spec/frontend/search/sidebar/components/language_filter_spec.js b/spec/frontend/search/sidebar/components/language_filter_spec.js index 817199d7cfe..b45f365e1e1 100644 --- a/spec/frontend/search/sidebar/components/language_filter_spec.js +++ b/spec/frontend/search/sidebar/components/language_filter_spec.js @@ -1,5 +1,6 @@ -import { GlAlert, GlFormCheckbox, GlForm } from '@gitlab/ui'; +import { GlAlert, GlFormCheckbox } from '@gitlab/ui'; import Vue, { nextTick } from 'vue'; +// eslint-disable-next-line no-restricted-imports import Vuex from 'vuex'; import { mockTracking, unmockTracking } from 'helpers/tracking_helper'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; @@ -13,13 +14,11 @@ import CheckboxFilter from '~/search/sidebar/components/language_filter/checkbox import { TRACKING_LABEL_SHOW_MORE, - TRACKING_CATEGORY, TRACKING_PROPERTY_MAX, TRACKING_LABEL_MAX, TRACKING_LABEL_FILTERS, TRACKING_ACTION_SHOW, TRACKING_ACTION_CLICK, - TRACKING_LABEL_APPLY, TRACKING_LABEL_ALL, } from '~/search/sidebar/components/language_filter/tracking'; @@ -61,10 +60,7 @@ describe('GlobalSearchSidebarLanguageFilter', () => { }); }; - const findForm = () => wrapper.findComponent(GlForm); const findCheckboxFilter = () => wrapper.findComponent(CheckboxFilter); - const findApplyButton = () => wrapper.findByTestId('apply-button'); - const findResetButton = () => wrapper.findByTestId('reset-button'); const findShowMoreButton = () => wrapper.findByTestId('show-more-button'); const findAlert = () => wrapper.findComponent(GlAlert); const findAllCheckboxes = () => wrapper.findAllComponents(GlFormCheckbox); @@ -80,10 +76,6 @@ describe('GlobalSearchSidebarLanguageFilter', () => { unmockTracking(); }); - it('renders form', () => { - expect(findForm().exists()).toBe(true); - }); - it('renders checkbox-filter', () => { expect(findCheckboxFilter().exists()).toBe(true); }); @@ -93,10 +85,6 @@ describe('GlobalSearchSidebarLanguageFilter', () => { expect(findAllCheckboxes()).toHaveLength(10); }); - it('renders ApplyButton', () => { - expect(findApplyButton().exists()).toBe(true); - }); - it('renders Show More button', () => { expect(findShowMoreButton().exists()).toBe(true); }); @@ -106,47 +94,6 @@ describe('GlobalSearchSidebarLanguageFilter', () => { }); }); - describe('resetButton', () => { - describe.each` - description | sidebarDirty | queryFilters | exists - ${'sidebar dirty only'} | ${true} | ${[]} | ${false} - ${'query filters only'} | ${false} | ${['JSON', 'C']} | ${false} - ${'sidebar dirty and query filters'} | ${true} | ${['JSON', 'C']} | ${true} - ${'no sidebar and no query filters'} | ${false} | ${[]} | ${false} - `('$description', ({ sidebarDirty, queryFilters, exists }) => { - beforeEach(() => { - getterSpies.queryLanguageFilters = jest.fn(() => queryFilters); - createComponent({ sidebarDirty, query: { ...MOCK_QUERY, language: queryFilters } }); - }); - - it(`button is ${exists ? 'shown' : 'hidden'}`, () => { - expect(findResetButton().exists()).toBe(exists); - }); - }); - }); - - describe('ApplyButton', () => { - describe('when sidebarDirty is false', () => { - beforeEach(() => { - createComponent({ sidebarDirty: false }); - }); - - it('disables the button', () => { - expect(findApplyButton().attributes('disabled')).toBeDefined(); - }); - }); - - describe('when sidebarDirty is true', () => { - beforeEach(() => { - createComponent({ sidebarDirty: true }); - }); - - it('enables the button', () => { - expect(findApplyButton().attributes('disabled')).toBe(undefined); - }); - }); - }); - describe('Show All button works', () => { beforeEach(() => { createComponent(); @@ -211,19 +158,5 @@ describe('GlobalSearchSidebarLanguageFilter', () => { it('uses action fetchAllAggregation', () => { expect(actionSpies.fetchAllAggregation).toHaveBeenCalled(); }); - - it('clicking ApplyButton calls applyQuery', () => { - findForm().vm.$emit('submit', { preventDefault: () => {} }); - - expect(actionSpies.applyQuery).toHaveBeenCalled(); - }); - - it('sends tracking information clicking ApplyButton', () => { - findForm().vm.$emit('submit', { preventDefault: () => {} }); - - expect(trackingSpy).toHaveBeenCalledWith(TRACKING_ACTION_CLICK, TRACKING_LABEL_APPLY, { - label: TRACKING_CATEGORY, - }); - }); }); }); diff --git a/spec/frontend/search/sidebar/components/merge_requests_filters_spec.js b/spec/frontend/search/sidebar/components/merge_requests_filters_spec.js new file mode 100644 index 00000000000..0932f8e47d2 --- /dev/null +++ b/spec/frontend/search/sidebar/components/merge_requests_filters_spec.js @@ -0,0 +1,28 @@ +import { shallowMount } from '@vue/test-utils'; +import MergeRequestsFilters from '~/search/sidebar/components/merge_requests_filters.vue'; +import StatusFilter from '~/search/sidebar/components/status_filter/index.vue'; +import FiltersTemplate from '~/search/sidebar/components/filters_template.vue'; + +describe('GlobalSearch MergeRequestsFilters', () => { + let wrapper; + + const findStatusFilter = () => wrapper.findComponent(StatusFilter); + const findFiltersTemplate = () => wrapper.findComponent(FiltersTemplate); + + const createComponent = () => { + wrapper = shallowMount(MergeRequestsFilters); + }; + + describe('Renders correctly', () => { + beforeEach(() => { + createComponent(); + }); + it('renders ConfidentialityFilter', () => { + expect(findStatusFilter().exists()).toBe(true); + }); + + it('renders FiltersTemplate', () => { + expect(findFiltersTemplate().exists()).toBe(true); + }); + }); +}); diff --git a/spec/frontend/search/sidebar/components/projects_filters_specs.js b/spec/frontend/search/sidebar/components/projects_filters_specs.js new file mode 100644 index 00000000000..15e3254e289 --- /dev/null +++ b/spec/frontend/search/sidebar/components/projects_filters_specs.js @@ -0,0 +1,28 @@ +import { shallowMount } from '@vue/test-utils'; +import ProjectsFilters from '~/search/sidebar/components/projects_filters.vue'; +import ArchivedFilter from '~/search/sidebar/components/language_filter/index.vue'; +import FiltersTemplate from '~/search/sidebar/components/filters_template.vue'; + +describe('GlobalSearch ProjectsFilters', () => { + let wrapper; + + const findArchivedFilter = () => wrapper.findComponent(ArchivedFilter); + const findFiltersTemplate = () => wrapper.findComponent(FiltersTemplate); + + const createComponent = () => { + wrapper = shallowMount(ProjectsFilters); + }; + + describe('Renders correctly', () => { + beforeEach(() => { + createComponent(); + }); + it('renders ArchivedFilter', () => { + expect(findArchivedFilter().exists()).toBe(true); + }); + + it('renders FiltersTemplate', () => { + expect(findFiltersTemplate().exists()).toBe(true); + }); + }); +}); diff --git a/spec/frontend/search/sidebar/components/radio_filter_spec.js b/spec/frontend/search/sidebar/components/radio_filter_spec.js index 47235b828c3..b99daf9e2f3 100644 --- a/spec/frontend/search/sidebar/components/radio_filter_spec.js +++ b/spec/frontend/search/sidebar/components/radio_filter_spec.js @@ -1,11 +1,12 @@ import { GlFormRadioGroup, GlFormRadio } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import Vue from 'vue'; +// eslint-disable-next-line no-restricted-imports import Vuex from 'vuex'; import { MOCK_QUERY } from 'jest/search/mock_data'; import RadioFilter from '~/search/sidebar/components/radio_filter.vue'; -import { confidentialFilterData } from '~/search/sidebar/constants/confidential_filter_data'; -import { stateFilterData } from '~/search/sidebar/constants/state_filter_data'; +import { confidentialFilterData } from '~/search/sidebar/components/confidentiality_filter/data'; +import { statusFilterData } from '~/search/sidebar/components/status_filter/data'; Vue.use(Vuex); @@ -21,7 +22,7 @@ describe('RadioFilter', () => { }; const defaultProps = { - filterData: stateFilterData, + filterData: statusFilterData, }; const createComponent = (initialState, props = {}) => { @@ -60,20 +61,20 @@ describe('RadioFilter', () => { describe('Status Filter', () => { it('renders a radio button for each filterOption', () => { expect(findGlRadioButtonsText()).toStrictEqual( - stateFilterData.filterByScope[stateFilterData.scopes.ISSUES].map((f) => { - return f.value === stateFilterData.filters.ANY.value - ? `Any ${stateFilterData.header.toLowerCase()}` + statusFilterData.filterByScope[statusFilterData.scopes.ISSUES].map((f) => { + return f.value === statusFilterData.filters.ANY.value + ? `Any ${statusFilterData.header.toLowerCase()}` : f.label; }), ); }); it('clicking a radio button item calls setQuery', () => { - const filter = stateFilterData.filters[Object.keys(stateFilterData.filters)[0]].value; + const filter = statusFilterData.filters[Object.keys(statusFilterData.filters)[0]].value; findGlRadioButtonGroup().vm.$emit('input', filter); expect(actionSpies.setQuery).toHaveBeenCalledWith(expect.any(Object), { - key: stateFilterData.filterParam, + key: statusFilterData.filterParam, value: filter, }); }); diff --git a/spec/frontend/search/sidebar/components/scope_legacy_navigation_spec.js b/spec/frontend/search/sidebar/components/scope_legacy_navigation_spec.js index 786ad806ea6..63d8b34fcf0 100644 --- a/spec/frontend/search/sidebar/components/scope_legacy_navigation_spec.js +++ b/spec/frontend/search/sidebar/components/scope_legacy_navigation_spec.js @@ -1,6 +1,7 @@ import { GlNav, GlNavItem, GlIcon } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import Vue from 'vue'; +// eslint-disable-next-line no-restricted-imports import Vuex from 'vuex'; import { MOCK_QUERY, MOCK_NAVIGATION } from 'jest/search/mock_data'; import ScopeLegacyNavigation from '~/search/sidebar/components/scope_legacy_navigation.vue'; diff --git a/spec/frontend/search/sidebar/components/scope_sidebar_navigation_spec.js b/spec/frontend/search/sidebar/components/scope_sidebar_navigation_spec.js index 86939bdc5d6..d85942b9634 100644 --- a/spec/frontend/search/sidebar/components/scope_sidebar_navigation_spec.js +++ b/spec/frontend/search/sidebar/components/scope_sidebar_navigation_spec.js @@ -1,5 +1,6 @@ import { mount } from '@vue/test-utils'; import Vue, { nextTick } from 'vue'; +// eslint-disable-next-line no-restricted-imports import Vuex from 'vuex'; import ScopeSidebarNavigation from '~/search/sidebar/components/scope_sidebar_navigation.vue'; import NavItem from '~/super_sidebar/components/nav_item.vue'; diff --git a/spec/frontend/search/sidebar/components/status_filter_spec.js b/spec/frontend/search/sidebar/components/status_filter_spec.js index a332a43e624..c230341c172 100644 --- a/spec/frontend/search/sidebar/components/status_filter_spec.js +++ b/spec/frontend/search/sidebar/components/status_filter_spec.js @@ -1,8 +1,9 @@ import { shallowMount } from '@vue/test-utils'; import Vue from 'vue'; +// eslint-disable-next-line no-restricted-imports import Vuex from 'vuex'; import RadioFilter from '~/search/sidebar/components/radio_filter.vue'; -import StatusFilter from '~/search/sidebar/components/status_filter.vue'; +import StatusFilter from '~/search/sidebar/components/status_filter/index.vue'; Vue.use(Vuex); @@ -20,33 +21,24 @@ describe('StatusFilter', () => { }; const findRadioFilter = () => wrapper.findComponent(RadioFilter); - const findHR = () => wrapper.findComponent('hr'); describe('old sidebar', () => { beforeEach(() => { - createComponent({ useNewNavigation: false }); + createComponent({ useSidebarNavigation: false }); }); it('renders the component', () => { expect(findRadioFilter().exists()).toBe(true); }); - - it('renders the divider', () => { - expect(findHR().exists()).toBe(true); - }); }); describe('new sidebar', () => { beforeEach(() => { - createComponent({ useNewNavigation: true }); + createComponent({ useSidebarNavigation: true }); }); it('renders the component', () => { expect(findRadioFilter().exists()).toBe(true); }); - - it("doesn't render the divider", () => { - expect(findHR().exists()).toBe(false); - }); }); }); diff --git a/spec/frontend/search/sort/components/app_spec.js b/spec/frontend/search/sort/components/app_spec.js index 09c295e3ea9..f701952701c 100644 --- a/spec/frontend/search/sort/components/app_spec.js +++ b/spec/frontend/search/sort/components/app_spec.js @@ -1,6 +1,7 @@ import { GlButtonGroup, GlButton, GlCollapsibleListbox, GlListboxItem } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import Vue from 'vue'; +// eslint-disable-next-line no-restricted-imports import Vuex from 'vuex'; import { MOCK_QUERY, MOCK_SORT_OPTIONS } from 'jest/search/mock_data'; import GlobalSearchSort from '~/search/sort/components/app.vue'; diff --git a/spec/frontend/search/store/actions_spec.js b/spec/frontend/search/store/actions_spec.js index 2051e731647..cc9c555b6c7 100644 --- a/spec/frontend/search/store/actions_spec.js +++ b/spec/frontend/search/store/actions_spec.js @@ -181,25 +181,36 @@ describe('Global Search Store Actions', () => { }); describe('applyQuery', () => { - it('calls visitUrl and setParams with the state.query', () => { - return testAction(actions.applyQuery, null, state, [], [], () => { - expect(urlUtils.setUrlParams).toHaveBeenCalledWith({ ...state.query, page: null }); - expect(urlUtils.visitUrl).toHaveBeenCalled(); - }); + it('calls visitUrl and setParams with the state.query', async () => { + await testAction(actions.applyQuery, null, state, [], []); + expect(urlUtils.setUrlParams).toHaveBeenCalledWith( + { ...state.query, page: null }, + 'http://test.host/', + false, + true, + ); + expect(urlUtils.visitUrl).toHaveBeenCalled(); }); }); describe('resetQuery', () => { - it('calls visitUrl and setParams with empty values', () => { - return testAction(actions.resetQuery, null, state, [], [], () => { - expect(urlUtils.setUrlParams).toHaveBeenCalledWith({ + it('calls visitUrl and setParams with empty values', async () => { + await testAction(actions.resetQuery, null, state, [], []); + const resetParams = SIDEBAR_PARAMS.reduce((acc, param) => { + acc[param] = null; + return acc; + }, {}); + + expect(urlUtils.setUrlParams).toHaveBeenCalledWith( + { ...state.query, page: null, - state: null, - confidential: null, - }); - expect(urlUtils.visitUrl).toHaveBeenCalled(); - }); + ...resetParams, + }, + undefined, + true, + ); + expect(urlUtils.visitUrl).toHaveBeenCalled(); }); }); @@ -327,28 +338,6 @@ describe('Global Search Store Actions', () => { }); }); - describe('resetLanguageQueryWithRedirect', () => { - it('calls visitUrl and setParams with the state.query', () => { - return testAction(actions.resetLanguageQueryWithRedirect, null, state, [], [], () => { - expect(urlUtils.setUrlParams).toHaveBeenCalledWith({ ...state.query, page: null }); - expect(urlUtils.visitUrl).toHaveBeenCalled(); - }); - }); - }); - - describe('resetLanguageQuery', () => { - it('calls commit SET_QUERY with value []', () => { - state = { ...state, query: { ...state.query, language: ['YAML', 'Text', 'Markdown'] } }; - return testAction( - actions.resetLanguageQuery, - null, - state, - [{ type: types.SET_QUERY, payload: { key: 'language', value: [] } }], - [], - ); - }); - }); - describe('closeLabel', () => { beforeEach(() => { state = createState({ diff --git a/spec/frontend/search/store/getters_spec.js b/spec/frontend/search/store/getters_spec.js index 772acb39a57..571525bd025 100644 --- a/spec/frontend/search/store/getters_spec.js +++ b/spec/frontend/search/store/getters_spec.js @@ -17,7 +17,6 @@ import { MOCK_LABEL_SEARCH_RESULT, MOCK_FILTERED_APPLIED_SELECTED_LABELS, MOCK_FILTERED_UNSELECTED_LABELS, - MOCK_FILTERED_UNAPPLIED_SELECTED_LABELS, } from '../mock_data'; describe('Global Search Store Getters', () => { @@ -70,18 +69,6 @@ describe('Global Search Store Getters', () => { }); }); - describe('currentUrlQueryHasLanguageFilters', () => { - it.each` - description | lang | result - ${'has valid language'} | ${{ language: ['a', 'b'] }} | ${true} - ${'has empty lang'} | ${{ language: [] }} | ${false} - ${'has no lang'} | ${{}} | ${false} - `('$description', ({ lang, result }) => { - state.urlQuery = lang; - expect(getters.currentUrlQueryHasLanguageFilters(state)).toBe(result); - }); - }); - describe('navigationItems', () => { it('returns the re-mapped navigation data', () => { state.navigation = MOCK_NAVIGATION; @@ -133,25 +120,6 @@ describe('Global Search Store Getters', () => { }); }); - describe('filteredUnappliedSelectedLabels', () => { - beforeEach(() => { - state.query.labels = ['6', '73']; - }); - - it('returns all labels that are selected (part of URL) no search', () => { - expect(getters.filteredUnappliedSelectedLabels(state)).toStrictEqual( - MOCK_FILTERED_UNAPPLIED_SELECTED_LABELS, - ); - }); - - it('returns labels that are selected (part of URL) and result of search', () => { - state.searchLabelString = 'ACC'; - expect(getters.filteredUnappliedSelectedLabels(state)).toStrictEqual([ - MOCK_FILTERED_UNAPPLIED_SELECTED_LABELS[1], - ]); - }); - }); - describe('filteredUnselectedLabels', () => { it('returns all labels that are selected (part of URL) no search', () => { expect(getters.filteredUnselectedLabels(state)).toStrictEqual( diff --git a/spec/frontend/search/topbar/components/app_spec.js b/spec/frontend/search/topbar/components/app_spec.js index 9dc14b97ce0..62d0e377d74 100644 --- a/spec/frontend/search/topbar/components/app_spec.js +++ b/spec/frontend/search/topbar/components/app_spec.js @@ -1,6 +1,7 @@ import { GlSearchBoxByClick, GlButton } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import Vue from 'vue'; +// eslint-disable-next-line no-restricted-imports import Vuex from 'vuex'; import { MOCK_QUERY } from 'jest/search/mock_data'; import { stubComponent } from 'helpers/stub_component'; diff --git a/spec/frontend/search/topbar/components/group_filter_spec.js b/spec/frontend/search/topbar/components/group_filter_spec.js index 94882d181d3..fa8036a7f97 100644 --- a/spec/frontend/search/topbar/components/group_filter_spec.js +++ b/spec/frontend/search/topbar/components/group_filter_spec.js @@ -1,5 +1,6 @@ import { shallowMount } from '@vue/test-utils'; import Vue from 'vue'; +// eslint-disable-next-line no-restricted-imports import Vuex from 'vuex'; import { MOCK_GROUP, MOCK_QUERY, CURRENT_SCOPE } from 'jest/search/mock_data'; import { visitUrl, setUrlParams } from '~/lib/utils/url_utility'; diff --git a/spec/frontend/search/topbar/components/project_filter_spec.js b/spec/frontend/search/topbar/components/project_filter_spec.js index c25d2b94027..e7808370098 100644 --- a/spec/frontend/search/topbar/components/project_filter_spec.js +++ b/spec/frontend/search/topbar/components/project_filter_spec.js @@ -1,5 +1,6 @@ import { shallowMount } from '@vue/test-utils'; import Vue from 'vue'; +// eslint-disable-next-line no-restricted-imports import Vuex from 'vuex'; import { MOCK_PROJECT, MOCK_QUERY, CURRENT_SCOPE } from 'jest/search/mock_data'; import { visitUrl, setUrlParams } from '~/lib/utils/url_utility'; diff --git a/spec/frontend/search/topbar/components/searchable_dropdown_spec.js b/spec/frontend/search/topbar/components/searchable_dropdown_spec.js index f7d847674eb..5acaa1c1900 100644 --- a/spec/frontend/search/topbar/components/searchable_dropdown_spec.js +++ b/spec/frontend/search/topbar/components/searchable_dropdown_spec.js @@ -1,6 +1,7 @@ import { GlDropdown, GlDropdownItem, GlSearchBoxByType, GlSkeletonLoader } from '@gitlab/ui'; import { shallowMount, mount } from '@vue/test-utils'; import Vue, { nextTick } from 'vue'; +// eslint-disable-next-line no-restricted-imports import Vuex from 'vuex'; import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import { MOCK_GROUPS, MOCK_GROUP, MOCK_QUERY } from 'jest/search/mock_data'; |