batchCooking/apps/web/cypress/e2e/auth.steps.ts
Nicolas 20d52aee2d feat(web): migre les specs Cypress vers Cucumber/Gherkin
Les tests e2e (apps/web/cypress/e2e/) étaient de simples specs Cypress
(.cy.ts), sans lien avec Cucumber alors qu'apps/api utilise déjà
Gherkin pour ses propres tests BDD. Intègre
@badeball/cypress-cucumber-preprocessor pour écrire les scénarios
utilisateurs en Gherkin des deux côtés, même vocabulaire.

- cypress.config.ts : specPattern sur *.feature, wiring du
  préprocesseur (esbuild bundler + plugin cucumber)
- Les 11 fichiers .cy.ts sont remplacés par des paires .feature/.steps.ts
  (co-localisées, même nom) — conversion complète, comportement
  équivalent (mêmes intercepts, mêmes assertions)
- cypress/support/step_definitions/common.steps.ts : steps partagés
  entre features (connexion, navigation, assertions génériques de
  texte/URL/champ) — globaux à toute la suite, réutilisables tels quels
- cypress/support/profile.ts : profil du compte "connecté" courant,
  assemblé au fil de plusieurs Given avant le premier visit/When
- README : nouvelle section "Cucumber (apps/web)" (miroir de la section
  existante pour apps/api), mise à jour des références aux anciens noms
  de fichiers .cy.ts (déjà obsolètes avant ce changement)

Vérification : impossible d'exécuter Cypress dans cet environnement
(crash Electron/GPU au lancement, limitation déjà documentée dans le
README — reproductible sur main, indépendante de ce changement). À la
place :
- les 447 steps Gherkin des 11 .feature ont été vérifiés
  programmatiquement contre les 165 patterns de step enregistrés : 0
  non résolu, 0 ambigu
- les 11 .feature parsent correctement avec le parser Gherkin officiel
  (57 scénarios au total)
- tous les .steps.ts passent `biome check` (syntaxe + style) sans erreur
- CYPRESS_INSTALL_BINARY déjà géré (voir PR précédente) — le binaire est
  bien présent localement (`cypress verify` OK), donc le blocage est
  spécifiquement le sandbox GPU de cet environnement, pas l'installation

La vraie exécution reste à vérifier via le job `e2e` de la CI GitHub
Actions sur cette PR — c'est le chemin déjà documenté dans le README
pour cet environnement précis.
2026-08-19 09:42:29 +02:00

82 lines
2.4 KiB
TypeScript

import { type DataTable, Given, Then, When } from "@badeball/cypress-cucumber-preprocessor";
import { ErrorCode } from "@batch-cooking/shared";
const signupResponse = {
id: 1,
firstName: "Alice",
lastName: "Martin",
email: "alice@example.com",
tokenVersion: 0,
houseId: null as number | null,
dietId: null,
};
Given("the signup request will succeed", () => {
cy.intercept("POST", "**/auth/signup", { statusCode: 201, body: signupResponse }).as("signup");
});
Given("the signup request is being watched", () => {
cy.intercept("POST", "**/auth/signup").as("signup");
});
Given("the signup request will fail because the email is already used", () => {
cy.intercept("POST", "**/auth/signup", {
statusCode: 409,
body: { code: ErrorCode.EMAIL_ALREADY_IN_USE, message: "Email already in use" },
}).as("signup");
});
Given("the diets reference list is empty", () => {
cy.intercept("GET", "**/reference/diets", { statusCode: 200, body: [] });
});
When("I sign up with:", (dataTable: DataTable) => {
const { firstName, lastName, email, password } = dataTable.rowsHash();
cy.visit("/signup");
cy.get("#firstName").type(firstName);
cy.get("#lastName").type(lastName);
cy.get("#email").type(email);
cy.get("#password").type(password);
cy.contains("button", "Créer mon profil").click();
});
Then("the signup request should have been made", () => {
cy.wait("@signup");
});
Then("the signup request should not have been made", () => {
cy.get("@signup.all").should("have.length", 0);
});
Given("the login request will succeed", () => {
cy.intercept("POST", "**/auth/login", {
statusCode: 200,
body: { ...signupResponse, houseId: 1 },
}).as("login");
});
Given("the login request will fail because the credentials are invalid", () => {
cy.intercept("POST", "**/auth/login", {
statusCode: 401,
body: { code: ErrorCode.INVALID_CREDENTIALS, message: "Invalid email or password" },
}).as("login");
});
When("I log in with email {string} and password {string}", (email: string, password: string) => {
cy.visit("/login");
cy.get("#email").type(email);
cy.get("#password").type(password);
cy.contains("button", "Se connecter").click();
});
Then("the login request should have been made", () => {
cy.wait("@login");
});
Given("the logout request will succeed", () => {
cy.intercept("POST", "**/auth/logout", { statusCode: 204 }).as("logout");
});
Then("the logout request should have been made", () => {
cy.wait("@logout");
});