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/header_search/components/app_spec.js')
-rw-r--r--spec/frontend/header_search/components/app_spec.js517
1 files changed, 0 insertions, 517 deletions
diff --git a/spec/frontend/header_search/components/app_spec.js b/spec/frontend/header_search/components/app_spec.js
deleted file mode 100644
index 0d0b6628bdf..00000000000
--- a/spec/frontend/header_search/components/app_spec.js
+++ /dev/null
@@ -1,517 +0,0 @@
-import { GlSearchBoxByType, GlToken, GlIcon } from '@gitlab/ui';
-import Vue, { nextTick } from 'vue';
-// eslint-disable-next-line no-restricted-imports
-import Vuex from 'vuex';
-import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import { mockTracking } from 'helpers/tracking_helper';
-import { s__, sprintf } from '~/locale';
-import HeaderSearchApp from '~/header_search/components/app.vue';
-import HeaderSearchAutocompleteItems from '~/header_search/components/header_search_autocomplete_items.vue';
-import HeaderSearchDefaultItems from '~/header_search/components/header_search_default_items.vue';
-import HeaderSearchScopedItems from '~/header_search/components/header_search_scoped_items.vue';
-import {
- SEARCH_INPUT_DESCRIPTION,
- SEARCH_RESULTS_DESCRIPTION,
- SEARCH_BOX_INDEX,
- ICON_PROJECT,
- ICON_GROUP,
- ICON_SUBGROUP,
- SCOPE_TOKEN_MAX_LENGTH,
- IS_SEARCHING,
- IS_NOT_FOCUSED,
- IS_FOCUSED,
- SEARCH_SHORTCUTS_MIN_CHARACTERS,
- DROPDOWN_CLOSE_TIMEOUT,
-} from '~/header_search/constants';
-import DropdownKeyboardNavigation from '~/vue_shared/components/dropdown_keyboard_navigation.vue';
-import { ENTER_KEY } from '~/lib/utils/keys';
-import { visitUrl } from '~/lib/utils/url_utility';
-import { truncate } from '~/lib/utils/text_utility';
-import {
- MOCK_SEARCH,
- MOCK_SEARCH_QUERY,
- MOCK_USERNAME,
- MOCK_DEFAULT_SEARCH_OPTIONS,
- MOCK_SCOPED_SEARCH_OPTIONS,
- MOCK_SEARCH_CONTEXT_FULL,
-} from '../mock_data';
-
-Vue.use(Vuex);
-
-jest.mock('~/lib/utils/url_utility', () => ({
- visitUrl: jest.fn(),
-}));
-
-describe('HeaderSearchApp', () => {
- let wrapper;
-
- jest.useFakeTimers();
- jest.spyOn(global, 'setTimeout');
-
- const actionSpies = {
- setSearch: jest.fn(),
- fetchAutocompleteOptions: jest.fn(),
- clearAutocomplete: jest.fn(),
- };
-
- const createComponent = (initialState, mockGetters) => {
- const store = new Vuex.Store({
- state: {
- ...initialState,
- },
- actions: actionSpies,
- getters: {
- searchQuery: () => MOCK_SEARCH_QUERY,
- searchOptions: () => MOCK_DEFAULT_SEARCH_OPTIONS,
- ...mockGetters,
- },
- });
-
- wrapper = shallowMountExtended(HeaderSearchApp, {
- store,
- });
- };
-
- const formatScopeName = (scopeName) => {
- if (!scopeName) {
- return false;
- }
- const searchResultsScope = s__('GlobalSearch|in %{scope}');
- return truncate(
- sprintf(searchResultsScope, {
- scope: scopeName,
- }),
- SCOPE_TOKEN_MAX_LENGTH,
- );
- };
-
- const findHeaderSearchForm = () => wrapper.findByTestId('header-search-form');
- const findHeaderSearchInput = () => wrapper.findComponent(GlSearchBoxByType);
- const findScopeToken = () => wrapper.findComponent(GlToken);
- const findHeaderSearchInputKBD = () => wrapper.find('.keyboard-shortcut-helper');
- const findHeaderSearchDropdown = () => wrapper.findByTestId('header-search-dropdown-menu');
- const findHeaderSearchDefaultItems = () => wrapper.findComponent(HeaderSearchDefaultItems);
- const findHeaderSearchScopedItems = () => wrapper.findComponent(HeaderSearchScopedItems);
- const findHeaderSearchAutocompleteItems = () =>
- wrapper.findComponent(HeaderSearchAutocompleteItems);
- const findDropdownKeyboardNavigation = () => wrapper.findComponent(DropdownKeyboardNavigation);
- const findSearchInputDescription = () => wrapper.find(`#${SEARCH_INPUT_DESCRIPTION}`);
- const findSearchResultsDescription = () => wrapper.findByTestId(SEARCH_RESULTS_DESCRIPTION);
-
- describe('template', () => {
- describe('always renders', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('Header Search Input', () => {
- expect(findHeaderSearchInput().exists()).toBe(true);
- });
-
- it('Header Search Input KBD hint', () => {
- expect(findHeaderSearchInputKBD().exists()).toBe(true);
- expect(findHeaderSearchInputKBD().text()).toContain('/');
- expect(findHeaderSearchInputKBD().attributes('title')).toContain(
- 'Use the shortcut key <kbd>/</kbd> to start a search',
- );
- });
-
- it('Search Input Description', () => {
- expect(findSearchInputDescription().exists()).toBe(true);
- });
-
- it('Search Results Description', () => {
- expect(findSearchResultsDescription().exists()).toBe(true);
- });
- });
-
- describe.each`
- showDropdown | username | showSearchDropdown
- ${false} | ${null} | ${false}
- ${false} | ${MOCK_USERNAME} | ${false}
- ${true} | ${null} | ${false}
- ${true} | ${MOCK_USERNAME} | ${true}
- `('Header Search Dropdown', ({ showDropdown, username, showSearchDropdown }) => {
- describe(`when showDropdown is ${showDropdown} and current_username is ${username}`, () => {
- beforeEach(() => {
- window.gon.current_username = username;
- createComponent();
- findHeaderSearchInput().vm.$emit(showDropdown ? 'focusin' : '');
- });
-
- it(`should${showSearchDropdown ? '' : ' not'} render`, () => {
- expect(findHeaderSearchDropdown().exists()).toBe(showSearchDropdown);
- });
- });
- });
-
- describe.each`
- search | showDefault | showScoped | showAutocomplete
- ${null} | ${true} | ${false} | ${false}
- ${''} | ${true} | ${false} | ${false}
- ${'t'} | ${false} | ${false} | ${true}
- ${'te'} | ${false} | ${false} | ${true}
- ${'tes'} | ${false} | ${true} | ${true}
- ${MOCK_SEARCH} | ${false} | ${true} | ${true}
- `('Header Search Dropdown Items', ({ search, showDefault, showScoped, showAutocomplete }) => {
- describe(`when search is ${search}`, () => {
- beforeEach(() => {
- window.gon.current_username = MOCK_USERNAME;
- createComponent({ search }, {});
- findHeaderSearchInput().vm.$emit('focusin');
- });
-
- it(`should${showDefault ? '' : ' not'} render the Default Dropdown Items`, () => {
- expect(findHeaderSearchDefaultItems().exists()).toBe(showDefault);
- });
-
- it(`should${showScoped ? '' : ' not'} render the Scoped Dropdown Items`, () => {
- expect(findHeaderSearchScopedItems().exists()).toBe(showScoped);
- });
-
- it(`should${showAutocomplete ? '' : ' not'} render the Autocomplete Dropdown Items`, () => {
- expect(findHeaderSearchAutocompleteItems().exists()).toBe(showAutocomplete);
- });
-
- it(`should render the Dropdown Navigation Component`, () => {
- expect(findDropdownKeyboardNavigation().exists()).toBe(true);
- });
-
- it(`should close the dropdown when press escape key`, async () => {
- findHeaderSearchInput().vm.$emit('keydown', new KeyboardEvent({ key: 27 }));
- jest.runAllTimers();
- await nextTick();
- expect(findHeaderSearchDropdown().exists()).toBe(false);
- expect(wrapper.emitted().expandSearchBar.length).toBe(1);
- });
- });
- });
-
- describe.each`
- username | showDropdown | expectedDesc
- ${null} | ${false} | ${HeaderSearchApp.i18n.SEARCH_INPUT_DESCRIBE_BY_NO_DROPDOWN}
- ${null} | ${true} | ${HeaderSearchApp.i18n.SEARCH_INPUT_DESCRIBE_BY_NO_DROPDOWN}
- ${MOCK_USERNAME} | ${false} | ${HeaderSearchApp.i18n.SEARCH_INPUT_DESCRIBE_BY_WITH_DROPDOWN}
- ${MOCK_USERNAME} | ${true} | ${HeaderSearchApp.i18n.SEARCH_INPUT_DESCRIBE_BY_WITH_DROPDOWN}
- `('Search Input Description', ({ username, showDropdown, expectedDesc }) => {
- describe(`current_username is ${username} and showDropdown is ${showDropdown}`, () => {
- beforeEach(() => {
- window.gon.current_username = username;
- createComponent();
- findHeaderSearchInput().vm.$emit(showDropdown ? 'focusin' : '');
- });
-
- it(`sets description to ${expectedDesc}`, () => {
- expect(findSearchInputDescription().text()).toBe(expectedDesc);
- });
- });
- });
-
- describe.each`
- username | showDropdown | search | loading | searchOptions | expectedDesc
- ${null} | ${true} | ${''} | ${false} | ${[]} | ${''}
- ${MOCK_USERNAME} | ${false} | ${''} | ${false} | ${[]} | ${''}
- ${MOCK_USERNAME} | ${true} | ${''} | ${false} | ${MOCK_DEFAULT_SEARCH_OPTIONS} | ${`${MOCK_DEFAULT_SEARCH_OPTIONS.length} default results provided. Use the up and down arrow keys to navigate search results list.`}
- ${MOCK_USERNAME} | ${true} | ${''} | ${true} | ${MOCK_DEFAULT_SEARCH_OPTIONS} | ${`${MOCK_DEFAULT_SEARCH_OPTIONS.length} default results provided. Use the up and down arrow keys to navigate search results list.`}
- ${MOCK_USERNAME} | ${true} | ${MOCK_SEARCH} | ${false} | ${MOCK_SCOPED_SEARCH_OPTIONS} | ${`Results updated. ${MOCK_SCOPED_SEARCH_OPTIONS.length} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit.`}
- ${MOCK_USERNAME} | ${true} | ${MOCK_SEARCH} | ${true} | ${MOCK_SCOPED_SEARCH_OPTIONS} | ${HeaderSearchApp.i18n.SEARCH_RESULTS_LOADING}
- `(
- 'Search Results Description',
- ({ username, showDropdown, search, loading, searchOptions, expectedDesc }) => {
- describe(`search is "${search}", loading is ${loading}, and showSearchDropdown is ${showDropdown}`, () => {
- beforeEach(() => {
- window.gon.current_username = username;
- createComponent(
- {
- search,
- loading,
- },
- {
- searchOptions: () => searchOptions,
- },
- );
- findHeaderSearchInput().vm.$emit(showDropdown ? 'focusin' : '');
- });
-
- it(`sets description to ${expectedDesc}`, () => {
- expect(findSearchResultsDescription().text()).toBe(expectedDesc);
- });
- });
- },
- );
-
- describe('input box', () => {
- describe.each`
- search | searchOptions | hasToken
- ${MOCK_SEARCH} | ${[MOCK_SCOPED_SEARCH_OPTIONS[0]]} | ${true}
- ${MOCK_SEARCH} | ${[MOCK_SCOPED_SEARCH_OPTIONS[1]]} | ${true}
- ${MOCK_SEARCH} | ${[MOCK_SCOPED_SEARCH_OPTIONS[2]]} | ${true}
- ${MOCK_SEARCH} | ${[MOCK_SCOPED_SEARCH_OPTIONS[3]]} | ${true}
- ${MOCK_SEARCH} | ${[MOCK_SCOPED_SEARCH_OPTIONS[4]]} | ${true}
- ${'te'} | ${[MOCK_SCOPED_SEARCH_OPTIONS[5]]} | ${false}
- ${'x'} | ${[]} | ${false}
- `('token', ({ search, searchOptions, hasToken }) => {
- beforeEach(() => {
- window.gon.current_username = MOCK_USERNAME;
- createComponent(
- { search },
- {
- searchOptions: () => searchOptions,
- },
- );
- findHeaderSearchInput().vm.$emit('focusin');
- });
-
- it(`${hasToken ? 'is' : 'is NOT'} rendered when data set has type "${
- searchOptions[0]?.html_id
- }"`, () => {
- expect(findScopeToken().exists()).toBe(hasToken);
- });
-
- it(`text ${hasToken ? 'is correctly' : 'is NOT'} rendered when text is "${
- searchOptions[0]?.scope || searchOptions[0]?.description
- }"`, () => {
- expect(findScopeToken().exists() && findScopeToken().text()).toBe(
- formatScopeName(searchOptions[0]?.scope || searchOptions[0]?.description),
- );
- });
- });
- });
-
- describe('form', () => {
- describe.each`
- searchContext | search | searchOptions | isFocused
- ${MOCK_SEARCH_CONTEXT_FULL} | ${null} | ${[]} | ${true}
- ${MOCK_SEARCH_CONTEXT_FULL} | ${MOCK_SEARCH} | ${[]} | ${true}
- ${MOCK_SEARCH_CONTEXT_FULL} | ${MOCK_SEARCH} | ${MOCK_SCOPED_SEARCH_OPTIONS} | ${true}
- ${MOCK_SEARCH_CONTEXT_FULL} | ${MOCK_SEARCH} | ${MOCK_SCOPED_SEARCH_OPTIONS} | ${false}
- ${null} | ${MOCK_SEARCH} | ${MOCK_SCOPED_SEARCH_OPTIONS} | ${true}
- ${null} | ${null} | ${MOCK_SCOPED_SEARCH_OPTIONS} | ${true}
- ${null} | ${null} | ${[]} | ${true}
- `('wrapper', ({ searchContext, search, searchOptions, isFocused }) => {
- beforeEach(() => {
- window.gon.current_username = MOCK_USERNAME;
- createComponent({ search, searchContext }, { searchOptions: () => searchOptions });
- if (isFocused) {
- findHeaderSearchInput().vm.$emit('focusin');
- }
- });
-
- const isSearching = search?.length > SEARCH_SHORTCUTS_MIN_CHARACTERS;
-
- it(`classes ${isSearching ? 'contain' : 'do not contain'} "${IS_SEARCHING}"`, () => {
- if (isSearching) {
- expect(findHeaderSearchForm().classes()).toContain(IS_SEARCHING);
- return;
- }
- if (!isSearching) {
- expect(findHeaderSearchForm().classes()).not.toContain(IS_SEARCHING);
- }
- });
-
- it(`classes ${isSearching ? 'contain' : 'do not contain'} "${
- isFocused ? IS_FOCUSED : IS_NOT_FOCUSED
- }"`, () => {
- expect(findHeaderSearchForm().classes()).toContain(
- isFocused ? IS_FOCUSED : IS_NOT_FOCUSED,
- );
- });
- });
- });
-
- describe.each`
- search | searchOptions | hasIcon | iconName
- ${MOCK_SEARCH} | ${[MOCK_SCOPED_SEARCH_OPTIONS[0]]} | ${true} | ${ICON_PROJECT}
- ${MOCK_SEARCH} | ${[MOCK_SCOPED_SEARCH_OPTIONS[2]]} | ${true} | ${ICON_GROUP}
- ${MOCK_SEARCH} | ${[MOCK_SCOPED_SEARCH_OPTIONS[3]]} | ${true} | ${ICON_SUBGROUP}
- ${MOCK_SEARCH} | ${[MOCK_SCOPED_SEARCH_OPTIONS[4]]} | ${false} | ${false}
- `('token', ({ search, searchOptions, hasIcon, iconName }) => {
- beforeEach(() => {
- window.gon.current_username = MOCK_USERNAME;
- createComponent(
- { search },
- {
- searchOptions: () => searchOptions,
- },
- );
- findHeaderSearchInput().vm.$emit('focusin');
- });
-
- it(`icon for data set type "${searchOptions[0]?.html_id}" ${
- hasIcon ? 'is' : 'is NOT'
- } rendered`, () => {
- expect(findScopeToken().findComponent(GlIcon).exists()).toBe(hasIcon);
- });
-
- it(`render ${iconName ? `"${iconName}"` : 'NO'} icon for data set type "${
- searchOptions[0]?.html_id
- }"`, () => {
- expect(
- findScopeToken().findComponent(GlIcon).exists() &&
- findScopeToken().findComponent(GlIcon).attributes('name'),
- ).toBe(iconName);
- });
- });
- });
-
- describe('events', () => {
- describe('Header Search Input', () => {
- beforeEach(() => {
- window.gon.current_username = MOCK_USERNAME;
- createComponent();
- });
-
- describe('when dropdown is closed', () => {
- let trackingSpy;
-
- beforeEach(() => {
- trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
- });
-
- it('onFocusin opens dropdown and triggers snowplow event', async () => {
- expect(findHeaderSearchDropdown().exists()).toBe(false);
- findHeaderSearchInput().vm.$emit('focusin');
-
- await nextTick();
-
- expect(findHeaderSearchDropdown().exists()).toBe(true);
- expect(trackingSpy).toHaveBeenCalledWith(undefined, 'focus_input', {
- label: 'global_search',
- property: 'navigation_top',
- });
- });
-
- it('onFocusout closes dropdown and triggers snowplow event', async () => {
- expect(findHeaderSearchDropdown().exists()).toBe(false);
-
- findHeaderSearchInput().vm.$emit('focusout');
- jest.runAllTimers();
- await nextTick();
-
- expect(findHeaderSearchDropdown().exists()).toBe(false);
- expect(trackingSpy).toHaveBeenCalledWith(undefined, 'blur_input', {
- label: 'global_search',
- property: 'navigation_top',
- });
- });
- });
-
- describe('onInput', () => {
- describe('when search has text', () => {
- beforeEach(() => {
- findHeaderSearchInput().vm.$emit('input', MOCK_SEARCH);
- });
-
- it('calls setSearch with search term', () => {
- expect(actionSpies.setSearch).toHaveBeenCalledWith(expect.any(Object), MOCK_SEARCH);
- });
-
- it('calls fetchAutocompleteOptions', () => {
- expect(actionSpies.fetchAutocompleteOptions).toHaveBeenCalled();
- });
-
- it('does not call clearAutocomplete', () => {
- expect(actionSpies.clearAutocomplete).not.toHaveBeenCalled();
- });
- });
-
- describe('when search is emptied', () => {
- beforeEach(() => {
- findHeaderSearchInput().vm.$emit('input', '');
- });
-
- it('calls setSearch with empty term', () => {
- expect(actionSpies.setSearch).toHaveBeenCalledWith(expect.any(Object), '');
- });
-
- it('does not call fetchAutocompleteOptions', () => {
- expect(actionSpies.fetchAutocompleteOptions).not.toHaveBeenCalled();
- });
-
- it('calls clearAutocomplete', () => {
- expect(actionSpies.clearAutocomplete).toHaveBeenCalled();
- });
- });
- });
- });
-
- describe('onFocusout dropdown', () => {
- beforeEach(() => {
- window.gon.current_username = MOCK_USERNAME;
- createComponent({ search: 'tes' }, {});
- findHeaderSearchInput().vm.$emit('focusin');
- });
-
- it('closes with timeout so click event gets emited', () => {
- findHeaderSearchInput().vm.$emit('focusout');
-
- expect(setTimeout).toHaveBeenCalledTimes(1);
- expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), DROPDOWN_CLOSE_TIMEOUT);
- });
- });
- });
-
- describe('computed', () => {
- describe.each`
- MOCK_INDEX | search
- ${1} | ${null}
- ${SEARCH_BOX_INDEX} | ${'test'}
- ${2} | ${'test1'}
- `('currentFocusedOption', ({ MOCK_INDEX, search }) => {
- beforeEach(() => {
- window.gon.current_username = MOCK_USERNAME;
- createComponent({ search });
- findHeaderSearchInput().vm.$emit('focusin');
- });
-
- it(`when currentFocusIndex changes to ${MOCK_INDEX} updates the data to searchOptions[${MOCK_INDEX}]`, () => {
- findDropdownKeyboardNavigation().vm.$emit('change', MOCK_INDEX);
- expect(wrapper.vm.currentFocusedOption).toBe(MOCK_DEFAULT_SEARCH_OPTIONS[MOCK_INDEX]);
- });
- });
- });
-
- describe('Submitting a search', () => {
- describe('with no currentFocusedOption', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('onKey-enter submits a search', () => {
- findHeaderSearchInput().vm.$emit('keydown', new KeyboardEvent({ key: ENTER_KEY }));
-
- expect(visitUrl).toHaveBeenCalledWith(MOCK_SEARCH_QUERY);
- });
- });
-
- describe('with less than min characters and no dropdown results', () => {
- beforeEach(() => {
- createComponent({ search: 'x' });
- });
-
- it('onKey-enter will NOT submit a search', () => {
- findHeaderSearchInput().vm.$emit('keydown', new KeyboardEvent({ key: ENTER_KEY }));
-
- expect(visitUrl).not.toHaveBeenCalledWith(MOCK_SEARCH_QUERY);
- });
- });
-
- describe('with currentFocusedOption', () => {
- const MOCK_INDEX = 1;
-
- beforeEach(() => {
- window.gon.current_username = MOCK_USERNAME;
- createComponent();
- findHeaderSearchInput().vm.$emit('focusin');
- });
-
- it('onKey-enter clicks the selected dropdown item rather than submitting a search', async () => {
- await nextTick();
- findDropdownKeyboardNavigation().vm.$emit('change', MOCK_INDEX);
-
- findHeaderSearchInput().vm.$emit('keydown', new KeyboardEvent({ key: ENTER_KEY }));
- expect(visitUrl).toHaveBeenCalledWith(MOCK_DEFAULT_SEARCH_OPTIONS[MOCK_INDEX].url);
- });
- });
- });
-});