From d9d30d1f2dd975e47db24df347554302b47db734 Mon Sep 17 00:00:00 2001 From: Mikhail Gubenko Date: Fri, 29 Jan 2021 10:52:39 +0200 Subject: [PATCH 1/3] Fix for trigger('focus') Added test case and the fix for wrapper trigger --- packages/test-utils/src/wrapper.js | 28 ++++++++- .../component-with-multiple-inputs.vue | 57 +++++++++++++++++++ test/specs/wrapper-array/trigger.spec.js | 24 ++++++++ 3 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 test/resources/components/component-with-multiple-inputs.vue diff --git a/packages/test-utils/src/wrapper.js b/packages/test-utils/src/wrapper.js index cf127f496..7d0736113 100644 --- a/packages/test-utils/src/wrapper.js +++ b/packages/test-utils/src/wrapper.js @@ -829,6 +829,31 @@ export default class Wrapper implements BaseWrapper { return this.element.textContent.trim() } + /** + * Simulates event triggering + * @param type + * @param options + * @returns {*} + * @private + */ + __simulateTrigger(type, options) { + const regularEventTrigger = (type, options) => { + const event = createDOMEvent(type, options) + return this.element.dispatchEvent(event) + } + + const focusEventTrigger = (type, options) => this.element.focus(options) + + const triggerProcedureMap = { + focus: focusEventTrigger, + __default: regularEventTrigger + } + + const triggerFn = triggerProcedureMap[type] || triggerProcedureMap.__default + + return triggerFn(type, options) + } + /** * Dispatches a DOM event on wrapper */ @@ -869,8 +894,7 @@ export default class Wrapper implements BaseWrapper { return nextTick() } - const event = createDOMEvent(type, options) - this.element.dispatchEvent(event) + this.__simulateTrigger(type, options) return nextTick() } } diff --git a/test/resources/components/component-with-multiple-inputs.vue b/test/resources/components/component-with-multiple-inputs.vue new file mode 100644 index 000000000..bd8bbbaf5 --- /dev/null +++ b/test/resources/components/component-with-multiple-inputs.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/test/specs/wrapper-array/trigger.spec.js b/test/specs/wrapper-array/trigger.spec.js index 9ef116678..648adba1c 100644 --- a/test/specs/wrapper-array/trigger.spec.js +++ b/test/specs/wrapper-array/trigger.spec.js @@ -1,7 +1,11 @@ import { compileToFunctions } from 'vue-template-compiler' import ComponentWithEvents from '~resources/components/component-with-events.vue' +import ComponentWithMultipleInputs from '~resources/components/component-with-multiple-inputs.vue' import { describeWithShallowAndMount } from '~resources/utils' +const assertElementIsFocused = element => + expect(document.activeElement.id).toEqual(element.id) + describeWithShallowAndMount('trigger', mountingMethod => { it('causes click handler to fire when wrapper.trigger("click") is called on a Component', async () => { const clickHandler = jest.fn() @@ -34,6 +38,26 @@ describeWithShallowAndMount('trigger', mountingMethod => { expect(keydownHandler).toHaveBeenCalled() }) + it('should really focus element when trigger focus was called', async () => { + const wrapper = mountingMethod(ComponentWithMultipleInputs, { + attachTo: document.body + }) + + assertElementIsFocused(wrapper.get('[data-test-position="2"]').element) + + await wrapper.get('[data-test-position="4"]').trigger('focus') + + assertElementIsFocused(wrapper.get('[data-test-position="4"]').element) + + await wrapper.get('[data-test-position="3"]').trigger('focus') + + assertElementIsFocused(wrapper.get('[data-test-position="4"]').element) + + await wrapper.get('[data-test-position="2"]').trigger('focus') + + assertElementIsFocused(wrapper.get('[data-test-position="2"]').element) + }) + it('throws an error if type is not a string', () => { const wrapper = mountingMethod(ComponentWithEvents) const invalidSelectors = [ From 9cd50d8687be3952064869a4cda769d5c12b51d7 Mon Sep 17 00:00:00 2001 From: Mikhail Gubenko Date: Fri, 29 Jan 2021 11:17:17 +0200 Subject: [PATCH 2/3] Extended types notation and jsdoc --- packages/test-utils/src/wrapper.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/test-utils/src/wrapper.js b/packages/test-utils/src/wrapper.js index 7d0736113..bf8f44acd 100644 --- a/packages/test-utils/src/wrapper.js +++ b/packages/test-utils/src/wrapper.js @@ -31,7 +31,7 @@ export default class Wrapper implements BaseWrapper { +vm: Component | void _emitted: { [name: string]: Array> } _emittedByOrder: Array<{ name: string, args: Array }> - +element: Element + +element: Element | HTMLInputElement +options: WrapperOptions isFunctionalComponent: boolean rootNode: VNode | Element @@ -831,8 +831,8 @@ export default class Wrapper implements BaseWrapper { /** * Simulates event triggering - * @param type - * @param options + * @param type {string} + * @param [options] {Object} * @returns {*} * @private */ From 0edc835376d60f7e9284d8f70c9e29206d50b57b Mon Sep 17 00:00:00 2001 From: Mikhail Gubenko Date: Fri, 29 Jan 2021 11:50:10 +0200 Subject: [PATCH 3/3] Added type check and fallback for focus processing --- packages/test-utils/src/wrapper.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/test-utils/src/wrapper.js b/packages/test-utils/src/wrapper.js index bf8f44acd..569269894 100644 --- a/packages/test-utils/src/wrapper.js +++ b/packages/test-utils/src/wrapper.js @@ -31,7 +31,7 @@ export default class Wrapper implements BaseWrapper { +vm: Component | void _emitted: { [name: string]: Array> } _emittedByOrder: Array<{ name: string, args: Array }> - +element: Element | HTMLInputElement + +element: Element +options: WrapperOptions isFunctionalComponent: boolean rootNode: VNode | Element @@ -831,18 +831,20 @@ export default class Wrapper implements BaseWrapper { /** * Simulates event triggering - * @param type {string} - * @param [options] {Object} - * @returns {*} - * @private */ - __simulateTrigger(type, options) { + __simulateTrigger(type: string, options?: Object): void { const regularEventTrigger = (type, options) => { const event = createDOMEvent(type, options) return this.element.dispatchEvent(event) } - const focusEventTrigger = (type, options) => this.element.focus(options) + const focusEventTrigger = (type, options) => { + if (this.element instanceof HTMLElement) { + return this.element.focus() + } + + regularEventTrigger(type, options) + } const triggerProcedureMap = { focus: focusEventTrigger,