From a5f4bba440d7f9ea47046a0a561d49adf0a1e6d4 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Wed, 16 Jun 2021 18:25:58 +0000 Subject: Add latest changes from gitlab-org/gitlab@14-0-stable-ee --- spec/frontend/search/mock_data.js | 28 ++++--- spec/frontend/search/store/actions_spec.js | 21 ++--- .../components/searchable_dropdown_item_spec.js | 97 ++++++++++++++++++++++ .../topbar/components/searchable_dropdown_spec.js | 58 ++++++------- 4 files changed, 150 insertions(+), 54 deletions(-) create mode 100644 spec/frontend/search/topbar/components/searchable_dropdown_item_spec.js (limited to 'spec/frontend/search') diff --git a/spec/frontend/search/mock_data.js b/spec/frontend/search/mock_data.js index d076997b04a..fbe01f372b0 100644 --- a/spec/frontend/search/mock_data.js +++ b/spec/frontend/search/mock_data.js @@ -2,47 +2,49 @@ export const MOCK_QUERY = { scope: 'issues', state: 'all', confidential: null, - group_id: 'test_1', + group_id: 1, }; export const MOCK_GROUP = { name: 'test group', - full_name: 'full name test group', - id: 'test_1', + full_name: 'full name / test group', + id: 1, }; export const MOCK_GROUPS = [ { + avatar_url: null, name: 'test group', - full_name: 'full name test group', - id: 'test_1', + full_name: 'full name / test group', + id: 1, }, { + avatar_url: 'https://avatar.com', name: 'test group 2', - full_name: 'full name test group 2', - id: 'test_2', + full_name: 'full name / test group 2', + id: 2, }, ]; export const MOCK_PROJECT = { name: 'test project', namespace: MOCK_GROUP, - nameWithNamespace: 'test group test project', - id: 'test_1', + nameWithNamespace: 'test group / test project', + id: 1, }; export const MOCK_PROJECTS = [ { name: 'test project', namespace: MOCK_GROUP, - name_with_namespace: 'test group test project', - id: 'test_1', + name_with_namespace: 'test group / test project', + id: 1, }, { name: 'test project 2', namespace: MOCK_GROUP, - name_with_namespace: 'test group test project 2', - id: 'test_2', + name_with_namespace: 'test group / test project 2', + id: 2, }, ]; diff --git a/spec/frontend/search/store/actions_spec.js b/spec/frontend/search/store/actions_spec.js index ab622c53387..634661c5843 100644 --- a/spec/frontend/search/store/actions_spec.js +++ b/spec/frontend/search/store/actions_spec.js @@ -20,9 +20,8 @@ describe('Global Search Store Actions', () => { let mock; let state; - const noCallback = () => {}; - const flashCallback = () => { - expect(createFlash).toHaveBeenCalledTimes(1); + const flashCallback = (callCount) => { + expect(createFlash).toHaveBeenCalledTimes(callCount); createFlash.mockClear(); }; @@ -37,19 +36,21 @@ describe('Global Search Store Actions', () => { }); describe.each` - action | axiosMock | type | expectedMutations | callback - ${actions.fetchGroups} | ${{ method: 'onGet', code: 200, res: MOCK_GROUPS }} | ${'success'} | ${[{ type: types.REQUEST_GROUPS }, { type: types.RECEIVE_GROUPS_SUCCESS, payload: MOCK_GROUPS }]} | ${noCallback} - ${actions.fetchGroups} | ${{ method: 'onGet', code: 500, res: null }} | ${'error'} | ${[{ type: types.REQUEST_GROUPS }, { type: types.RECEIVE_GROUPS_ERROR }]} | ${flashCallback} - ${actions.fetchProjects} | ${{ method: 'onGet', code: 200, res: MOCK_PROJECTS }} | ${'success'} | ${[{ type: types.REQUEST_PROJECTS }, { type: types.RECEIVE_PROJECTS_SUCCESS, payload: MOCK_PROJECTS }]} | ${noCallback} - ${actions.fetchProjects} | ${{ method: 'onGet', code: 500, res: null }} | ${'error'} | ${[{ type: types.REQUEST_PROJECTS }, { type: types.RECEIVE_PROJECTS_ERROR }]} | ${flashCallback} - `(`axios calls`, ({ action, axiosMock, type, expectedMutations, callback }) => { + action | axiosMock | type | expectedMutations | flashCallCount + ${actions.fetchGroups} | ${{ method: 'onGet', code: 200, res: MOCK_GROUPS }} | ${'success'} | ${[{ type: types.REQUEST_GROUPS }, { type: types.RECEIVE_GROUPS_SUCCESS, payload: MOCK_GROUPS }]} | ${0} + ${actions.fetchGroups} | ${{ method: 'onGet', code: 500, res: null }} | ${'error'} | ${[{ type: types.REQUEST_GROUPS }, { type: types.RECEIVE_GROUPS_ERROR }]} | ${1} + ${actions.fetchProjects} | ${{ method: 'onGet', code: 200, res: MOCK_PROJECTS }} | ${'success'} | ${[{ type: types.REQUEST_PROJECTS }, { type: types.RECEIVE_PROJECTS_SUCCESS, payload: MOCK_PROJECTS }]} | ${0} + ${actions.fetchProjects} | ${{ method: 'onGet', code: 500, res: null }} | ${'error'} | ${[{ type: types.REQUEST_PROJECTS }, { type: types.RECEIVE_PROJECTS_ERROR }]} | ${2} + `(`axios calls`, ({ action, axiosMock, type, expectedMutations, flashCallCount }) => { describe(action.name, () => { describe(`on ${type}`, () => { beforeEach(() => { mock[axiosMock.method]().replyOnce(axiosMock.code, axiosMock.res); }); it(`should dispatch the correct mutations`, () => { - return testAction({ action, state, expectedMutations }).then(() => callback()); + return testAction({ action, state, expectedMutations }).then(() => + flashCallback(flashCallCount), + ); }); }); }); diff --git a/spec/frontend/search/topbar/components/searchable_dropdown_item_spec.js b/spec/frontend/search/topbar/components/searchable_dropdown_item_spec.js new file mode 100644 index 00000000000..e51fe9a4cf9 --- /dev/null +++ b/spec/frontend/search/topbar/components/searchable_dropdown_item_spec.js @@ -0,0 +1,97 @@ +import { GlDropdownItem, GlAvatar } from '@gitlab/ui'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; +import { MOCK_GROUPS } from 'jest/search/mock_data'; +import { truncateNamespace } from '~/lib/utils/text_utility'; +import SearchableDropdownItem from '~/search/topbar/components/searchable_dropdown_item.vue'; +import { GROUP_DATA } from '~/search/topbar/constants'; + +describe('Global Search Searchable Dropdown Item', () => { + let wrapper; + + const defaultProps = { + item: MOCK_GROUPS[0], + selectedItem: MOCK_GROUPS[0], + name: GROUP_DATA.name, + fullName: GROUP_DATA.fullName, + }; + + const createComponent = (props) => { + wrapper = shallowMountExtended(SearchableDropdownItem, { + propsData: { + ...defaultProps, + ...props, + }, + }); + }; + + afterEach(() => { + wrapper.destroy(); + }); + + const findGlDropdownItem = () => wrapper.findComponent(GlDropdownItem); + const findGlAvatar = () => wrapper.findComponent(GlAvatar); + const findDropdownTitle = () => wrapper.findByTestId('item-title'); + const findDropdownSubtitle = () => wrapper.findByTestId('item-namespace'); + + describe('template', () => { + describe('always', () => { + beforeEach(() => { + createComponent(); + }); + + it('renders GlDropdownItem', () => { + expect(findGlDropdownItem().exists()).toBe(true); + }); + + it('renders GlAvatar', () => { + expect(findGlAvatar().exists()).toBe(true); + }); + + it('renders Dropdown Title correctly', () => { + const titleEl = findDropdownTitle(); + + expect(titleEl.exists()).toBe(true); + expect(titleEl.text()).toBe(MOCK_GROUPS[0][GROUP_DATA.name]); + }); + + it('renders Dropdown Subtitle correctly', () => { + const subtitleEl = findDropdownSubtitle(); + + expect(subtitleEl.exists()).toBe(true); + expect(subtitleEl.text()).toBe(truncateNamespace(MOCK_GROUPS[0][GROUP_DATA.fullName])); + }); + }); + + describe('when item === selectedItem', () => { + beforeEach(() => { + createComponent({ item: MOCK_GROUPS[0], selectedItem: MOCK_GROUPS[0] }); + }); + + it('marks the dropdown as checked', () => { + expect(findGlDropdownItem().attributes('ischecked')).toBe('true'); + }); + }); + + describe('when item !== selectedItem', () => { + beforeEach(() => { + createComponent({ item: MOCK_GROUPS[0], selectedItem: MOCK_GROUPS[1] }); + }); + + it('marks the dropdown as not checked', () => { + expect(findGlDropdownItem().attributes('ischecked')).toBeUndefined(); + }); + }); + }); + + describe('actions', () => { + beforeEach(() => { + createComponent(); + }); + + it('clicking the dropdown item $emits change with the item', () => { + findGlDropdownItem().vm.$emit('click'); + + expect(wrapper.emitted('change')[0]).toEqual([MOCK_GROUPS[0]]); + }); + }); +}); diff --git a/spec/frontend/search/topbar/components/searchable_dropdown_spec.js b/spec/frontend/search/topbar/components/searchable_dropdown_spec.js index 5de948592d4..10d779f0f90 100644 --- a/spec/frontend/search/topbar/components/searchable_dropdown_spec.js +++ b/spec/frontend/search/topbar/components/searchable_dropdown_spec.js @@ -1,20 +1,21 @@ import { GlDropdown, GlDropdownItem, GlSearchBoxByType, GlSkeletonLoader } from '@gitlab/ui'; -import { createLocalVue, shallowMount, mount } from '@vue/test-utils'; +import { shallowMount, mount } from '@vue/test-utils'; +import Vue from 'vue'; import Vuex from 'vuex'; import { MOCK_GROUPS, MOCK_GROUP, MOCK_QUERY } from 'jest/search/mock_data'; import SearchableDropdown from '~/search/topbar/components/searchable_dropdown.vue'; +import SearchableDropdownItem from '~/search/topbar/components/searchable_dropdown_item.vue'; import { ANY_OPTION, GROUP_DATA } from '~/search/topbar/constants'; -const localVue = createLocalVue(); -localVue.use(Vuex); +Vue.use(Vuex); describe('Global Search Searchable Dropdown', () => { let wrapper; const defaultProps = { headerText: GROUP_DATA.headerText, - selectedDisplayValue: GROUP_DATA.selectedDisplayValue, - itemsDisplayValue: GROUP_DATA.itemsDisplayValue, + name: GROUP_DATA.name, + fullName: GROUP_DATA.fullName, loading: false, selectedItem: ANY_OPTION, items: [], @@ -29,7 +30,6 @@ describe('Global Search Searchable Dropdown', () => { }); wrapper = mountFn(SearchableDropdown, { - localVue, store, propsData: { ...defaultProps, @@ -40,17 +40,16 @@ describe('Global Search Searchable Dropdown', () => { afterEach(() => { wrapper.destroy(); - wrapper = null; }); - const findGlDropdown = () => wrapper.find(GlDropdown); - const findGlDropdownSearch = () => findGlDropdown().find(GlSearchBoxByType); + const findGlDropdown = () => wrapper.findComponent(GlDropdown); + const findGlDropdownSearch = () => findGlDropdown().findComponent(GlSearchBoxByType); const findDropdownText = () => findGlDropdown().find('.dropdown-toggle-text'); - const findDropdownItems = () => findGlDropdown().findAll(GlDropdownItem); - const findDropdownItemsText = () => findDropdownItems().wrappers.map((w) => w.text()); - const findAnyDropdownItem = () => findDropdownItems().at(0); - const findFirstGroupDropdownItem = () => findDropdownItems().at(1); - const findLoader = () => wrapper.find(GlSkeletonLoader); + const findSearchableDropdownItems = () => + findGlDropdown().findAllComponents(SearchableDropdownItem); + const findAnyDropdownItem = () => findGlDropdown().findComponent(GlDropdownItem); + const findFirstGroupDropdownItem = () => findSearchableDropdownItems().at(0); + const findLoader = () => wrapper.findComponent(GlSkeletonLoader); describe('template', () => { beforeEach(() => { @@ -93,9 +92,12 @@ describe('Global Search Searchable Dropdown', () => { expect(findLoader().exists()).toBe(false); }); - it('renders an instance for each namespace', () => { - const resultsIncludeAny = ['Any'].concat(MOCK_GROUPS.map((n) => n.full_name)); - expect(findDropdownItemsText()).toStrictEqual(resultsIncludeAny); + it('renders the Any Dropdown', () => { + expect(findAnyDropdownItem().exists()).toBe(true); + }); + + it('renders SearchableDropdownItem for each item', () => { + expect(findSearchableDropdownItems()).toHaveLength(MOCK_GROUPS.length); }); }); @@ -108,18 +110,12 @@ describe('Global Search Searchable Dropdown', () => { expect(findLoader().exists()).toBe(true); }); - it('renders only Any in dropdown', () => { - expect(findDropdownItemsText()).toStrictEqual(['Any']); - }); - }); - - describe('when item is selected', () => { - beforeEach(() => { - createComponent({}, { items: MOCK_GROUPS, selectedItem: MOCK_GROUPS[0] }); + it('renders the Any Dropdown', () => { + expect(findAnyDropdownItem().exists()).toBe(true); }); - it('marks the dropdown as checked', () => { - expect(findFirstGroupDropdownItem().attributes('ischecked')).toBe('true'); + it('does not render SearchableDropdownItem', () => { + expect(findSearchableDropdownItems()).toHaveLength(0); }); }); }); @@ -140,8 +136,8 @@ describe('Global Search Searchable Dropdown', () => { createComponent({}, { selectedItem: MOCK_GROUP }, mount); }); - it('sets dropdown text to the selectedItem selectedDisplayValue', () => { - expect(findDropdownText().text()).toBe(MOCK_GROUP[GROUP_DATA.selectedDisplayValue]); + it('sets dropdown text to the selectedItem name', () => { + expect(findDropdownText().text()).toBe(MOCK_GROUP[GROUP_DATA.name]); }); }); }); @@ -158,8 +154,8 @@ describe('Global Search Searchable Dropdown', () => { expect(wrapper.emitted('change')[0]).toEqual([ANY_OPTION]); }); - it('clicking result dropdown item $emits @change with result', () => { - findFirstGroupDropdownItem().vm.$emit('click'); + it('on SearchableDropdownItem @change, the wrapper $emits change with the item', () => { + findFirstGroupDropdownItem().vm.$emit('change', MOCK_GROUPS[0]); expect(wrapper.emitted('change')[0]).toEqual([MOCK_GROUPS[0]]); }); -- cgit v1.2.1