Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(trigger('focus')) added natural to jsdom behavior #1777

Merged
merged 4 commits into from
Feb 10, 2021
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.
Jump to
Jump to file
Failed to load files.
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