'vitest test await async completion of onMounted callback in vue3 component
I'm playing around with Vitest and want to wait for the completion of a couple mocked fetches in the onMounted lifecycle hook in my component:
My test:
import { mount } from '@vue/test-utils';
import HelloWorld from './HelloWorld.vue';
import { mockGet } from 'vi-fetch';
import 'vi-fetch/setup';
mockGet('api/welcome-message').willResolve('Welcome message from vitest');
mockGet('api/players').willResolve(['Mario', 'Luigi']);
test('the players have been rendered', async () => {
const wrapper = mount(HelloWorld);
const lastPlayer = await wrapper.findAll('.player');
expect(lastPlayer).toHaveLength(2);
});
My component script:
<script setup lang="ts">
import { onMounted, ref } from 'vue';
const apiMessage = ref('');
const players = ref<string[]>([]);
onMounted(async () => {
const fetchMessage = fetch('api/welcome-message')
.then((res) => res.text())
.then((message: string) => (apiMessage.value = message));
const fetchPlayers = fetch('api/players')
.then((res) => res.json())
.then((playersRes: string[]) => (players.value = playersRes));
});
</script>
The test fails because, I assume, the code running in onMounted doesn't have time to complete before the test looks for all .player <li> elements (rendered with a v-for) off of the players ref. How can I ask vitest to wait for the responses from each of these fetches before calling the test a failure.
Thanks.
Solution 1:[1]
The fetch Promises resolve in the next macro tick, which can be awaited like this:
test('...', async() => {
?
await new Promise(r => setTimeout(r));
})
Or you can use Vue Test Utils' utility for this:
import { flushPromises } from '@vue/test-utils';
test('...', async() => {
?
await flushPromises();
})
Add that line before running any assertions:
?
import { mount, flushPromises } from '@vue/test-utils';
import HelloWorld from './HelloWorld.vue';
import { mockGet } from 'vi-fetch';
import 'vi-fetch/setup';
mockGet('api/welcome-message').willResolve('Welcome message from vitest');
mockGet('api/players').willResolve(['Mario', 'Luigi']);
test('the players have been rendered', async () => {
const wrapper = mount(HelloWorld);
?
await flushPromises();
const lastPlayer = await wrapper.findAll('.player');
expect(lastPlayer).toHaveLength(2);
});
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | tony19 |
