1.0.0-beta.24
https://codesandbox.io/s/61jzxnovnk
Trying to test click when using VIcon
I reproduce some scenarii :
it works when shallowMounting without using Vuetify, it works when mounting using Vuetify
I doesn't work when shallowMounting with Vuetify when selecting Component, by ref, by name
a way to trigger click on stub when shallowMount
it doesn't work
Same problem here. I guess this is because Vuetify components are now seen as child components and stubs it therefore.
So the question is: "How could it be possible to trigger event on stubbed components?"
A temporary workaround is to stub the component manually:
const Stub = {
template: '<div />'
}
const wrapper = shallowMount(TestComponent, {
stubs: {
'VIcon': Stub
}
})
wrapper.find(Stub)
I have same problem on <v-btn> & <v-textarea>.
My workaround is changing data same as click action.
@eddyerburgh is this what you were thinking for a workaround? https://codesandbox.io/s/42rxjjvz44
Not sure if I implemented your suggestion how you intended.
@eddyerburgh : to me, the issue is not fixed in beta 25.
On my CodeSandbox, I update VueTestUtils version 25, it doesn't solve anything
Are you sure, this issue is fixed?
Confirming. v25 didn't fix stubs problem
@trollepierre did you find some solution with shallowMount?
No. I had to mount. :'(
@eddyerburgh is it possible to reopen this issue?
@eddyerburgh , thank you for your suggestion, but it does not help in the case, when there is a click handler passed as prop to parent component:
<div>
I am parent
<v-btn @click="callbackFromProp"></v-btn>
</div>
export default {
props: {
callbackFromProp: Function
}
}
@p1pchenk0 In that case you need to supply a stub that calls the listener on the root element:
const wrapper = shallowMount(TestComponent, {
stubs: {
'v-icon': {
template: '<div class="v-icon" @click="$listeners.click" />'
}
}
})
wrapper.find('.icon').trigger('click')
I don't think we should add all listeners to the auto stubs. With normal components we use the on value of the component that's being stubbed, but not all components expose this info.
I'm going to close this issue, since it's not a bug. Let me clear up some misconceptions.
shallowMount only stubs components that are registered. This is to avoid false positives where components are stubbed and rendered in tests, but can't render in production.
The only guaranteed ways to select an auto stubbed component is to use a component selector:
const wrapper = shallowMount(TestComponent)
wrapper.find(Icon)
Or a ref selector:
const wrapper = shallowMount(TestComponent)
wrapper.find({ ref: 'icon' })
If you don't have access to the component, you must use the stubs option, and use the stub as a selector:
const Stub = { template: '<div />' }
const wrapper = shallowMount(TestComponent, {
stubs: { icon: Stub }
})
wrapper.find(Stub)
If anyone is still trying to figure this out and is confused by the conversation in this issue, I found the solution in the documentation. In short, instead of triggering through the wrapper API like this:
wrapper.find(ChildComponent).trigger('click')
you should call the vue instance $emit function like this:
wrapper.find(ChildComponent).vm.$emit('click')
Hope that helps.
If anyone is still trying to figure this out and is confused by the conversation in this issue, I found the solution in the documentation. In short, instead of triggering through the wrapper API like this:
wrapper.find(ChildComponent).trigger('click')you should call the vue instance
$emitfunction like this:
wrapper.find(ChildComponent).vm.$emit('click')Hope that helps.
I've used this solution before, but it doesn't seem to work now. On further inspection I noted the following:
// Default stub of a v-text-field (Vuetify) child component
const vTextFieldStub = wrapper.find('v-text-field-stub[name="password"]')
// Output: `Wrapper { isFunctionalComponent: true }`
console.log(vTextFieldStub)
// Output: `undefined`
console.log(vTextFieldStub.vm)
I can't emit the click event because vm is undefined. I assume it is because it is a functional component. How can I emit an event on functional components? Or is it even possible?
Or maybe isFunctionalComponent is a result of the stubbing process? I will have to check.
Here is the result of a v-container (Vuetify) child component stub, which shows that it is not a functional component.
// Output:
//VueWrapper {
// isFunctionalComponent: undefined,
// _emitted: [Object: null prototype] {},
// _emittedByOrder: []
//}
console.log(wrapper.find('v-container-stub'))
I found this question, but I can't seem to get it to work properly.
I think this problem is not solved. could you reopen ?
in my case, I use @click.native Instead of @click it works.
I have a similar issue with .trigger('click') not dispatching a click on a VBtn in a fully mounted component. So instead of wrapper.find(selector).trigger('click') and then asserting that the click called a method, I am dispatching a classic browser click event, eg:
document.querySelector(selector).dispatchEvent(new Event('click'))
Doing it this way makes my assertion pass as expected.
I have the same issue as well (in beta.24)
In my component, the child component I'm targetting is a functional component, and so it can't trigger its custom event by using vm.$emit.
const wrapper = shallowMount(MyComponent);
// ChildComp is a functional component
const childWrapper = wrapper.find({ name: 'ChildComp' });
// cannot trigger with this method, as `vm` is undefined
childWrapper.vm.$emit('customEvt'); // ERROR: cannot read property $emit of undefined
I am running beta 34 and I can't reproduce any of the solutions.
https://vue-test-utils.vuejs.org/guides/#emitting-event-from-child-component
This does not work, the parent component doesn't receive any events and the event handlers don't fire at all.
@lukaVarga document.querySelector(selector) returns undefined for me..
My test:
it('increments the internal counter when the + button is clicked', () => {
const wrap = mount(NumericSpinner)
wrap.find(SpinnerValueChangeButton).vm.$emit('click')
console.log(wrap.emitted())
})
The console.log() outputs [Object: null prototype] {}
@ccarstens beta 34? Do you mean beta 31 (which is the latest version atm), or beta 24?
Regardless, for document.querySelector(foo) to return something, you have to pass the attachToDocument option (see https://vue-test-utils.vuejs.org/api/options.html#attachtodocument) when mounting the component.
I'm currently running beta 31 and I can do wrapper.find(foo).trigger('click') and it works fine for me for all use-cases (including triggering it and checking that the handler was invoked on eg. a Vuetify component, so <v-btn @click="doSth"></v-btn>, or on a classic html element, like <a href="..." @click="doSthElse"></a> for instance).
After having upgraded from beta 29, I in fact had to adjust tests to not use the method I mentioned in my previous comment (document.querySelector(selector).dispatchEvent(new Event('click'))) anymore and had to change it to wrapper.find(selector).trigger('click')
Usually I have a lot of same child components, like buttons, so the implementation wrapper.find(ChildComponent).trigger('click') is not good for that case
If anyone else stumbles on this thread looking for a way to use shallowMount yet still interact with simple ui-components like buttons, this worked for me:
import ComponentBeingTested from 'Component.vue';
import ButtonComponent from 'ButtonComponent.vue';
....
// In a test:
const wrapper = shallowMount(ComponentBeingTested, {
stubs: { ButtonComponent } // use real implementation for this "stub"
});
wrapper.find('.first-button-component').trigger('click');
await wrapper.vm.$nextTick();
Most helpful comment
If anyone is still trying to figure this out and is confused by the conversation in this issue, I found the solution in the documentation. In short, instead of triggering through the wrapper API like this:
wrapper.find(ChildComponent).trigger('click')you should call the vue instance
$emitfunction like this:wrapper.find(ChildComponent).vm.$emit('click')Hope that helps.