I have this project structure:
/App.vue
|-components/CoponentA.vue
|-components/CoponentB.vue
In App.vue
the ComponentB
is not mounted until ComponentA
emits an event:
<!-- App.vue -->
<template>
<ComponentA @onMessage="onMessage"/>
<ComponentB v-if="message"/>
</template>
<script setup lang="ts">
import { type Ref, ref } from 'vue';
import ComponentA from '@/components/ComponentA.vue';
import ComponentB from '@/components/ComponentB.vue';
const message: Ref<String | undefined> = ref();
const onMessage = (messageParam: String): void => {
message.value = messageParam;
};
</script>
In my test I am trying to check this but I am not able to trigger a custom event on my test. The documentation says trigger
is only for DOM events :/
My test code:
// App.spec.ts
import { describe, it, expect } from 'vitest'
import { shallowMount } from '@vue/test-utils'
import App from '@/App.vue'
import ComponentA from '@/components/ComponentA.vue'
import ComponentB from '@/components/ComponentB.vue'
import { nextTick } from 'vue'
describe('App', () => {
it("renders the ComponentA component", (): void => {
const wrapper = shallowMount<App>(App);
expect(wrapper.findComponent(ComponentA).exists()).toBe(true);
}); // -> works
it("no renders the ComponentB component", (): void => {
const wrapper = shallowMount<App>(App);
expect(wrapper.findComponent(ComponentB).exists()).toBe(false);
}); // -> works
it('renders ComponentB when event emitted', async () => {
const wrapper = shallowMount<App>(App);
wrapper.findComponent(ComponentA).trigger('onMessage', 'MESSAGE');
await nextTick();
expect(wrapper.findComponent(ComponentB).exists()).toBe(true);
}) // -> fails
})
Full components code:
<!-- Component A -->
<template>
<h2>Component A</h2>
</template>
<script setup lang="ts">
import { onMounted } from 'vue';
const emit = defineEmits<{
onMessage: [message: string]
}>();
onMounted(async () => {
setTimeout(() => {
emit("onMessage", "Loading finished!");
}, 1000);
});
</script>
and:
<!-- Component B -->
<template>
<h2>Component B</h2>
</template>
The only way to do this is using:
wrapper.vm.$emit()
In this case the working test will be like this:
it('renders ComponentB when event emitted', async () => {
const wrapper = shallowMount<App>(App);
const component = wrapper.findComponent(ComponentA);
component.vm.$emit('onMessage', 'MESSAGE');
await nextTick();
expect(wrapper.findComponent(ComponentB).exists()).toBe(true);
});