Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/search/topbar')
-rw-r--r--spec/frontend/search/topbar/components/app_spec.js63
-rw-r--r--spec/frontend/search/topbar/components/group_filter_spec.js187
-rw-r--r--spec/frontend/search/topbar/components/project_filter_spec.js188
-rw-r--r--spec/frontend/search/topbar/components/search_type_indicator_spec.js128
-rw-r--r--spec/frontend/search/topbar/components/searchable_dropdown_item_spec.js93
-rw-r--r--spec/frontend/search/topbar/components/searchable_dropdown_spec.js220
6 files changed, 150 insertions, 729 deletions
diff --git a/spec/frontend/search/topbar/components/app_spec.js b/spec/frontend/search/topbar/components/app_spec.js
index 9704277c86b..d17bdc2a6e1 100644
--- a/spec/frontend/search/topbar/components/app_spec.js
+++ b/spec/frontend/search/topbar/components/app_spec.js
@@ -1,14 +1,14 @@
-import { GlSearchBoxByClick, GlButton } from '@gitlab/ui';
+import { GlSearchBoxByType, GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import Vue from 'vue';
+import Vue, { nextTick } 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';
import GlobalSearchTopbar from '~/search/topbar/components/app.vue';
-import GroupFilter from '~/search/topbar/components/group_filter.vue';
-import ProjectFilter from '~/search/topbar/components/project_filter.vue';
import MarkdownDrawer from '~/vue_shared/components/markdown_drawer/markdown_drawer.vue';
+import SearchTypeIndicator from '~/search/topbar/components/search_type_indicator.vue';
+import { ENTER_KEY } from '~/lib/utils/keys';
import {
SYNTAX_OPTIONS_ADVANCED_DOCUMENT,
SYNTAX_OPTIONS_ZOEKT_DOCUMENT,
@@ -41,42 +41,22 @@ describe('GlobalSearchTopbar', () => {
});
};
- const findGlSearchBox = () => wrapper.findComponent(GlSearchBoxByClick);
- const findGroupFilter = () => wrapper.findComponent(GroupFilter);
- const findProjectFilter = () => wrapper.findComponent(ProjectFilter);
+ const findGlSearchBox = () => wrapper.findComponent(GlSearchBoxByType);
const findSyntaxOptionButton = () => wrapper.findComponent(GlButton);
const findSyntaxOptionDrawer = () => wrapper.findComponent(MarkdownDrawer);
+ const findSearchTypeIndicator = () => wrapper.findComponent(SearchTypeIndicator);
describe('template', () => {
beforeEach(() => {
createComponent();
});
- describe('Search box', () => {
- it('renders always', () => {
- expect(findGlSearchBox().exists()).toBe(true);
- });
+ it('always renders Search box', () => {
+ expect(findGlSearchBox().exists()).toBe(true);
});
- describe.each`
- snippets | showFilters
- ${null} | ${true}
- ${{ query: { snippets: '' } }} | ${true}
- ${{ query: { snippets: false } }} | ${true}
- ${{ query: { snippets: true } }} | ${false}
- ${{ query: { snippets: 'false' } }} | ${true}
- ${{ query: { snippets: 'true' } }} | ${false}
- `('topbar filters', ({ snippets, showFilters }) => {
- beforeEach(() => {
- createComponent(snippets);
- });
-
- it(`does${showFilters ? '' : ' not'} render when snippets is ${JSON.stringify(
- snippets,
- )}`, () => {
- expect(findGroupFilter().exists()).toBe(showFilters);
- expect(findProjectFilter().exists()).toBe(showFilters);
- });
+ it('always renders Search indicator', () => {
+ expect(findSearchTypeIndicator().exists()).toBe(true);
});
describe.each`
@@ -128,15 +108,15 @@ describe('GlobalSearchTopbar', () => {
});
describe.each`
- state | defaultBranchName | hasSyntaxOptions
- ${{ query: { repository_ref: '' }, searchType: 'basic' }} | ${'master'} | ${false}
- ${{ query: { repository_ref: 'v0.1' }, searchType: 'basic' }} | ${''} | ${false}
- ${{ query: { repository_ref: 'master' }, searchType: 'basic' }} | ${'master'} | ${false}
- ${{ query: { repository_ref: 'master' }, searchType: 'advanced' }} | ${''} | ${false}
- ${{ query: { repository_ref: '' }, searchType: 'advanced' }} | ${'master'} | ${true}
- ${{ query: { repository_ref: 'v0.1' }, searchType: 'advanced' }} | ${''} | ${false}
- ${{ query: { repository_ref: 'master' }, searchType: 'advanced' }} | ${'master'} | ${true}
- ${{ query: { repository_ref: 'master' }, searchType: 'zoekt' }} | ${'master'} | ${true}
+ state | hasSyntaxOptions
+ ${{ query: { repository_ref: '' }, searchType: 'basic', searchLevel: 'project', defaultBranchName: 'master' }} | ${false}
+ ${{ query: { repository_ref: 'v0.1' }, searchType: 'basic', searchLevel: 'project', defaultBranchName: '' }} | ${false}
+ ${{ query: { repository_ref: 'master' }, searchType: 'basic', searchLevel: 'project', defaultBranchName: 'master' }} | ${false}
+ ${{ query: { repository_ref: 'master' }, searchType: 'advanced', searchLevel: 'project', defaultBranchName: '' }} | ${false}
+ ${{ query: { repository_ref: '' }, searchType: 'advanced', searchLevel: 'project', defaultBranchName: 'master' }} | ${true}
+ ${{ query: { repository_ref: 'v0.1' }, searchType: 'advanced', searchLevel: 'project', defaultBranchName: '' }} | ${false}
+ ${{ query: { repository_ref: 'master' }, searchType: 'advanced', searchLevel: 'project', defaultBranchName: 'master' }} | ${true}
+ ${{ query: { repository_ref: 'master' }, searchType: 'zoekt', searchLevel: 'project', defaultBranchName: 'master' }} | ${true}
`(
`the syntax option based on component state`,
({ state, defaultBranchName, hasSyntaxOptions }) => {
@@ -162,9 +142,10 @@ describe('GlobalSearchTopbar', () => {
createComponent();
});
- it('clicking search button inside search box calls applyQuery', () => {
- findGlSearchBox().vm.$emit('submit', { preventDefault: () => {} });
+ it('clicking search button inside search box calls applyQuery', async () => {
+ await nextTick();
+ findGlSearchBox().vm.$emit('keydown', new KeyboardEvent({ key: ENTER_KEY }));
expect(actionSpies.applyQuery).toHaveBeenCalled();
});
});
diff --git a/spec/frontend/search/topbar/components/group_filter_spec.js b/spec/frontend/search/topbar/components/group_filter_spec.js
deleted file mode 100644
index fa8036a7f97..00000000000
--- a/spec/frontend/search/topbar/components/group_filter_spec.js
+++ /dev/null
@@ -1,187 +0,0 @@
-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';
-import { GROUPS_LOCAL_STORAGE_KEY } from '~/search/store/constants';
-import GroupFilter from '~/search/topbar/components/group_filter.vue';
-import SearchableDropdown from '~/search/topbar/components/searchable_dropdown.vue';
-import { ANY_OPTION, GROUP_DATA, PROJECT_DATA } from '~/search/topbar/constants';
-
-Vue.use(Vuex);
-
-jest.mock('~/lib/utils/url_utility', () => ({
- visitUrl: jest.fn(),
- setUrlParams: jest.fn(),
-}));
-
-describe('GroupFilter', () => {
- let wrapper;
-
- const actionSpies = {
- fetchGroups: jest.fn(),
- setFrequentGroup: jest.fn(),
- loadFrequentGroups: jest.fn(),
- };
-
- const defaultProps = {
- initialData: null,
- };
-
- const createComponent = (initialState, props) => {
- const store = new Vuex.Store({
- state: {
- query: MOCK_QUERY,
- ...initialState,
- },
- actions: actionSpies,
- getters: {
- frequentGroups: () => [],
- currentScope: () => CURRENT_SCOPE,
- },
- });
-
- wrapper = shallowMount(GroupFilter, {
- store,
- propsData: {
- ...defaultProps,
- ...props,
- },
- });
- };
-
- const findSearchableDropdown = () => wrapper.findComponent(SearchableDropdown);
-
- describe('template', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('renders SearchableDropdown always', () => {
- expect(findSearchableDropdown().exists()).toBe(true);
- });
- });
-
- describe('events', () => {
- beforeEach(() => {
- createComponent();
- });
-
- describe('when @search is emitted', () => {
- const search = 'test';
-
- beforeEach(() => {
- findSearchableDropdown().vm.$emit('search', search);
- });
-
- it('calls fetchGroups with the search paramter', () => {
- expect(actionSpies.fetchGroups).toHaveBeenCalledTimes(1);
- expect(actionSpies.fetchGroups).toHaveBeenCalledWith(expect.any(Object), search);
- });
- });
-
- describe('when @change is emitted with Any', () => {
- beforeEach(() => {
- findSearchableDropdown().vm.$emit('change', ANY_OPTION);
- });
-
- it('calls setUrlParams with group null, project id null, nav_source null, and then calls visitUrl', () => {
- expect(setUrlParams).toHaveBeenCalledWith({
- [GROUP_DATA.queryParam]: null,
- [PROJECT_DATA.queryParam]: null,
- nav_source: null,
- scope: CURRENT_SCOPE,
- });
-
- expect(visitUrl).toHaveBeenCalled();
- });
-
- it('does not call setFrequentGroup', () => {
- expect(actionSpies.setFrequentGroup).not.toHaveBeenCalled();
- });
- });
-
- describe('when @change is emitted with a group', () => {
- beforeEach(() => {
- findSearchableDropdown().vm.$emit('change', MOCK_GROUP);
- });
-
- it('calls setUrlParams with group id, project id null, nav_source null, and then calls visitUrl', () => {
- expect(setUrlParams).toHaveBeenCalledWith({
- [GROUP_DATA.queryParam]: MOCK_GROUP.id,
- [PROJECT_DATA.queryParam]: null,
- nav_source: null,
- scope: CURRENT_SCOPE,
- });
-
- expect(visitUrl).toHaveBeenCalled();
- });
-
- it(`calls setFrequentGroup with the group and ${GROUPS_LOCAL_STORAGE_KEY}`, () => {
- expect(actionSpies.setFrequentGroup).toHaveBeenCalledWith(expect.any(Object), MOCK_GROUP);
- });
- });
-
- describe('when @first-open is emitted', () => {
- beforeEach(() => {
- findSearchableDropdown().vm.$emit('first-open');
- });
-
- it('calls loadFrequentGroups', () => {
- expect(actionSpies.loadFrequentGroups).toHaveBeenCalledTimes(1);
- });
- });
- });
-
- describe('computed', () => {
- describe('selectedGroup', () => {
- describe('when initialData is null', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('sets selectedGroup to ANY_OPTION', () => {
- expect(wrapper.vm.selectedGroup).toBe(ANY_OPTION);
- });
- });
-
- describe('when initialData is set', () => {
- beforeEach(() => {
- createComponent({}, { initialData: MOCK_GROUP });
- });
-
- it('sets selectedGroup to ANY_OPTION', () => {
- expect(wrapper.vm.selectedGroup).toBe(MOCK_GROUP);
- });
- });
- });
- });
-
- describe.each`
- navSource | initialData | callMethod
- ${null} | ${null} | ${false}
- ${null} | ${MOCK_GROUP} | ${false}
- ${'navbar'} | ${null} | ${false}
- ${'navbar'} | ${MOCK_GROUP} | ${true}
- `('onCreate', ({ navSource, initialData, callMethod }) => {
- describe(`when nav_source is ${navSource} and ${
- initialData ? 'has' : 'does not have'
- } an initial group`, () => {
- beforeEach(() => {
- createComponent({ query: { ...MOCK_QUERY, nav_source: navSource } }, { initialData });
- });
-
- it(`${callMethod ? 'does' : 'does not'} call setFrequentGroup`, () => {
- if (callMethod) {
- expect(actionSpies.setFrequentGroup).toHaveBeenCalledWith(
- expect.any(Object),
- initialData,
- );
- } else {
- expect(actionSpies.setFrequentGroup).not.toHaveBeenCalled();
- }
- });
- });
- });
-});
diff --git a/spec/frontend/search/topbar/components/project_filter_spec.js b/spec/frontend/search/topbar/components/project_filter_spec.js
deleted file mode 100644
index e7808370098..00000000000
--- a/spec/frontend/search/topbar/components/project_filter_spec.js
+++ /dev/null
@@ -1,188 +0,0 @@
-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';
-import { PROJECTS_LOCAL_STORAGE_KEY } from '~/search/store/constants';
-import ProjectFilter from '~/search/topbar/components/project_filter.vue';
-import SearchableDropdown from '~/search/topbar/components/searchable_dropdown.vue';
-import { ANY_OPTION, GROUP_DATA, PROJECT_DATA } from '~/search/topbar/constants';
-
-Vue.use(Vuex);
-
-jest.mock('~/lib/utils/url_utility', () => ({
- visitUrl: jest.fn(),
- setUrlParams: jest.fn(),
-}));
-
-describe('ProjectFilter', () => {
- let wrapper;
-
- const actionSpies = {
- fetchProjects: jest.fn(),
- setFrequentProject: jest.fn(),
- loadFrequentProjects: jest.fn(),
- };
-
- const defaultProps = {
- initialData: null,
- };
-
- const createComponent = (initialState, props) => {
- const store = new Vuex.Store({
- state: {
- query: MOCK_QUERY,
- ...initialState,
- },
- actions: actionSpies,
- getters: {
- frequentProjects: () => [],
- currentScope: () => CURRENT_SCOPE,
- },
- });
-
- wrapper = shallowMount(ProjectFilter, {
- store,
- propsData: {
- ...defaultProps,
- ...props,
- },
- });
- };
-
- const findSearchableDropdown = () => wrapper.findComponent(SearchableDropdown);
-
- describe('template', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('renders SearchableDropdown always', () => {
- expect(findSearchableDropdown().exists()).toBe(true);
- });
- });
-
- describe('events', () => {
- beforeEach(() => {
- createComponent();
- });
-
- describe('when @search is emitted', () => {
- const search = 'test';
-
- beforeEach(() => {
- findSearchableDropdown().vm.$emit('search', search);
- });
-
- it('calls fetchProjects with the search paramter', () => {
- expect(actionSpies.fetchProjects).toHaveBeenCalledWith(expect.any(Object), search);
- });
- });
-
- describe('when @change is emitted', () => {
- describe('with Any', () => {
- beforeEach(() => {
- findSearchableDropdown().vm.$emit('change', ANY_OPTION);
- });
-
- it('calls setUrlParams with null, no group id, nav_source null, then calls visitUrl', () => {
- expect(setUrlParams).toHaveBeenCalledWith({
- [PROJECT_DATA.queryParam]: null,
- nav_source: null,
- scope: CURRENT_SCOPE,
- });
- expect(visitUrl).toHaveBeenCalled();
- });
-
- it('does not call setFrequentProject', () => {
- expect(actionSpies.setFrequentProject).not.toHaveBeenCalled();
- });
- });
-
- describe('with a Project', () => {
- beforeEach(() => {
- findSearchableDropdown().vm.$emit('change', MOCK_PROJECT);
- });
-
- it('calls setUrlParams with project id, group id, nav_source null, then calls visitUrl', () => {
- expect(setUrlParams).toHaveBeenCalledWith({
- [GROUP_DATA.queryParam]: MOCK_PROJECT.namespace.id,
- [PROJECT_DATA.queryParam]: MOCK_PROJECT.id,
- nav_source: null,
- scope: CURRENT_SCOPE,
- });
- expect(visitUrl).toHaveBeenCalled();
- });
-
- it(`calls setFrequentProject with the group and ${PROJECTS_LOCAL_STORAGE_KEY}`, () => {
- expect(actionSpies.setFrequentProject).toHaveBeenCalledWith(
- expect.any(Object),
- MOCK_PROJECT,
- );
- });
- });
- });
-
- describe('when @first-open is emitted', () => {
- beforeEach(() => {
- findSearchableDropdown().vm.$emit('first-open');
- });
-
- it('calls loadFrequentProjects', () => {
- expect(actionSpies.loadFrequentProjects).toHaveBeenCalledTimes(1);
- });
- });
- });
-
- describe('computed', () => {
- describe('selectedProject', () => {
- describe('when initialData is null', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('sets selectedProject to ANY_OPTION', () => {
- expect(wrapper.vm.selectedProject).toBe(ANY_OPTION);
- });
- });
-
- describe('when initialData is set', () => {
- beforeEach(() => {
- createComponent({}, { initialData: MOCK_PROJECT });
- });
-
- it('sets selectedProject to the initialData', () => {
- expect(wrapper.vm.selectedProject).toBe(MOCK_PROJECT);
- });
- });
- });
- });
-
- describe.each`
- navSource | initialData | callMethod
- ${null} | ${null} | ${false}
- ${null} | ${MOCK_PROJECT} | ${false}
- ${'navbar'} | ${null} | ${false}
- ${'navbar'} | ${MOCK_PROJECT} | ${true}
- `('onCreate', ({ navSource, initialData, callMethod }) => {
- describe(`when nav_source is ${navSource} and ${
- initialData ? 'has' : 'does not have'
- } an initial project`, () => {
- beforeEach(() => {
- createComponent({ query: { ...MOCK_QUERY, nav_source: navSource } }, { initialData });
- });
-
- it(`${callMethod ? 'does' : 'does not'} call setFrequentProject`, () => {
- if (callMethod) {
- expect(actionSpies.setFrequentProject).toHaveBeenCalledWith(
- expect.any(Object),
- initialData,
- );
- } else {
- expect(actionSpies.setFrequentProject).not.toHaveBeenCalled();
- }
- });
- });
- });
-});
diff --git a/spec/frontend/search/topbar/components/search_type_indicator_spec.js b/spec/frontend/search/topbar/components/search_type_indicator_spec.js
new file mode 100644
index 00000000000..d69ca6dfb16
--- /dev/null
+++ b/spec/frontend/search/topbar/components/search_type_indicator_spec.js
@@ -0,0 +1,128 @@
+import Vue from 'vue';
+// eslint-disable-next-line no-restricted-imports
+import Vuex from 'vuex';
+import { GlSprintf } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import { MOCK_QUERY } from 'jest/search/mock_data';
+import SearchTypeIndicator from '~/search/topbar/components/search_type_indicator.vue';
+
+Vue.use(Vuex);
+
+describe('SearchTypeIndicator', () => {
+ let wrapper;
+
+ const actionSpies = {
+ applyQuery: jest.fn(),
+ setQuery: jest.fn(),
+ preloadStoredFrequentItems: jest.fn(),
+ };
+
+ const createComponent = (initialState = {}) => {
+ const store = new Vuex.Store({
+ state: {
+ query: MOCK_QUERY,
+ ...initialState,
+ },
+ actions: actionSpies,
+ });
+
+ wrapper = shallowMountExtended(SearchTypeIndicator, {
+ store,
+ stubs: {
+ GlSprintf,
+ },
+ });
+ };
+
+ const findIndicator = (id) => wrapper.findAllByTestId(id);
+ const findDocsLink = () => wrapper.findComponentByTestId('docs-link');
+ const findSyntaxDocsLink = () => wrapper.findComponentByTestId('syntax-docs-link');
+
+ // searchType and search level params cobination in this test reflects
+ // all possible combinations
+
+ describe.each`
+ searchType | searchLevel | repository | showSearchTypeIndicator
+ ${'advanced'} | ${'project'} | ${'master'} | ${'advanced-enabled'}
+ ${'advanced'} | ${'project'} | ${'v0.1'} | ${'advanced-disabled'}
+ ${'advanced'} | ${'group'} | ${'master'} | ${'advanced-enabled'}
+ ${'advanced'} | ${'global'} | ${'master'} | ${'advanced-enabled'}
+ ${'zoekt'} | ${'project'} | ${'master'} | ${'zoekt-enabled'}
+ ${'zoekt'} | ${'project'} | ${'v0.1'} | ${'zoekt-disabled'}
+ ${'zoekt'} | ${'group'} | ${'master'} | ${'zoekt-enabled'}
+ `(
+ 'search type indicator for $searchType $searchLevel',
+ ({ searchType, repository, showSearchTypeIndicator, searchLevel }) => {
+ beforeEach(() => {
+ createComponent({
+ query: { repository_ref: repository },
+ searchType,
+ searchLevel,
+ defaultBranchName: 'master',
+ });
+ });
+ it('renders correctly', () => {
+ expect(findIndicator(showSearchTypeIndicator).exists()).toBe(true);
+ });
+ },
+ );
+
+ describe.each`
+ searchType | repository | showSearchTypeIndicator
+ ${'basic'} | ${'master'} | ${true}
+ ${'basic'} | ${'v0.1'} | ${true}
+ `(
+ 'search type indicator for $searchType and $repository',
+ ({ searchType, repository, showSearchTypeIndicator }) => {
+ beforeEach(() => {
+ createComponent({
+ query: { repository_ref: repository },
+ searchType,
+ defaultBranchName: 'master',
+ });
+ });
+ it.each(['zoekt-enabled', 'zoekt-disabled', 'advanced-enabled', 'advanced-disabled'])(
+ 'renders correct indicator %s',
+ () => {
+ expect(findIndicator(searchType).exists()).toBe(showSearchTypeIndicator);
+ },
+ );
+ },
+ );
+
+ describe.each`
+ searchType | docsLink
+ ${'advanced'} | ${'/help/user/search/advanced_search'}
+ ${'zoekt'} | ${'/help/user/search/exact_code_search'}
+ `('documentation link for $searchType', ({ searchType, docsLink }) => {
+ beforeEach(() => {
+ createComponent({
+ query: { repository_ref: 'master' },
+ searchType,
+ searchLevel: 'project',
+ defaultBranchName: 'master',
+ });
+ });
+ it('has correct link', () => {
+ expect(findDocsLink().attributes('href')).toBe(docsLink);
+ });
+ });
+
+ describe.each`
+ searchType | syntaxdocsLink
+ ${'advanced'} | ${'/help/user/search/advanced_search#use-the-advanced-search-syntax'}
+ ${'zoekt'} | ${'/help/user/search/exact_code_search#syntax'}
+ `('Syntax documentation $searchType', ({ searchType, syntaxdocsLink }) => {
+ beforeEach(() => {
+ createComponent({
+ query: { repository_ref: '000' },
+ searchType,
+ searchLevel: 'project',
+ defaultBranchName: 'master',
+ });
+ });
+ it('has correct link', () => {
+ expect(findSyntaxDocsLink().attributes('href')).toBe(syntaxdocsLink);
+ });
+ });
+});
diff --git a/spec/frontend/search/topbar/components/searchable_dropdown_item_spec.js b/spec/frontend/search/topbar/components/searchable_dropdown_item_spec.js
deleted file mode 100644
index c911fe53d40..00000000000
--- a/spec/frontend/search/topbar/components/searchable_dropdown_item_spec.js
+++ /dev/null
@@ -1,93 +0,0 @@
-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,
- },
- });
- };
-
- 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
deleted file mode 100644
index 5acaa1c1900..00000000000
--- a/spec/frontend/search/topbar/components/searchable_dropdown_spec.js
+++ /dev/null
@@ -1,220 +0,0 @@
-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';
-import SearchableDropdown from '~/search/topbar/components/searchable_dropdown.vue';
-import { ANY_OPTION, GROUP_DATA } from '~/search/topbar/constants';
-
-Vue.use(Vuex);
-
-describe('Global Search Searchable Dropdown', () => {
- let wrapper;
-
- const defaultProps = {
- headerText: GROUP_DATA.headerText,
- name: GROUP_DATA.name,
- fullName: GROUP_DATA.fullName,
- loading: false,
- selectedItem: ANY_OPTION,
- items: [],
- };
-
- const createComponent = (initialState, props, mountFn = shallowMount) => {
- const store = new Vuex.Store({
- state: {
- query: MOCK_QUERY,
- ...initialState,
- },
- });
-
- wrapper = extendedWrapper(
- mountFn(SearchableDropdown, {
- store,
- propsData: {
- ...defaultProps,
- ...props,
- },
- }),
- );
- };
-
- const findGlDropdown = () => wrapper.findComponent(GlDropdown);
- const findGlDropdownSearch = () => findGlDropdown().findComponent(GlSearchBoxByType);
- const findDropdownText = () => findGlDropdown().find('.dropdown-toggle-text');
- const findSearchableDropdownItems = () => wrapper.findAllByTestId('searchable-items');
- const findFrequentDropdownItems = () => wrapper.findAllByTestId('frequent-items');
- const findAnyDropdownItem = () => findGlDropdown().findComponent(GlDropdownItem);
- const findFirstSearchableDropdownItem = () => findSearchableDropdownItems().at(0);
- const findFirstFrequentDropdownItem = () => findFrequentDropdownItems().at(0);
- const findLoader = () => wrapper.findComponent(GlSkeletonLoader);
-
- describe('template', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('renders GlDropdown', () => {
- expect(findGlDropdown().exists()).toBe(true);
- });
-
- describe('findGlDropdownSearch', () => {
- it('renders always', () => {
- expect(findGlDropdownSearch().exists()).toBe(true);
- });
-
- it('has debounce prop', () => {
- expect(findGlDropdownSearch().attributes('debounce')).toBe('500');
- });
-
- describe('onSearch', () => {
- const search = 'test search';
-
- beforeEach(() => {
- findGlDropdownSearch().vm.$emit('input', search);
- });
-
- it('$emits @search when input event is fired from GlSearchBoxByType', () => {
- expect(wrapper.emitted('search')[0]).toEqual([search]);
- });
- });
- });
-
- describe('Searchable Dropdown Items', () => {
- describe('when loading is false', () => {
- beforeEach(() => {
- createComponent({}, { items: MOCK_GROUPS });
- });
-
- it('does not render loader', () => {
- expect(findLoader().exists()).toBe(false);
- });
-
- it('renders the Any Dropdown', () => {
- expect(findAnyDropdownItem().exists()).toBe(true);
- });
-
- it('renders searchable dropdown item for each item', () => {
- expect(findSearchableDropdownItems()).toHaveLength(MOCK_GROUPS.length);
- });
- });
-
- describe('when loading is true', () => {
- beforeEach(() => {
- createComponent({}, { loading: true, items: MOCK_GROUPS });
- });
-
- it('does render loader', () => {
- expect(findLoader().exists()).toBe(true);
- });
-
- it('renders the Any Dropdown', () => {
- expect(findAnyDropdownItem().exists()).toBe(true);
- });
-
- it('does not render searchable dropdown items', () => {
- expect(findSearchableDropdownItems()).toHaveLength(0);
- });
- });
- });
-
- describe.each`
- searchText | frequentItems | length
- ${''} | ${[]} | ${0}
- ${''} | ${MOCK_GROUPS} | ${MOCK_GROUPS.length}
- ${'test'} | ${[]} | ${0}
- ${'test'} | ${MOCK_GROUPS} | ${0}
- `('Frequent Dropdown Items', ({ searchText, frequentItems, length }) => {
- describe(`when search is ${searchText} and frequentItems length is ${frequentItems.length}`, () => {
- beforeEach(() => {
- createComponent({}, { frequentItems });
- findGlDropdownSearch().vm.$emit('input', searchText);
- });
-
- it(`should${length ? '' : ' not'} render frequent dropdown items`, () => {
- expect(findFrequentDropdownItems()).toHaveLength(length);
- });
- });
- });
-
- describe('Dropdown Text', () => {
- describe('when selectedItem is any', () => {
- beforeEach(() => {
- createComponent({}, {}, mount);
- });
-
- it('sets dropdown text to Any', () => {
- expect(findDropdownText().text()).toBe(ANY_OPTION.name);
- });
- });
-
- describe('selectedItem is set', () => {
- beforeEach(() => {
- createComponent({}, { selectedItem: MOCK_GROUP }, mount);
- });
-
- it('sets dropdown text to the selectedItem name', () => {
- expect(findDropdownText().text()).toBe(MOCK_GROUP[GROUP_DATA.name]);
- });
- });
- });
- });
-
- describe('actions', () => {
- beforeEach(() => {
- createComponent({}, { items: MOCK_GROUPS, frequentItems: MOCK_GROUPS });
- });
-
- it('clicking "Any" dropdown item $emits @change with ANY_OPTION', () => {
- findAnyDropdownItem().vm.$emit('click');
-
- expect(wrapper.emitted('change')[0]).toEqual([ANY_OPTION]);
- });
-
- it('on searchable item @change, the wrapper $emits change with the item', () => {
- findFirstSearchableDropdownItem().vm.$emit('change', MOCK_GROUPS[0]);
-
- expect(wrapper.emitted('change')[0]).toEqual([MOCK_GROUPS[0]]);
- });
-
- it('on frequent item @change, the wrapper $emits change with the item', () => {
- findFirstFrequentDropdownItem().vm.$emit('change', MOCK_GROUPS[0]);
-
- expect(wrapper.emitted('change')[0]).toEqual([MOCK_GROUPS[0]]);
- });
-
- describe('opening the dropdown', () => {
- beforeEach(() => {
- findGlDropdown().vm.$emit('show');
- });
-
- it('$emits @search and @first-open on the first open', () => {
- expect(wrapper.emitted('search')[0]).toStrictEqual(['']);
- expect(wrapper.emitted('first-open')[0]).toStrictEqual([]);
- });
-
- describe('when the dropdown has been opened', () => {
- it('$emits @search with the searchText', async () => {
- const searchText = 'foo';
-
- findGlDropdownSearch().vm.$emit('input', searchText);
- await nextTick();
-
- expect(wrapper.emitted('search')[1]).toStrictEqual([searchText]);
- expect(wrapper.emitted('first-open')).toHaveLength(1);
- });
-
- it('does not emit @first-open again', async () => {
- expect(wrapper.emitted('first-open')).toHaveLength(1);
-
- findGlDropdownSearch().vm.$emit('input');
- await nextTick();
-
- expect(wrapper.emitted('first-open')).toHaveLength(1);
- });
- });
- });
- });
-});