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.

1 answer

  • answered 2022-05-07 02:01 tony19

    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);
    });
    

    demo

How many English words
do you know?
Test your English vocabulary size, and measure
how many words do you know
Online Test
Powered by Examplum