Description
I have a scenario where I want to test that interacting with a component (that results in emitting a v-model event) does not lead to a state change in the internals of a component.
Here is a simplified version of what I'm trying to do
import { mount } from '@vue/test-utils'
import { defineComponent, h } from 'vue'
const Foo = defineComponent({
name: 'Foo',
props: {
foo: String,
},
emits: ['update:foo'],
setup (props, ctx) {
return () => h('div', {
onClick: () => {
ctx.emit('update:foo', 'baz')
},
}, props.foo)
}
})
test('something', async () => {
const wrapper = mount(Foo, {
props: {
foo: 'bar',
}
})
expect(wrapper.text()).toEqual('bar')
await wrapper.trigger('click')
expect(wrapper.text()).toEqual('bar')
})
Currently this fails on the second expect with a received value of baz
. This to me feels very strange and unintuitive. The component has emitted an event, but I have done nothing to catch it and subsequently update state to trigger a re-render, as I need to do in a real Vue app. Yet the props have been modified.
The change was introduced in this PR #393. With this change, components under test do not behave in the same way as in normal operation.
edit:
Something a bit closer to real usage would be if you could perhaps do something like this, if you need the 2-way binding to be automatic.
const wrapper = mount(Foo, {
props: {
foo: 'bar',
onUpdateFoo: async (foo) => {
await wrapper.setProps({ foo })
}
}
})
Replacing the code from the PR with the following works, but I've no idea how stable it is.
var eventFnName = `on${event.split(':').map(vue.capitalize).join('')}`
if (wrapperVm.attrs[eventFnName]) {
wrapperVm.attrs[eventFnName](...args)
}