Skip to content

Créer ses premiers tests fr FR

rocambille edited this page Jun 4, 2026 · 4 revisions

Résumé : Apprenez à tester votre application, en commençant par les requêtes les plus simples, en gérant les jetons de sécurité, et enfin en comprenant pourquoi StartER utilise un système de "contrats" avancé.

Le continuum de tests

StartER utilise une architecture de tests pilotés par contrat (située dans le dossier tests/contracts/) pour vérifier automatiquement la base de code. Bien que ce système soit efficace, il est abstrait et n'est pas recommandé pour les débutants.

Lorsque vous construisez vos propres fonctionnalités, la meilleure façon d'apprendre est d'écrire des tests "linéaires" standards en utilisant vitest, supertest et testing-library. Explorons comment les tests évoluent du plus simple au plus complexe.

Niveau 1 : le test le plus simple (GET)

La façon la plus simple de tester votre API est avec une requête GET, car elle ne modifie pas de données et ne nécessite pas de jetons de sécurité.

Créez un fichier juste à côté de votre repository, par exemple src/express/modules/group/group.test.ts :

import express from "express";
import request from "supertest";

import routes from "../../routes";

const app = express();
app.use(routes);

describe("API Group", () => {
  it("devrait récupérer tous les groupes avec succès", async () => {
    // 1. Arrange & Act : Envoyer une requête GET
    const response = await request(app).get("/api/groups");

    // 2. Assert : Vérifier le code de statut et le corps
    expect(response.status).toBe(200);
    expect(Array.isArray(response.body)).toBe(true);
  });
});

Tip

Où placer vos tests ?

  • Colocalisation : gardez group.test.ts à côté de groupActions.ts pour un contexte immédiat.
  • Dossier dédié : déplacez tous vos tests dans un dossier tests/ central (par exemple tests/react/components) pour garder vos dossiers sources propres. Les deux sont de bonnes pratiques ! StartER vous laisse choisir ce qui convient le mieux à votre flux de travail.

Niveau 2 : mutation et CSRF (POST)

Lorsque vous essayez de tester une requête POST, PUT ou DELETE, vous rencontrerez probablement une erreur 403 Forbidden. Pourquoi ?

StartER impose une protection CSRF par double-submit cookie sur toutes les routes de mutation pour prévenir les attaques malveillantes. Pour tester une requête POST, vous devez simuler manuellement cette protection en envoyant un cookie et une en-tête correspondants.

it("devrait créer un groupe avec succès", async () => {
  // 1. Arrange : Créer un faux jeton CSRF
  const fakeCsrfToken = "test-csrf-token";

  // 2. Act : Envoyer la requête POST avec le jeton dans le cookie ET dans l'en-tête
  const response = await request(app)
    .post("/api/groups")
    .set("Cookie", [`__Host-x-csrf-token=${fakeCsrfToken}`])
    .set("X-CSRF-Token", fakeCsrfToken)
    .send({ name: "Mon Groupe de Test" });

  // 3. Assert
  expect(response.status).toBe(201);
  expect(response.body).toHaveProperty("insertId");
});

Niveau 2.5 : tester l'interface (React)

Tester des composants React implique de rendre le composant et de simuler les interactions de l'utilisateur. Pour les composants qui dépendent du routage (comme les liens ou la navigation), vous devriez utiliser un Route Stub.

Créez votre fichier de test à côté de votre composant, par exemple src/react/components/group/GroupCreate.test.tsx :

import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { createRoutesStub } from "react-router"; 
import { vi } from "vitest";

import GroupCreate from "./GroupCreate";

describe("Composant GroupCreate", () => {
  it("devrait soumettre le formulaire correctement", async () => {
    // 1. Arrange : Mocker manuellement l'API fetch du navigateur
    const fetchMock = vi.spyOn(global, "fetch").mockResolvedValue({
      status: 201,
      json: async () => ({ insertId: 1 }),
    } as Response);

    const user = userEvent.setup();

    // 2. Act : Créer un "route stub" pour le composant
    const Stub = createRoutesStub([
      { path: "/groups/new", Component: GroupCreate }
    ]);

    render(<Stub initialEntries={["/groups/new"]} />);

    // 3. Act : Simuler l'interaction utilisateur
    await user.type(screen.getByLabelText(/name/i), "Mon Groupe de Test");
    await user.click(screen.getByRole("button", { name: /submit/i }));

    // 4. Assert : Vérifier l'appel fetch
    expect(fetchMock).toHaveBeenCalledWith(
      expect.stringContaining("/api/groups"),
      expect.objectContaining({ method: "POST" })
    );
  });
});

Niveau 3 : le point de bascule (pourquoi les contrats existent)

Maintenant, imaginez que votre route POST /api/groups nécessite également que l'utilisateur soit authentifié.

Pour tester cela manuellement, vous devriez :

  1. Générer un faux jeton JWT en utilisant jsonwebtoken.
  2. Simuler (mock) la base de données pour s'assurer que l'utilisateur existe.
  3. Passer le cookie __Host-auth=jwt.
  4. Passer le cookie __Host-x-csrf-token=abcd.
  5. Passer l'en-tête X-CSRF-Token: abcd.

La même chose s'applique à React : à mesure que vos composants font plus d'appels API, simuler fetch pour chaque test devient un fardeau considérable.

C'est exactement pour cela que le système de contrats existe.

Le système de contrats abstrait la répétition de la mise en place de l'authentification, du CSRF et des états de la base de données. Il vous permet de définir le comportement une seule fois de manière centralisée et de l'utiliser pour vérifier automatiquement votre backend et votre frontend.

Lancer vos tests

Vitest est configuré pour trouver automatiquement tout fichier se terminant par .test.ts ou .test.tsx. Pour exécuter vos tests, lancez :

npm run test

Voir aussi

Clone this wiki locally