In my Vue 3 component I have a link that uses @click.prevent to call a method that emits and event. I'm unable to figure out why my attempts to test if this method is called or event is emitted fail.
Component:
<script setup lang="ts">
const emit = defineEmits<{
closeMinicart: any[];
}>();
const closeDialog = (ev: Event) => {
console.log('------------- close dialog ----------------');
emit('closeMinicart');
};
</script>
<template>
<a
href="#"
@click.prevent="closeDialog($event)">
Continue shopping
</a>
</template>
Test:
it('should emit `closeDialog` when clicked', async () => {
const user = userEvent.setup();
const { emitted } = render(EmptyCart);
const el = screen.getByText(/Continue shopping/i);
await user.click(el);
await waitFor(() => {
expect(emitted()).toHaveProperty('closeMinicart');
})
});
It fails with this message:
FAIL src/components/EmptyCart.test.ts > Continue shopping link > should emit `closeDialog` when clicked
AssertionError: expected { pointerover: [ [ …(1) ] ], …(11) } to have property "closeMinicart"
But the console.log inside the function is always printed out in the terminal.
I've tried using the plain vue-test-utils with mount and adding wrapper.vm.$nextTick() but that doesn't work for me either.
I tried changing the link to a button as well as removing the .prevent (putting preventDefault in the method) but they don't work either.
I also attempted to create a spy on the closeDialog method like so:
it('...', () => {
//...
const spy = vi.spyOn(wrapper.vm, 'closeDialog');
//...
expect(spy).toHaveBeenCalled();
But I kept getting errors talking about not being able to call a spy on undefined or something similar.
Edit
An even more bare-bones example. Making my component look like this:
<script setup lang="ts">
import { onMounted } from 'vue';
const emit = defineEmits<{
(e: 'myEvent'): void;
(e: 'foobar', value: string): void;
}>();
onMounted(() => {
emit('foobar', 'something to talk about');
});
</script>
<template>
<a href="#"
@click.prevent="$emit('myEvent')">
Continue shopping
</a>
</template>
With this test:
it('should emit `myEvent` when clicked', async () => {
const wrapper = mount(MyComponent);
expect(wrapper.emitted()).toHaveProperty('foobar');
await wrapper.find('a').trigger('click');
expect(wrapper.emitted()).toHaveProperty('myEvent');
});
I get:
AssertionError: expected { click: [ [ …(1) ] ] } to have property "foobar"
If I console.log JSON.stringify emitted, it returns this:
{"click":[[{"isTrusted":false,"_vts":1691539798806}]]}
describeblock.