Skip to content

Commit d9d30d1

Browse files
committed
Fix for trigger('focus')
Added test case and the fix for wrapper trigger
1 parent 3536ade commit d9d30d1

File tree

3 files changed

+107
-2
lines changed

3 files changed

+107
-2
lines changed

packages/test-utils/src/wrapper.js

+26-2
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,31 @@ export default class Wrapper implements BaseWrapper {
829829
return this.element.textContent.trim()
830830
}
831831

832+
/**
833+
* Simulates event triggering
834+
* @param type
835+
* @param options
836+
* @returns {*}
837+
* @private
838+
*/
839+
__simulateTrigger(type, options) {
840+
const regularEventTrigger = (type, options) => {
841+
const event = createDOMEvent(type, options)
842+
return this.element.dispatchEvent(event)
843+
}
844+
845+
const focusEventTrigger = (type, options) => this.element.focus(options)
846+
847+
const triggerProcedureMap = {
848+
focus: focusEventTrigger,
849+
__default: regularEventTrigger
850+
}
851+
852+
const triggerFn = triggerProcedureMap[type] || triggerProcedureMap.__default
853+
854+
return triggerFn(type, options)
855+
}
856+
832857
/**
833858
* Dispatches a DOM event on wrapper
834859
*/
@@ -869,8 +894,7 @@ export default class Wrapper implements BaseWrapper {
869894
return nextTick()
870895
}
871896

872-
const event = createDOMEvent(type, options)
873-
this.element.dispatchEvent(event)
897+
this.__simulateTrigger(type, options)
874898
return nextTick()
875899
}
876900
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<template>
2+
<div>
3+
<input
4+
v-for="index of 5"
5+
@focus="onFocus(index)"
6+
:id="index"
7+
:data-test-position="index"
8+
:ref="refNameByIndex(index)"
9+
:key="index"
10+
type="text"
11+
/>
12+
</div>
13+
</template>
14+
15+
<script>
16+
export default {
17+
name: 'component-with-multiple-inputs',
18+
data: () => ({ activeInputIndex: null }),
19+
computed: {
20+
inputRefAtIndex() {
21+
return index => this.$refs[this.refNameByIndex(index)]
22+
}
23+
},
24+
25+
methods: {
26+
refNameByIndex(index) {
27+
return `input${index}`
28+
},
29+
30+
returnToLastSelectedInput() {
31+
return this.focusInput(this.inputRefAtIndex(this.activeInputIndex))
32+
},
33+
34+
onFocus(index) {
35+
const isOdd = Boolean(index % 2)
36+
if (isOdd) {
37+
return this.returnToLastSelectedInput()
38+
}
39+
this.activeInputIndex = index
40+
},
41+
42+
focusInput(inputRef) {
43+
if (!inputRef) {
44+
return
45+
}
46+
const [input] = inputRef
47+
input.focus()
48+
}
49+
},
50+
51+
mounted() {
52+
this.focusInput(this.focusInput(this.inputRefAtIndex(2)))
53+
}
54+
}
55+
</script>
56+
57+
<style scoped></style>

test/specs/wrapper-array/trigger.spec.js

+24
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import { compileToFunctions } from 'vue-template-compiler'
22
import ComponentWithEvents from '~resources/components/component-with-events.vue'
3+
import ComponentWithMultipleInputs from '~resources/components/component-with-multiple-inputs.vue'
34
import { describeWithShallowAndMount } from '~resources/utils'
45

6+
const assertElementIsFocused = element =>
7+
expect(document.activeElement.id).toEqual(element.id)
8+
59
describeWithShallowAndMount('trigger', mountingMethod => {
610
it('causes click handler to fire when wrapper.trigger("click") is called on a Component', async () => {
711
const clickHandler = jest.fn()
@@ -34,6 +38,26 @@ describeWithShallowAndMount('trigger', mountingMethod => {
3438
expect(keydownHandler).toHaveBeenCalled()
3539
})
3640

41+
it('should really focus element when trigger focus was called', async () => {
42+
const wrapper = mountingMethod(ComponentWithMultipleInputs, {
43+
attachTo: document.body
44+
})
45+
46+
assertElementIsFocused(wrapper.get('[data-test-position="2"]').element)
47+
48+
await wrapper.get('[data-test-position="4"]').trigger('focus')
49+
50+
assertElementIsFocused(wrapper.get('[data-test-position="4"]').element)
51+
52+
await wrapper.get('[data-test-position="3"]').trigger('focus')
53+
54+
assertElementIsFocused(wrapper.get('[data-test-position="4"]').element)
55+
56+
await wrapper.get('[data-test-position="2"]').trigger('focus')
57+
58+
assertElementIsFocused(wrapper.get('[data-test-position="2"]').element)
59+
})
60+
3761
it('throws an error if type is not a string', () => {
3862
const wrapper = mountingMethod(ComponentWithEvents)
3963
const invalidSelectors = [

0 commit comments

Comments
 (0)