Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 28 additions & 2 deletions packages/test-utils/src/wrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -829,6 +829,33 @@ export default class Wrapper implements BaseWrapper {
return this.element.textContent.trim()
}

/**
* Simulates event triggering
*/
__simulateTrigger(type: string, options?: Object): void {
const regularEventTrigger = (type, options) => {
const event = createDOMEvent(type, options)
return this.element.dispatchEvent(event)
}

const focusEventTrigger = (type, options) => {
if (this.element instanceof HTMLElement) {
return this.element.focus()
}

regularEventTrigger(type, options)
}

const triggerProcedureMap = {
focus: focusEventTrigger,
__default: regularEventTrigger
}

const triggerFn = triggerProcedureMap[type] || triggerProcedureMap.__default

return triggerFn(type, options)
}

/**
* Dispatches a DOM event on wrapper
*/
Expand Down Expand Up @@ -869,8 +896,7 @@ export default class Wrapper implements BaseWrapper {
return nextTick()
}

const event = createDOMEvent(type, options)
this.element.dispatchEvent(event)
this.__simulateTrigger(type, options)
return nextTick()
}
}
57 changes: 57 additions & 0 deletions test/resources/components/component-with-multiple-inputs.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<template>
<div>
<input
v-for="index of 5"
@focus="onFocus(index)"
:id="index"
:data-test-position="index"
:ref="refNameByIndex(index)"
:key="index"
type="text"
/>
</div>
</template>

<script>
export default {
name: 'component-with-multiple-inputs',
data: () => ({ activeInputIndex: null }),
computed: {
inputRefAtIndex() {
return index => this.$refs[this.refNameByIndex(index)]
}
},

methods: {
refNameByIndex(index) {
return `input${index}`
},

returnToLastSelectedInput() {
return this.focusInput(this.inputRefAtIndex(this.activeInputIndex))
},

onFocus(index) {
const isOdd = Boolean(index % 2)
if (isOdd) {
return this.returnToLastSelectedInput()
}
this.activeInputIndex = index
},

focusInput(inputRef) {
if (!inputRef) {
return
}
const [input] = inputRef
input.focus()
}
},

mounted() {
this.focusInput(this.focusInput(this.inputRefAtIndex(2)))
}
}
</script>

<style scoped></style>
24 changes: 24 additions & 0 deletions test/specs/wrapper-array/trigger.spec.js
Original file line number Diff line number Diff line change
@@ -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()
Expand Down Expand Up @@ -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 = [
Expand Down