Tester du code react — Formation Apprendre React

Dans ce chapitre nous allons faire une petite aparté sur les tests unitaires dans le cadre de React. Comment tester les hooks et nos composants ?

Configuration de l’environnement

Dans le cadre de react-dom, nos tests auront besoin d’interagir avec le DOM, on pourra utiliser jsdom pour que notre code fonctionne sur NodeJS. Dans le cadre de vitest, on l’ajoutera à notre configuration :

import { defineConfig } from 'vite'  
import react from '@vitejs/plugin-react'  

// https://vitejs.dev/config/  
export default defineConfig({  
  plugins: [react()],  
  test: {  
    environment: 'jsdom',  
    setupFiles: './test/setup.js'  
  }  
})

Dans le fichier setup.js on s’assurera que notre environnement est bien nettoyé après chaque test.

import {afterEach} from "vitest";  
import {cleanup} from "@testing-library/react";  

afterEach(() => {  
    cleanup()  
})

Tester un hook

Une hook est une fonction qui ne peut être exécuté que dans le contexte d’un composant. On pourra utiliser la librairie @testing-library/react qui nous offrira 2 méthodes utiles en lien avec les tests de hooks

  • renderHook(), qui permet d’exécuter le code d’un hook en renvoyant le résultat dans un objet.
  • act(), qui permet de faire un changement d’état (appeler un setter par exemple).

Voici un petit exemple d’utilisation :

import {describe, it, expect} from "vitest";  
import {useIncrement} from "../src/hooks/useIncrement.js";  
import {act, renderHook} from "@testing-library/react";  

describe('useIncrement', () => {  
    it('should use the default value', () => {  
        const {result} = renderHook(() => useIncrement({base: 5}))  
        expect(result.current.count).toBe(5)  
    })  
    it('should increment value', () => {  
        const {result} = renderHook(() => useIncrement({base: 5}))  
        act(() => result.current.increment())  
        expect(result.current.count).toBe(6)  
    })  
    it('should not bypass max', () => {  
        const {result} = renderHook(() => useIncrement({base: 5, max: 7}))  
        act(() => result.current.increment())  
        act(() => result.current.increment())  
        act(() => result.current.increment())  
        act(() => result.current.increment())  
        expect(result.current.count).toBe(7)  
    })  
})

Tester un composant

Pour tester un composant le plus simple est de vérifier que la structure HTML corresponde à ce que l’on attend. On pourra aussi utiliser la librairie @testing-library/user-event pour simuler les évènements navigateur.

import {describe, it, expect} from "vitest";  
import {render, screen} from "@testing-library/react";  
import {Alert} from "../src/components/Alert.jsx";  
import {userEvent} from "@testing-library/user-event";  

describe('<Alert>', () => {  
    it('should render correctly', () => {  
        const {container} = render(<Alert type="danger">Erreur</Alert>)  
        expect(container.firstChild).toMatchInlineSnapshot()  
    })  
    it('should close the alert on click', async () => {  
        const {container} = render(<Alert type="danger">Erreur</Alert>)  
        await userEvent.click(screen.getByText('Fermer'))  
        expect(container.firstChild).toMatchInlineSnapshot('null')  
    })  
})