IMDW320 - Tests et CI - 01/03/2024 - Tests frontend et end-to-end

Description - Compétences visées

Après avoir abordé les tests unitaires, et d’intégration (dans le cadre d’un backend Express), nous allons aborder d’autres concepts et pratiques, pour compléter la boîte à outils des développeur·euse·s d’applications web full-stack.

  • Tests d’applications frontend (matinée)
  • Tests end-to-end (après-midi)

Les tests frontend seront assez spécifiques à React, mais la bibliothèque utilisée (Testing Library) offre des variantes pour d’autres frameworks, et pour du Vanilla JS. Les compétences acquises seront donc transférables à d’autres contextes.

Les tests end-to-end utiliseront l’outil Webdriver.io, écrit en JavaScript/TypeScript. D’autres outils existent y compris dans l’écosystème JavaScript, et bien sûr pour d’autres stacks.

Point de départ

Un dépôt vous est fourni avec un backend et frontend minimalistes.

Vous allez le forker et le cloner.

Voici son URL : https://gitlab.com/bhubert/express-react-testing-monorepo

Créez une branche dès que vous aurez cloné le dépôt : git checkout -b tests-frontend.

❗️ IMPORTANT ❗️

  • Il vous est demandé de committer et pousser votre travail au fur et à mesure de votre avancée. Cela fera partie de l’évaluation.
  • Dès que vous aurez forké le dépôt, vous pourrez m’envoyer son URL par mail.
  • Dans le README.md n’hésitez pas à préciser vos nom et prénom (s’ils ne sont pas clairement suggérés par votre username GitLab).

1. Matinée : Tests React avec React Testing Library

1.1. Introduction aux Tests React

Objectifs de la session

  • Comprendre l’importance et les bénéfices des tests dans le développement d’applications frontend, et en particulier React.
  • Se familiariser avec les outils et librairies pour tester les composants React, en particulier React Testing Library et Vitest.

Pourquoi tester nos composants React ?

Les points suivants ne sont pas spécifiques : les objectifs restent les mêmes que pour les tests d’une façon générale.

  • Assurance qualité : Les tests garantissent que nos composants se comportent comme attendu, même après des modifications ultérieures du code.
  • Refactoring sécurisé : Avec une suite de tests fiable, nous pouvons refactoriser notre code en toute confiance, sachant que les tests détecteront les régressions potentielles.
  • Documentation : Les tests illustrent comment les composants sont censés être utilisés, servant de documentation vivante pour le code.

Introduction à React Testing Library

  • React Testing Library est une librairie populaire pour tester les composants React de manière “fonctionnelle”, c’est-à-dire en se concentrant sur ce que l’utilisateur final voit et fait, plutôt que sur les détails d’implémentation internes des composants.
  • Elle encourage les bonnes pratiques de testing en permettant de tester les composants “comme si” vous étiez l’utilisateur, ce qui rend les tests plus résilients aux changements de structure interne des composants.

Introduction à Vitest

Lors de la première session dédiée aux tests, nous avons utilisé Jest, dans le contexte de tests unitaires de fonctions et de classes, et de tests d’intégration d’une application backend (Express).

Nous allons utiliser un autre outil, qui a émergé plus récemment, comme alternative à Jest : Vitest.

Pourquoi l’utiliser plutôt que Jest ? Voici quelques éléments de réponse.

  • Configuration simplifiée : Vitest est conçu pour fonctionner de manière transparente avec Vite, offrant une configuration minimale et une intégration aisée dans les projets Vite.
  • Performance : Vitest est réputé pour sa rapidité et son efficacité, profitant de l’architecture moderne de Vite.
  • API familière : Pour ceux qui ont déjà utilisé Jest, Vitest offre une expérience similaire avec une API familière. Cela signifie que les connaissances acquises sur Jest sont largement transférables à Vitest.

Relations entre les différents outils

Lors de la dernière session, nous avons utilisé Jest, à la fois comme test runner et comme bibliothèque d’assertions, là où, avant que Jest ne devienne prédominant, on aurait pu utiliser des outils distincts, tels que Mocha (test runner) et Chai (bibliothèque d’assertions).

Ici c’est Vitest qui va remplir ce rôle de test runner et bibliothèque d’assertions.

Le rôle de React Testing Library (RTL) va être d’interagir avec nos composants React et avec le “DOM” simulé via la bibliothèque jsdom.

RTL va nous permettre, entre autres :

  • d’afficher (render) des composants,
  • de récupérer dans la page les éléments DOM générés par le rendu de ces composants,
  • de simuler des interactions utilisateurs avec ces composants.

1.2. Prise en main de React Testing Library avec un composant simple

Organisation

Les outils ont déjà été configurés, afin de pouvoir nous concentrer sur l’écriture des tests proprement dite.

Ici, nous avons choisi de placer les tests “côte à côte” avec leur System Under Test respectif - c’est à dire les composants testés.

Les fichiers .test.tsx sont donc au même niveau de l’arborescence que les .tsx associés.

C’est une organisation différente de celle que nous avions adoptée pour le backend. Notez que nous aurions pu faire pareil du côté backend. Mais il aurait fallu par exemple exclure les fichiers .test.ts du build TypeScript. Ici, l’outil de build s’en charge, et ne va packager dans le “bundle” JavaScript final que les composants.

Test du composant App

Regardez le fichier frontend/src/App.test.tsx, qui contient un test pour le composant App. N’hésitez pas à regarder le code source de App.tsx en même temps.

// src/App.test.tsx
import { render, screen } from "@testing-library/react";
import App from "./App";

it("renders without crashing", () => {
  // Rendu du composant App dans le DOM virtuel
  render(<App />);

  // Récupération de l'élément titre par son texte
  const titleElement = screen.getByText(/Vite \+ React/i);

  // Assertions pour vérifier la présence du titre et sa classe CSS
  expect(titleElement).toBeInTheDocument();
  expect(titleElement).toHaveClass("App-title");
});

Ce fichier minimaliste nous permet d’aborder quelques points récurrents que nous retrouverons tout au long de nos tests.

  • les imports :

    • de render et screen depuis @testing-library/react (RTL)
    • du composant à tester
  • dans le test :

    • le rendu initial d’un composant
    • la récupération d’un ou plusieurs éléments via des queries (ici screen.getByText())
    • éventuellement (absent ici) la simulation d’interactions avec des éléments
    • et enfin des assertions spécifiques aux tests frontend, utilisant des matchers qui ne sont pas disponibles par défaut avec Jest/Vitest, mais sont fournis par la bibliothèque de matchers jest-dom.

1.3. Exercice : composant Title

  • Title.tsx pour y écrire un composant Title,
  • Title.test.tsx pour écrire les tests.

Le composant Title aura la “spécification suivante”. Ne l’écrivez pas maintenant car vous devrez d’abord écrire le test :

  • Accepter une “prop” title qui vaudra Default Title par défaut,
  • Rendre un h1 ayant pour contenu la prop title passée

Écrivez le test en vous inspirant de celui de App.test.tsx, avec ces variantes :

  • Utilisez screen.getByRole('heading') pour récupérer le titre, plutôt que screen.getByText(). Cette page sur MDN donne une référence de toutes les valeurs possibles pour les rôles ; un rôle est attribué par défaut à certaines balises comme les h1 à h6 (rôle heading) ou button (rôle button) ; on peut également attribuer un rôle explicitement avec l’attribut role, tant que la valeur associée est listée parmi les valeurs possibles dans la documentation mise en lien.

  • Vérifiez que le contenu de ce titre est bien celui attendu avec le “matcher” toHaveTextContent(), qui prend une string comme argument — doc de toHaveTextContent()

  • Écrivez deux tests :

    • un pour le cas où la prop title est passée (le titre affiché doit donc être la valeur passée),
    • un pour le cas où elle n’est pas passée (le titre doit donc être la valeur par défaut de la prop)

Indices

Si vous ne savez pas comment attribuer une “prop” par défaut :

1.4. Exercice : composant ToggleButton

Dans cet exercice, nous allons créer un composant ToggleButton qui change de classe CSS lorsqu’il est cliqué, affectant ainsi sa couleur de fond. Nous testerons également ce comportement avec React Testing Library.

Fichiers à créer

  • ToggleButton.tsx : pour le composant ToggleButton.
  • ToggleButton.test.tsx : pour les tests de ToggleButton.
  • ToggleButton.css : pour définir les classes CSS red, blue et gray.

Définir les styles CSS

Dans ToggleButton.css, définissez les classes pour les couleurs de fond :

.red {
  background-color: red;
}

.blue {
  background-color: blue;
}

/* Pour la partie optionnelle de l'exercice */
.gray {
  background-color: gray;
}

Écrire le test

Commencez par écrire un test pour vérifier le rendu initial du bouton avec la classe red et le texte “Change to blue”.

Dans un premier temps, ce test va échouer et c’est normal, car vous n’aurez pas encore écrit le System Under Test, c’est-à-dire le composant à tester. C’est l’essence du TDD ou Test-Driven Development : écrire un test qui échoue, puis écrire le test pour le faire passer ! Puis répéter au fur et à mesure qu’on ajoute des “exigences” à satisfaire.

ToggleButton.test.tsx :

import { render, screen } from "@testing-library/react";
import ToggleButton from "./ToggleButton";

describe("ToggleButton", () => {
  it('renders with initial class "red" and text "Change to blue"', () => {
    // Votre code ici pour rendre le composant et vérifier la classe et le texte initiaux
  });
});

Vous pouvez utiliser encore la query screen.getByRole pour récupérer le bouton de cette façon :

const buttonElement = screen.getByRole("button", { name: /change to blue/i });

Elle permet de récupérer le bouton :

  • par son rôle (button)
  • en précisant également son contenu textuel, ici avec une regex (modificateur i pour case-insensitive), ce qui permet de rendre la requête plus précise (dans le cas où par exemple on aurait plusieurs boutons sur la page).

Utilisez le matcher toHaveClass() prenant une string en argument, pour vérifier que le bouton a la classe red.

Écrire le composant

Écrivez ensuite le code de ToggleButton. Dans un premier temps, vous pouvez juste renvoyer un button avec la classe red et le texte Change to blue.

Test du changement de classe et de texte

Il va vous falloir ajouter un test pour simuler un clic sur le bouton et vérifier que la classe et le texte changent comme attendu.

Vous aurez besoin d’importer, en plus de screen et render, la méthode fireEvent de @testing-library/react. Voici un exemple de son utilisation - adaptez au test écrit ci-dessus au-lieu de simplement copier-coller !

import { render, screen, fireEvent } from "@testing-library/react";
import MyComponent from "./MyComponent";

it("test user interaction", () => {
  render(<MyComponent />);

  // récupérer l'élément
  const buttonElement = screen.getByRole("button");

  // simuler un clic sur le bouton
  fireEvent.click(buttonElement);

  // effectuer vos assertions
});

À vous de jouer : dans votre fichier de tests, ajoutez un deuxième test pour effectuer le clic sur le bouton, et vérifier la nouvelle classe et le nouveau texte.

Modifier le composant pour refléter le 2ème test

Il est temps d’ajouter du “dynamisme” au bouton, et d’implémenter la logique de changement de couleur et de texte.

  • Vous aurez besoin d’utiliser useState pour stocker la couleur (red ou blue) avec comme valeur initiale red.
  • Vous pouvez, sous le useState, déclarer une variable nextColor qui dépendra du state déclaré avec useState. Si la couleur dans le state vaut red, alors nextColor vaudra blue, et vice-versa.
  • Renvoyez un tag button avec comme attribut className la couleur stockée dans le state, et un texte qui utilisera nextColor pour afficher “Change to blue” ou “Change to red”.

Exercice optionnel : contrôle de l’état “disabled”

Pour aller plus loin, ajoutez une checkbox qui contrôle l’état “disabled” du bouton. Lorsque la checkbox est cochée, le bouton doit être désactivé et avoir la classe gray.

Indications pour le test :

  • Rendez le composant ToggleButton
  • Récupérez la checkbox avec screen.getByRole('checkbox').
  • Utilisez fireEvent pour simuler le clic sur la checkbox.
  • Vérifiez que le bouton devient désactivé (toBeDisabled()) et obtient la classe gray lorsque la checkbox est cochée.
  • Vérifiez également que la checkbox est cochée (toBeChecked()).

Suivant le temps que vous pouvez y consacrer, écrivez éventuellement un test supplémentaire avec deux clics sur la checkbox pour vérifier que la checkbox revient à son état non-coché d’origine (.not.toBeChecked()) et que le bouton est à nouveau actif (toBeEnabled())

Modifier le composant pour ajouter la checkbox

Après avoir écrit les tests, modifiez encore le composant ToggleButton pour satisfaire les nouvelles spécifications et passer les tests.

En résumé

Cet exercice vous aidera à comprendre comment tester les interactions utilisateur et les changements de classe CSS dans les composants React. Vous avez appris à utiliser différentes queries et matchers de RTL pour récupérer des éléments et vérifier leurs propriétés. L’exercice optionnel vous offre une opportunité supplémentaire de pratiquer les tests d’interactions plus complexes et les changements d’état.

1.5. Composant SignupForm

Introduction

Le composant SignupForm représente une étape avancée de notre exploration des tests React. Il combine plusieurs aspects du développement frontend, notamment la gestion des états, les validations des champs de formulaire, et l’intégration avec des services backend pour les vérifications de disponibilité. Cette section vous guidera à travers la construction et le test de ce composant de manière incrémentale.

Étape 1 : Composant AlertBox

Avant de plonger dans SignupForm, nous commencerons par un composant plus simple : AlertBox. Ce composant affichera des messages de feedback à l’utilisateur, tels que des erreurs de validation ou des confirmations de succès.

Spécifications :

  • Le composant accepte deux props :
    • message : une chaîne de caractères contenant le message à afficher.
    • status : une chaîne de caractères pouvant être 'success' ou 'failure', déterminant la couleur du message (green pour succès, red pour échec).
  • Le composant doit rendre une div avec le rôle alert et afficher le message dans la couleur correspondante au status.

Écrivez le test en premier en vous basant sur ce squelette de test pour AlertBox :

import { render, screen } from "@testing-library/react";
import AlertBox from "./AlertBox";

describe("AlertBox", () => {
  it("should display a success message with green color", () => {
    // Test implementation...
  });

  it("should display a failure message with red color", () => {
    // Test implementation...
  });
});

Étape 2 : Premiers pas avec SignupForm

Avec AlertBox en place, nous pouvons commencer à travailler sur SignupForm. Ce formulaire comprendra des champs pour username, email, et password, chacun avec ses propres règles de validation.

Squelette de SignupForm :

import React, { useState } from "react";
import AlertBox from "./AlertBox";

interface ValidationOutcome {
  isValid: boolean;
  message: string;
}

/**
 * Vérifie qu'un username est valide : commence par une lettre, suivie de lettres et nombres
 */
function checkUsername(username: string): ValidationOutcome {
  // à remplir
}

/**
 * Vérifie qu'un email est valide (possibilité d'utiliser une lib externe ou une regex)
 */
function checkEmail(email: string): ValidationOutcome {
  // à remplir
}

/**
 * Vérifie qu'un mot de passe est valide :
 * - au moins 8 caractères,
 * - éventuellement vérifier présence de minuscules, majuscules ET nombres
 */
function checkPassword(password: string): ValidationOutcome {
  // à remplir
}

export default function SignupForm() {
  // valeur du state pour username
  const [username, setUsername] = useState("");
  // informations de validation pour username
  // si le formulaire n'a pas encore été soumis => null
  // s'il a été soumis, on va stocker un objet contenant un booléen `isValid`,
  // et une string `message` (vide si `isValid` vaut true, avec la raison du problème sinon)
  const [usernameValidation, setUsernameValidation] =
    useState<ValidationOutcome | null>(null);

  const [email, setEmail] = useState("");
  const [emailValidation, setEmailValidation] =
    useState<ValidationOutcome | null>(null);

  const [password, setPassword] = useState("");
  const [passwordValidation, setPasswordValidation] =
    useState<ValidationOutcome | null>(null);

  // sera utilisé à la toute fin, pour stocker le résultat
  // de la soumission du formulaire
  const [submissionOutcome, setSubmissionOutcome] = useState<{
    message: string;
    status: "success" | "failure";
  } | null>(null);

  const handleSubmit = async (event: React.FormEvent) => {
    event.preventDefault();
    // Validation et logique de soumission du formulaire

    // C'est notamment ici qu'on va, pour chaque champ:
    // 1. appeler le "check*" correspondant : checkUsername, etc.
    // 2. stocker le résultat dans une variable locale (checkUsernameOutcome par ex.)
    // 3. stocker la valeur de cette variable dans l'état correspondant (`setUsernameValidation(checkUsernameOutcome)`)

    // Si l'une des validations a échoué on n'ira pas plus loin

    // Sinon on effectuera une requête AJAX vers /api/auth/signup
    // Idéalement utiliser axios !
  };

  return (
    <form onSubmit={handleSubmit}>
      {/* Input fields for username, email, and password */}
      <button type="submit">Sign Up</button>
    </form>
  );
}

Étape 3 : Tester les Validations de SignupForm

Votre premier test consistera à vérifier que la soumission d’un formulaire vide déclenche des erreurs de validation pour chaque champ. Utilisez des AlertBox pour afficher ces erreurs.

Indications pour le test :

  • Rendez le SignupForm et simulez une soumission.

  • Utilisez getAllByRole('alert') pour récupérer toutes les instances d’AlertBox.

  • Assurez-vous que chaque erreur de validation attendue est affichée. Par exemple :

    • Invalid username
    • Invalid email
    • Invalid password: too short (< 8 characters), missing uppercase letters, missing lowercase letters, missing numbers

Étape 4 : Implémentation des Validations

Implémentez la logique de validation dans SignupForm. Assurez-vous que les champs username, email, et password respectent des critères spécifiques (par exemple, format d’email valide, longueur minimum du mot de passe, etc.). Affichez une AlertBox avec un message d’erreur approprié en cas de validation échouée.

Étape 5 : Tests Avancés et Gestion des Réponses Serveur

Après avoir géré les validations côté client, vous aborderez la gestion des réponses serveur.

Testez le comportement de SignupForm lorsque le serveur renvoie une erreur (par exemple, username déjà utilisé) ou une confirmation de succès.

On va vous proposer des indications pour les tests avancés, et deux méthodes différentes.

Mais il y a des notions fondamentales communes aux deux méthodes, que nous allons détailler.

L’utilisation d’axios permet de simplifier la gestion des requêtes AJAX, en fournissant une meilleure gestion des erreurs, la conversion automatique des données envoyées/reçues en JSON, etc.

Mais cela introduit dans notre composant une dépendance. Le problème serait tout de même quasiment identique, même si on utilisait l’API fetch du navigateur au lieu d’Axios.

Le problème est qu’on dépend maintenant d’une source de données externe à notre composant, et même à notre application React : le backend qui va recevoir la requête d’inscription.

On souhaite pouvoir tester nos composants - y compris les requêtes AJAX - sans avoir besoin de démarrer un serveur (ce qui peut s’avérer assez lourd).

Méthode 1 : “mocker” l’appel Axios

Mocker Axios consiste à remplacer la véritable bibliothèque par un “double” offrant le même comportement.

Dans les tests :

import { vi, Mocked } from "vitest";
// autres imports omis

// Mocker le module axios
vi.mock("axios");
const mockedAxios = axios as Mocked<typeof axios>;

describe("tests with axios", () => {
  beforeEach(() => {
    // Réinitialiser les mocks avant chaque test
    mockedAxios.post.mockClear();
  });

  it("test with axios", async () => {
    // On simule la réponse { message: 'Welcome, user' } renvoyée par le serveur
    mockedAxios.post.mockResolvedValue({ data: { message: "Welcome, user" } });

    // Rendu composant
    render(<SignupForm />);

    // Récupération éléments et interactions
    // ...

    // waitFor permet d'attendre l'apparition d'un élément
    await waitFor(() => {
      const alertElements = screen.queryAllByRole("alert");
      expect(alertElements).toHaveLength(1);
      // On retrouve le message qu'on a récupéré du serveur
      expect(alertElements[0]).toHaveTextContent("Welcome, user");
    });
  });
});
Méthode 2 : mettre en place un faux serveur avec msw
  • Cette fois, on ne modifie pas le comportement d’Axios : on simule un serveur.
  • Utilisez msw pour intercepter et manipuler les réponses du serveur.
  • Testez la réaction de votre formulaire aux différentes réponses du serveur, en vous assurant que les AlertBox appropriées sont affichées.

La mise en place msw n’est pas si compliquée mais peut se heurter à quelques obstacles :

  • La doc officielle est très complète mais il peut être difficile de s’y retrouver !
  • La doc de React Testing Library montre des exemples d’utilisation de msw, mais avec l’ancienne version 1.x.
  • Si vous utilisez ChatGPT pour vous aider, il vous proposera naturellement des réponses avec l’ancienne version !

Aussi, voici quelques “raccourcis” pour vous permettre de démarrer.

Commencez par créer un fichier src/msw/handlers.ts avec ce contenu :

import { http, HttpResponse } from "msw";

const somePostHandler = async ({ request, params }) => {
  // Permet de récupérer des données envoyées JSON en POST/PUT
  const data = await request.json();
  console.log("\n\n>>> data:", data);

  // Possibilité de mettre en place une gestion d'erreur ici
  // par exemple, si un champ requis dans data n'est pas présent, ou invalide,
  // renvoyer une réponse avec un message d'erreur et un code de statut 4xx

  return HttpResponse.json(
    // 1er argument = les données à renvoyer. Ce serait l'équivalent de ce qui
    // est passé à res.json() dans Express
    { message: "Data received", success: true },
    // 2ème argument (optionnel) = (méta-)données supplémentaires.
    // Ici un code de statut 201 est un code "succès" pour signifier qu'une ressource
    // a bien été créée
    { status: 201 }
  );
};

export const handlers = [http.post("/api/some-endpoint", somePostHandler)];

Créez un deuxième fichier, src/msw/server.ts :

import { setupServer } from "msw/node";
import { handlers } from "./handlers";

export const server = setupServer(...handlers);

Ce server sera importé depuis les tests. Voici la structure générale pour l’utiliser dans les tests :

import { render, screen, fireEvent, waitFor } from "@testing-library/react";
import MyComponent from "./MyComponent";
import { server } from "./msw/server";

describe("MyComponent", () => {
  beforeAll(() => {
    // Avant de démarrer cette suite de tests :
    // met le faux serveur en écoute
    server.listen();
  });

  afterEach(() => {
    // Après chaque test : nettoyer tous les handlers
    // et leurs données
    server.resetHandlers();
  });

  afterAll(() => {
    // À la fin de l'exécution de cette suite, fermer le faux serveur
    server.close();
  });

  it("success case - all fields good and no duplicate", async () => {
    render(<MyComponent />);

    // Récupérer les éléments (par ex. champs input, boutons, etc.)
    const myTextInput = screen.getByRole("textbox", {
      name: /label du champ input/i,
    });
    const submitButton = screen.getByRole("button", { name: /submit/i });
    // ...

    // Simuler des saisies clavier en envoyant des évènements "change"
    fireEvent.change(myTextInput, { target: { value: "someValue" } });

    // Soumettre le formulaire => CENSÉ ÉMETTRE UNE REQUÊTE AJAX
    fireEvent.click(submitButton);

    await waitFor(() => {
      console.log("waitFor");
      const successMessage = screen.getByRole("alert");
      expect(successMessage).toHaveTextContent("My message");
    });
  });
});

Cette approche progressive vous permettra de construire et de tester efficacement un composant SignupForm robuste et réactif aux interactions utilisateur et aux réponses serveur.

2. Après-midi : Tests End-to-End avec Webdriver.io

2.1. Introduction aux tests End-to-End

  • Présentation des objectifs et aperçu de Webdriver.io
  • Distinction entre tests e2e et autres types de tests

2.2. Configuration de Webdriver.io

Lancer la commande à la racine du repo : npm init wdio@latest .

Cela va lancer un questionnaire :

===============================
🤖 WDIO Configuration Wizard 🧙
===============================

? A project named "express-react-testing-monorepo" was detected at "/Users/benoit/IPI/express-react-testing-monorepo", correct? Yes
? What type of testing would you like to do? E2E Testing - of Web or Mobile Applications
? Where is your automation backend located? On my local machine
? Which environment you would like to automate? Web - web applications in the browser
? With which browser should we start? Chrome
? Which framework do you want to use? Mocha (https://mochajs.org/)
? Do you want to use a compiler? TypeScript (https://www.typescriptlang.org/)
? Do you want WebdriverIO to autogenerate some test files? Yes
? What should be the location of your spec files? /Users/benoit/IPI/express-react-testing-monorepo/test/specs/**/*.ts
? Do you want to use page objects (https://martinfowler.com/bliki/PageObject.html)? No
? Which reporter do you want to use? spec
? Do you want to add a plugin to your test setup? wait-for: utilities that provide functionalities to wait for certain conditions till a defined task is complete.
   > https://www.npmjs.com/package/wdio-wait-for
? Would you like to include Visual Testing to your setup? For more information see https://webdriver.io/docs/visual-testing! No
? Do you want to add a service to your test setup? 
? Do you want me to run `npm install` Yes

Pour lancer les tests : npm run wdio

2.3. Tests e2e sur le SignupForm

  • Lancer npm run dev sous frontend

  • Modifier test/specs/test.e2e.ts de façon à interagir avec le formulaire

  • Écrire deux cas de test :

    • Un cas de test erreur avec les champs incorrects,
    • Un cas de test avec les champs corrects
  • Écrire un serveur Express minimaliste dans backend/src/index.js avec juste un endpoint /api/auth/signup.

    • Ce mini-serveur doit aussi être lancé avant de (re)lancer vos tests
    • Pas besoin de base de données : juste renvoyer un message de succès si on vous fournit les données requises (username, email, password)
    • Éventuellement : vous pouvez décider de renvoyer une erreur du type Email johndoe@example.com already taken que vous pouvez afficher dans l’interface, afin de la tester avec wdio.

2.4. Intégration des tests dans un pipeline CI

  • Présentation de l’intégration des tests dans un pipeline CI avec GitLab CI
  • Configuration de base du pipeline pour exécuter les tests React et e2e

2.5. Conclusion et Q&A

  • Récapitulatif de la journée
  • Session de questions-réponses pour clarifier les doutes et discuter des challenges rencontrés