diff options
Diffstat (limited to 'spec/frontend/header_search/components/app_spec.js')
-rw-r--r-- | spec/frontend/header_search/components/app_spec.js | 90 |
1 files changed, 43 insertions, 47 deletions
diff --git a/spec/frontend/header_search/components/app_spec.js b/spec/frontend/header_search/components/app_spec.js index d6263c663d2..ad56b2dde24 100644 --- a/spec/frontend/header_search/components/app_spec.js +++ b/spec/frontend/header_search/components/app_spec.js @@ -20,6 +20,7 @@ import { 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'; @@ -43,6 +44,9 @@ jest.mock('~/lib/utils/url_utility', () => ({ describe('HeaderSearchApp', () => { let wrapper; + jest.useFakeTimers(); + jest.spyOn(global, 'setTimeout'); + const actionSpies = { setSearch: jest.fn(), fetchAutocompleteOptions: jest.fn(), @@ -80,10 +84,6 @@ describe('HeaderSearchApp', () => { ); }; - afterEach(() => { - wrapper.destroy(); - }); - const findHeaderSearchForm = () => wrapper.findByTestId('header-search-form'); const findHeaderSearchInput = () => wrapper.findComponent(GlSearchBoxByType); const findScopeToken = () => wrapper.findComponent(GlToken); @@ -135,7 +135,7 @@ describe('HeaderSearchApp', () => { beforeEach(() => { window.gon.current_username = username; createComponent(); - findHeaderSearchInput().vm.$emit(showDropdown ? 'click' : ''); + findHeaderSearchInput().vm.$emit(showDropdown ? 'focusin' : ''); }); it(`should${showSearchDropdown ? '' : ' not'} render`, () => { @@ -157,7 +157,7 @@ describe('HeaderSearchApp', () => { beforeEach(() => { window.gon.current_username = MOCK_USERNAME; createComponent({ search }, {}); - findHeaderSearchInput().vm.$emit('click'); + findHeaderSearchInput().vm.$emit('focusin'); }); it(`should${showDefault ? '' : ' not'} render the Default Dropdown Items`, () => { @@ -178,6 +178,7 @@ describe('HeaderSearchApp', () => { 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); @@ -187,16 +188,16 @@ describe('HeaderSearchApp', () => { describe.each` username | showDropdown | expectedDesc - ${null} | ${false} | ${HeaderSearchApp.i18n.searchInputDescribeByNoDropdown} - ${null} | ${true} | ${HeaderSearchApp.i18n.searchInputDescribeByNoDropdown} - ${MOCK_USERNAME} | ${false} | ${HeaderSearchApp.i18n.searchInputDescribeByWithDropdown} - ${MOCK_USERNAME} | ${true} | ${HeaderSearchApp.i18n.searchInputDescribeByWithDropdown} + ${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 ? 'click' : ''); + findHeaderSearchInput().vm.$emit(showDropdown ? 'focusin' : ''); }); it(`sets description to ${expectedDesc}`, () => { @@ -212,7 +213,7 @@ describe('HeaderSearchApp', () => { ${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.searchResultsLoading} + ${MOCK_USERNAME} | ${true} | ${MOCK_SEARCH} | ${true} | ${MOCK_SCOPED_SEARCH_OPTIONS} | ${HeaderSearchApp.i18n.SEARCH_RESULTS_LOADING} `( 'Search Results Description', ({ username, showDropdown, search, loading, searchOptions, expectedDesc }) => { @@ -228,7 +229,7 @@ describe('HeaderSearchApp', () => { searchOptions: () => searchOptions, }, ); - findHeaderSearchInput().vm.$emit(showDropdown ? 'click' : ''); + findHeaderSearchInput().vm.$emit(showDropdown ? 'focusin' : ''); }); it(`sets description to ${expectedDesc}`, () => { @@ -257,7 +258,7 @@ describe('HeaderSearchApp', () => { searchOptions: () => searchOptions, }, ); - findHeaderSearchInput().vm.$emit('click'); + findHeaderSearchInput().vm.$emit('focusin'); }); it(`${hasToken ? 'is' : 'is NOT'} rendered when data set has type "${ @@ -291,7 +292,7 @@ describe('HeaderSearchApp', () => { window.gon.current_username = MOCK_USERNAME; createComponent({ search, searchContext }, { searchOptions: () => searchOptions }); if (isFocused) { - findHeaderSearchInput().vm.$emit('click'); + findHeaderSearchInput().vm.$emit('focusin'); } }); @@ -332,7 +333,7 @@ describe('HeaderSearchApp', () => { searchOptions: () => searchOptions, }, ); - findHeaderSearchInput().vm.$emit('click'); + findHeaderSearchInput().vm.$emit('focusin'); }); it(`icon for data set type "${searchOptions[0]?.html_id}" ${ @@ -353,12 +354,12 @@ describe('HeaderSearchApp', () => { }); describe('events', () => { - beforeEach(() => { - createComponent(); - window.gon.current_username = MOCK_USERNAME; - }); - describe('Header Search Input', () => { + beforeEach(() => { + window.gon.current_username = MOCK_USERNAME; + createComponent(); + }); + describe('when dropdown is closed', () => { let trackingSpy; @@ -366,9 +367,9 @@ describe('HeaderSearchApp', () => { trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn); }); - it('onFocus opens dropdown and triggers snowplow event', async () => { + it('onFocusin opens dropdown and triggers snowplow event', async () => { expect(findHeaderSearchDropdown().exists()).toBe(false); - findHeaderSearchInput().vm.$emit('focus'); + findHeaderSearchInput().vm.$emit('focusin'); await nextTick(); @@ -379,25 +380,19 @@ describe('HeaderSearchApp', () => { }); }); - it('onClick opens dropdown and triggers snowplow event', async () => { + it('onFocusout closes dropdown and triggers snowplow event', async () => { expect(findHeaderSearchDropdown().exists()).toBe(false); - findHeaderSearchInput().vm.$emit('click'); + findHeaderSearchInput().vm.$emit('focusout'); + jest.runAllTimers(); await nextTick(); - expect(findHeaderSearchDropdown().exists()).toBe(true); - expect(trackingSpy).toHaveBeenCalledWith(undefined, 'focus_input', { + expect(findHeaderSearchDropdown().exists()).toBe(false); + expect(trackingSpy).toHaveBeenCalledWith(undefined, 'blur_input', { label: 'global_search', property: 'navigation_top', }); }); - - it('onClick followed by onFocus only triggers a single snowplow event', async () => { - findHeaderSearchInput().vm.$emit('click'); - findHeaderSearchInput().vm.$emit('focus'); - - expect(trackingSpy).toHaveBeenCalledTimes(1); - }); }); describe('onInput', () => { @@ -439,18 +434,18 @@ describe('HeaderSearchApp', () => { }); }); - describe('Dropdown Keyboard Navigation', () => { + describe('onFocusout dropdown', () => { beforeEach(() => { - findHeaderSearchInput().vm.$emit('click'); + window.gon.current_username = MOCK_USERNAME; + createComponent({ search: 'tes' }, {}); + findHeaderSearchInput().vm.$emit('focusin'); }); - it('closes dropdown when @tab is emitted', async () => { - expect(findHeaderSearchDropdown().exists()).toBe(true); - findDropdownKeyboardNavigation().vm.$emit('tab'); - - await nextTick(); + it('closes with timeout so click event gets emited', () => { + findHeaderSearchInput().vm.$emit('focusout'); - expect(findHeaderSearchDropdown().exists()).toBe(false); + expect(setTimeout).toHaveBeenCalledTimes(1); + expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), DROPDOWN_CLOSE_TIMEOUT); }); }); }); @@ -463,9 +458,9 @@ describe('HeaderSearchApp', () => { ${2} | ${'test1'} `('currentFocusedOption', ({ MOCK_INDEX, search }) => { beforeEach(() => { - createComponent({ search }); window.gon.current_username = MOCK_USERNAME; - findHeaderSearchInput().vm.$emit('click'); + createComponent({ search }); + findHeaderSearchInput().vm.$emit('focusin'); }); it(`when currentFocusIndex changes to ${MOCK_INDEX} updates the data to searchOptions[${MOCK_INDEX}]`, () => { @@ -504,12 +499,13 @@ describe('HeaderSearchApp', () => { const MOCK_INDEX = 1; beforeEach(() => { - createComponent(); window.gon.current_username = MOCK_USERNAME; - findHeaderSearchInput().vm.$emit('click'); + createComponent(); + findHeaderSearchInput().vm.$emit('focusin'); }); - it('onKey-enter clicks the selected dropdown item rather than submitting a search', () => { + 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 })); |