test-utils icon indicating copy to clipboard operation
test-utils copied to clipboard

Feature request: trigger does not work on vue components

Open ghost opened this issue 1 year ago • 5 comments

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')

ghost avatar Jun 06 '23 21:06 ghost

@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?

cexbrayat avatar Jun 07 '23 09:06 cexbrayat

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.

lmiller1990 avatar Jun 07 '23 22:06 lmiller1990

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.

ghost avatar Jun 08 '23 15:06 ghost

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?

freakzlike avatar Jun 08 '23 15:06 freakzlike

I also like wrapper.emit() 👍

cexbrayat avatar Jun 12 '23 06:06 cexbrayat