batchCooking/apps/web/cypress/e2e/household-settings.ts
Nicolas 37cf6d4dcd fix(web): fix cross-feature step discovery and slash-alternation bug
La CI de la refonte précédente (commit aaace15) a échoué : la
découverte par défaut du préprocesseur ne charge, pour un fichier
`foo.feature`, QUE `foo.ts` (co-localisé, même basename) et
`cypress/support/step_definitions/**` — pas les autres `.ts` du
dossier `cypress/e2e/`. onboarding.feature référençait donc des steps
qui ne vivaient que dans preferences.ts, household-settings.ts et
auth.ts, introuvables lors de son propre run.

Déplace les steps réellement partagés entre plusieurs .feature vers
cypress/support/step_definitions/ (chargé pour toutes les features) :
- reference-data.steps.ts : mocks des listes de référence régimes/
  allergies (options ou vides) — partagé entre auth.feature et
  onboarding.feature
- household-mutations.steps.ts : création/adhésion à un foyer et leurs
  assertions — partagé entre household-settings.feature et
  onboarding.feature
- profile-mutations.steps.ts : sélection du régime, mise à jour des
  allergies et leur assertion — partagé entre preferences.feature et
  onboarding.feature

Les définitions d'origine sont retirées de auth.ts/household-
settings.ts/onboarding.ts/preferences.ts pour éviter un step
"Ambiguous" (chargé deux fois pour la feature qui les définissait déjà
elle-même).

Corrige aussi un second bug distinct révélé par la même CI :
"the ingredient/diet catalog is available" (recipe-form.feature)
contient un "/" non échappé — en syntaxe Cucumber Expression, "/" hors
d'un paramètre {..} signifie une alternative de texte ("ingredient" OU
"diet catalog is available"), jamais le caractère littéral. Le texte
du .feature ne pouvait donc jamais matcher. Renommé sans "/" :
"the ingredient and diet catalog is available".

Le script de vérification statique utilisé pour valider aaace15 avant
push donnait une fausse confiance : il regroupait tous les steps de
tous les fichiers comme disponibles globalement pour chaque feature,
sans respecter ce scoping réel. Réécrit pour ne charger, par feature,
que son fichier co-localisé + step_definitions/ — et pour détecter les
patterns contenant un "/" non échappé. Résultat : toujours 246 steps,
0 non résolu, 0 ambigu, 0 pattern à slash non échappé, cette fois avec
un modèle de résolution fidèle au comportement réel du préprocesseur.
2026-08-19 13:47:56 +02:00

74 lines
2.5 KiB
TypeScript

import { Given, Then, When } from "@badeball/cypress-cucumber-preprocessor";
const houseWithTwoMembers = {
id: 1,
name: "Chez Alice",
adminId: 1,
inviteCode: "ABCD2345",
members: [
{ id: 1, firstName: "Alice", lastName: "Martin" },
{ id: 2, firstName: "Bob", lastName: "Dupont" },
],
};
Given("the household request returns the two-member household", () => {
cy.intercept("GET", "**/house/current", { statusCode: 200, body: houseWithTwoMembers });
});
// Creating/joining a household, and asserting on those two requests, is
// shared with onboarding.feature's household step — see
// cypress/support/step_definitions/household-mutations.steps.ts.
Given("renaming the household will succeed", () => {
cy.intercept("PATCH", "**/house/current", {
statusCode: 200,
body: { ...houseWithTwoMembers, name: "Chez les Martin" },
}).as("renameHouse");
});
Given("removing Bob from the household will succeed", () => {
const householdWithoutBob = { ...houseWithTwoMembers, members: [houseWithTwoMembers.members[0]] };
let memberRemoved = false;
cy.intercept("GET", "**/house/current", (req) => {
req.reply({ statusCode: 200, body: memberRemoved ? householdWithoutBob : houseWithTwoMembers });
});
cy.intercept("DELETE", "**/house/members/2", (req) => {
memberRemoved = true;
req.reply({ statusCode: 200, body: householdWithoutBob });
}).as("removeMember");
});
Given("deleting the household will succeed", () => {
let houseDeleted = false;
cy.intercept("GET", "**/house/current", (req) => {
req.reply({ statusCode: 200, body: houseDeleted ? null : houseWithTwoMembers });
});
cy.intercept("DELETE", "**/house/current", (req) => {
houseDeleted = true;
req.reply({ statusCode: 204 });
}).as("deleteHouse");
});
Given("leaving the household will succeed", () => {
cy.intercept("POST", "**/house/leave", { statusCode: 204 }).as("leaveHouse");
});
When("I click {string} for the member {string}", (action: string, member: string) => {
cy.contains("li", member).contains("button", action).click();
});
Then("the household rename request should have been made with name {string}", (name: string) => {
cy.wait("@renameHouse").its("request.body").should("deep.equal", { name });
});
Then("the member removal request should have been made", () => {
cy.wait("@removeMember");
});
Then("the household deletion request should have been made", () => {
cy.wait("@deleteHouse");
});
Then("the household leave request should have been made", () => {
cy.wait("@leaveHouse");
});