diff options
Diffstat (limited to 'spec/frontend')
-rw-r--r-- | spec/frontend/__helpers__/flush_promises.js | 3 | ||||
-rw-r--r-- | spec/frontend/diffs/store/actions_spec.js | 4 | ||||
-rw-r--r-- | spec/frontend/diffs/utils/tree_worker_utils_spec.js (renamed from spec/frontend/diffs/utils/workers_spec.js) | 8 | ||||
-rw-r--r-- | spec/frontend/vue_shared/components/dropdown_keyboard_navigation_spec.js | 141 |
4 files changed, 152 insertions, 4 deletions
diff --git a/spec/frontend/__helpers__/flush_promises.js b/spec/frontend/__helpers__/flush_promises.js new file mode 100644 index 00000000000..5287a060753 --- /dev/null +++ b/spec/frontend/__helpers__/flush_promises.js @@ -0,0 +1,3 @@ +export default function flushPromises() { + return new Promise(setImmediate); +} diff --git a/spec/frontend/diffs/store/actions_spec.js b/spec/frontend/diffs/store/actions_spec.js index b35abc9da02..85734e05aeb 100644 --- a/spec/frontend/diffs/store/actions_spec.js +++ b/spec/frontend/diffs/store/actions_spec.js @@ -51,7 +51,7 @@ import { } from '~/diffs/store/actions'; import * as types from '~/diffs/store/mutation_types'; import * as utils from '~/diffs/store/utils'; -import * as workerUtils from '~/diffs/utils/workers'; +import * as treeWorkerUtils from '~/diffs/utils/tree_worker_utils'; import createFlash from '~/flash'; import axios from '~/lib/utils/axios_utils'; import * as commonUtils from '~/lib/utils/common_utils'; @@ -253,7 +253,7 @@ describe('DiffsStoreActions', () => { // Workers are synchronous in Jest environment (see https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58805) { type: types.SET_TREE_DATA, - payload: workerUtils.generateTreeList(diffMetadata.diff_files), + payload: treeWorkerUtils.generateTreeList(diffMetadata.diff_files), }, ], [], diff --git a/spec/frontend/diffs/utils/workers_spec.js b/spec/frontend/diffs/utils/tree_worker_utils_spec.js index 25d8183b777..8113428f712 100644 --- a/spec/frontend/diffs/utils/workers_spec.js +++ b/spec/frontend/diffs/utils/tree_worker_utils_spec.js @@ -1,6 +1,10 @@ -import { generateTreeList, getLowestSingleFolder, flattenTree } from '~/diffs/utils/workers'; +import { + generateTreeList, + getLowestSingleFolder, + flattenTree, +} from '~/diffs/utils/tree_worker_utils'; -describe('~/diffs/utils/workers', () => { +describe('~/diffs/utils/tree_worker_utils', () => { describe('generateTreeList', () => { let files; diff --git a/spec/frontend/vue_shared/components/dropdown_keyboard_navigation_spec.js b/spec/frontend/vue_shared/components/dropdown_keyboard_navigation_spec.js new file mode 100644 index 00000000000..996df34f2ff --- /dev/null +++ b/spec/frontend/vue_shared/components/dropdown_keyboard_navigation_spec.js @@ -0,0 +1,141 @@ +import { shallowMount } from '@vue/test-utils'; +import DropdownKeyboardNavigation from '~/vue_shared/components/dropdown_keyboard_navigation.vue'; +import { UP_KEY_CODE, DOWN_KEY_CODE, TAB_KEY_CODE } from '~/lib/utils/keycodes'; + +const MOCK_INDEX = 0; +const MOCK_MAX = 10; +const MOCK_MIN = 0; +const MOCK_DEFAULT_INDEX = 0; + +describe('DropdownKeyboardNavigation', () => { + let wrapper; + + const defaultProps = { + index: MOCK_INDEX, + max: MOCK_MAX, + min: MOCK_MIN, + defaultIndex: MOCK_DEFAULT_INDEX, + }; + + const createComponent = (props) => { + wrapper = shallowMount(DropdownKeyboardNavigation, { + propsData: { + ...defaultProps, + ...props, + }, + }); + }; + + const helpers = { + arrowDown: () => { + document.dispatchEvent(new KeyboardEvent('keydown', { keyCode: DOWN_KEY_CODE })); + }, + arrowUp: () => { + document.dispatchEvent(new KeyboardEvent('keydown', { keyCode: UP_KEY_CODE })); + }, + tab: () => { + document.dispatchEvent(new KeyboardEvent('keydown', { keyCode: TAB_KEY_CODE })); + }, + }; + + afterEach(() => { + wrapper.destroy(); + }); + + describe('onInit', () => { + beforeEach(() => { + createComponent(); + }); + + it('should $emit @change with the default index', async () => { + expect(wrapper.emitted('change')[0]).toStrictEqual([MOCK_DEFAULT_INDEX]); + }); + + it('should $emit @change with the default index when max changes', async () => { + wrapper.setProps({ max: 20 }); + await wrapper.vm.$nextTick(); + // The first @change`call happens on created() so we test for the second [1] + expect(wrapper.emitted('change')[1]).toStrictEqual([MOCK_DEFAULT_INDEX]); + }); + }); + + describe('keydown events', () => { + let incrementSpy; + + beforeEach(() => { + createComponent(); + incrementSpy = jest.spyOn(wrapper.vm, 'increment'); + }); + + afterEach(() => { + incrementSpy.mockRestore(); + }); + + it('onKeydown-Down calls increment(1)', () => { + helpers.arrowDown(); + + expect(incrementSpy).toHaveBeenCalledWith(1); + }); + + it('onKeydown-Up calls increment(-1)', () => { + helpers.arrowUp(); + + expect(incrementSpy).toHaveBeenCalledWith(-1); + }); + + it('onKeydown-Tab $emits @tab event', () => { + helpers.tab(); + + expect(wrapper.emitted('tab')).toHaveLength(1); + }); + }); + + describe('increment', () => { + describe('when max is 0', () => { + beforeEach(() => { + createComponent({ max: 0 }); + }); + + it('does not $emit any @change events', () => { + helpers.arrowDown(); + + // The first @change`call happens on created() so we test that we only have 1 call + expect(wrapper.emitted('change')).toHaveLength(1); + }); + }); + + describe.each` + keyboardAction | direction | index | max | min + ${helpers.arrowDown} | ${1} | ${10} | ${10} | ${0} + ${helpers.arrowUp} | ${-1} | ${0} | ${10} | ${0} + `('moving out of bounds', ({ keyboardAction, direction, index, max, min }) => { + beforeEach(() => { + createComponent({ index, max, min }); + keyboardAction(); + }); + + it(`in ${direction} direction does not $emit any @change events`, () => { + // The first @change`call happens on created() so we test that we only have 1 call + expect(wrapper.emitted('change')).toHaveLength(1); + }); + }); + + describe.each` + keyboardAction | direction | index | max | min + ${helpers.arrowDown} | ${1} | ${0} | ${10} | ${0} + ${helpers.arrowUp} | ${-1} | ${10} | ${10} | ${0} + `('moving in bounds', ({ keyboardAction, direction, index, max, min }) => { + beforeEach(() => { + createComponent({ index, max, min }); + keyboardAction(); + }); + + it(`in ${direction} direction $emits @change event with the correct index ${ + index + direction + }`, () => { + // The first @change`call happens on created() so we test for the second [1] + expect(wrapper.emitted('change')[1]).toStrictEqual([index + direction]); + }); + }); + }); +}); |