Search code examples
vue.jsaxiosvitestvue-testing-library

Test assertions fail in vitest because vue component DOM is not updating after an axios request in a method


On a button click, the text in a div is supposed to be updated with data from an axios request. It works but the test fails (the text in the div doesn't get updated in the test). A basic representation of my code:

Component.js:

<template>
 <button data-testid="button" @click="getData"> Get data </button>
 <div>{{dataToDisplay}}</div>
</template>

<script setup>
import {ref} from 'vue';
import axios from 'axios';

const dataToDisplay = ref('');

function getData() {
 axios.post('/route')
  .then((response) => {
    dataToDisplay.value = response.data;
    console.log(dataToDisplay.value);
  })
}
</script>

In Component.test.js

import { render, fireEvent } from '@testing-library/vue';
import axios from 'axios';

vi.mock('axios');

test('text is rendered from axios request', async () => {
  const { queryByTestId, getByText } = render(Component);

  axios.post.mockResolvedValue({
    status: 200,
    data: 'new text',
  });

  fireEvent.click(queryByTestId('button'));
  
  await nextTick();

  getByText('new text');
});

The test fails because the DOM does not get updated. However I know that the code in the "then" block runs because the updated value of "dataToDisplay" is logged in the console.

I have also tried using "await flushPromises()" from '@vue/test-utils' but the component DOM still doesn't get updated.

After some searching, I tried using setTimeout() but that doesn't work either, the code in the setTimeout block doesn't get executed at all.

Any help is much appreciated. Thank you.


Solution

  • I was able to solve the problem by wrapping the assertion in a "waitFor" function like so:

    import { waitFor } from '@testing-library/vue';
    
    await waitFor(() => {
     getByText('new text');
    });