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