diff options
Diffstat (limited to 'spec/frontend/vue_shared/components/dropdown_keyboard_navigation_spec.js')
-rw-r--r-- | spec/frontend/vue_shared/components/dropdown_keyboard_navigation_spec.js | 141 |
1 files changed, 141 insertions, 0 deletions
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]); + }); + }); + }); +}); |