test-utils
test-utils copied to clipboard
Feature request: trigger does not work on vue components
Describe the bug
I just kinda expected vue test utils to be able to trigger Vue component events out of the box. VueWrapper does not have a trigger implementation that works for Vue components. You have to use $emit
on the vm instance.
To Reproduce https://stackblitz.com/edit/github-kdgtxj?file=src%2Fcomponents%2FHelloWorld.vue,src%2FApp.vue,src%2Fcomponents%2F__tests__%2FHelloWorld.spec.ts,src%2F__tests__%2FApp.spec.ts
Expected behavior
mount(VueComponent).findComponent({ name: 'VueComponent' }).trigger('vueComponentEvent')
should work like
mount(VueComponent).findComponent({ name: 'VueComponent' }).vm.$emit('vueComponentEvent')
@micDropper I think this is because this was historically the case with VTU v1 (for Vue 2).
As I was not around at that time I don't know if there is a specific reason that we don't support this.
@freakzlike @lmiller1990 do you think this would be good idea?
Historical context can be found in issues such as:
https://github.com/vuejs/vue-test-utils/issues/145 https://github.com/vuejs/vue-test-utils/issues/1239 https://github.com/vuejs/vue-test-utils/issues/1588 https://github.com/vuejs/vue-test-utils/issues/1952
https://github.com/vuejs/vue-test-utils/issues/1588 probably has the best discussion. Historically, trigger
is for things users can do, like clicking, focusing, etc - DOM events.
Is there a compelling use case for manually emitting an event? It's not something a user can do. In general, I recommend causing the event to be emitted like a user, instead of emitting it manually. If we did add this, I think we'd be better to make a wrapper.emit()
alias, as opposed to overloading trigger
.
This would be used when testing components that emit events not triggered by user interaction. Perhaps they would be triggered by a timer, as in my demo, or emit events as it performs other autonomous behaviors (animation, external/internal condition becomes met, etc).
In my case, it'd be useful for testing heavyweight js libraries with thin vue wrappers that emit their own events (think ag-grid, vee-validate, etc). Ag-grid emits a gridReady
event containing its custom grid api when its grid is ready. Vee-validate has a similar formReady
event that contains their form api. It'd be nice to stub those heavy components out and have an official api to trigger their events to test how our code handles it without having to fully mount their library (often expensive).
I agree with the preference for wrapper.emit()
- overloading trigger may potentially be a breaking change if someone calls trigger on a VueWrapper that is capable of emitting an event, say a declared blur
event, that potentially overlaps with the events of its root HTMLElement.
Using one trigger
function for both cases might not be possible. I like the idea of having wrapper.emit()
. Feels better integrated instead of wrapper.vm.$emit()
. Not sure if we might get some difficulties with the typings?
I also like wrapper.emit()
👍