Passer au contenu

Tester les composants asynchrones

Utilisation de flushPromises

Lors du test de composants qui effectuent des opérations asynchrones, vous aurez besoin d’attendre que ces opérations se terminent avant de vérifier les résultats. @vue/test-utils fournit une fonction utilitaire flushPromises qui attend que toutes les promesses en attente soient résolues.

import { mount } from '@vue/test-utils'
import { flushPromises } from '@vue/test-utils'
import { describe, it, expect, vi } from 'vitest'
import UserProfile from '@/components/UserProfile.vue'
import { fetchUserData } from '@/api/user'
// Mock le module d'API
vi.mock('@/api/user', () => ({
fetchUserData: vi.fn()
}))
describe('UserProfile.vue', () => {
it('loads and displays user data', async () => {
// Préparer le mock avec les données
const userData = { name: 'John Doe', email: '[email protected]' }
fetchUserData.mockResolvedValue(userData)
const wrapper = mount(UserProfile)
// Initialement, devrait afficher un loader
expect(wrapper.find('.loading').exists()).toBe(true)
expect(wrapper.find('.user-info').exists()).toBe(false)
// Attendre que toutes les promesses soient résolues
await flushPromises()
// Maintenant le loader devrait être caché et les infos utilisateur affichées
expect(wrapper.find('.loading').exists()).toBe(false)
expect(wrapper.find('.user-info').exists()).toBe(true)
expect(wrapper.text()).toContain('John Doe')
expect(wrapper.text()).toContain('[email protected]')
})
})

Comment fonctionne flushPromises

La fonction flushPromises est particulièrement utile car elle:

  1. Attend que toutes les promesses en attente dans la file d’attente des microtâches soient résolues
  2. Met à jour le DOM après la résolution des promesses
  3. Permet de tester l’état du composant après une opération asynchrone

C’est une alternative à l’utilisation de setTimeout qui peut être moins fiable et moins claire.

Tester les erreurs asynchrones

Vous pouvez également tester le comportement de votre composant lorsqu’une opération asynchrone échoue:

it('handles error state when API call fails', async () => {
// Configurer le mock pour rejeter la promesse
fetchUserData.mockRejectedValue(new Error('API Error'))
const wrapper = mount(UserProfile)
// Attendre que toutes les promesses soient résolues (ou rejetées)
await flushPromises()
// Vérifier que le message d'erreur s'affiche
expect(wrapper.find('.error-message').exists()).toBe(true)
expect(wrapper.text()).toContain('Une erreur est survenue')
})

Tester avec Vue Router et navigation asynchrone

Si votre composant utilise Vue Router et effectue des navigations, vous devrez également attendre que ces navigations soient terminées:

import { mount } from '@vue/test-utils'
import { flushPromises } from '@vue/test-utils'
import { createRouter, createWebHistory } from 'vue-router'
import { describe, it, expect } from 'vitest'
import NavComponent from '@/components/NavComponent.vue'
// Créer un router de test
const router = createRouter({
history: createWebHistory(),
routes: [/* vos routes */]
})
it('navigates when button is clicked', async () => {
const wrapper = mount(NavComponent, {
global: {
plugins: [router]
}
})
// Cliquer sur un bouton qui déclenche une navigation
await wrapper.find('button').trigger('click')
// Attendre que la navigation soit terminée
await flushPromises()
// Vérifier que la navigation a eu lieu
expect(router.currentRoute.value.path).toBe('/expected-path')
})