batchCooking/apps/web/cypress/e2e/onboarding.cy.ts
Nicolas f00485f341 fix(ci): corrige les specs Cypress cassées par le refactor uid+i18n, applique biome
- onboarding.cy.ts / preferences.cy.ts / recipes.cy.ts mockaient encore
  GET /reference/diets|allergies avec l'ancienne forme {id, name}. Depuis
  les deux derniers commits l'API renvoie {id, key} (uid anglais) et le
  composant résout le libellé via i18n (t(`catalog.diets.${key}`)) — avec
  key manquant, ça affichait littéralement "catalog.diets.undefined" au
  lieu de "Végétarien"/"Omnivore"/etc., faisant échouer cy.select()/
  cy.contains() dans ces 3 specs. Corrigé pour mocker {key: "vegetarian"},
  {key: "peanuts"}, etc.
- recipes.cy.ts : le test "shows a not-found message" utilisait le
  mauvais code d'erreur (4041 au lieu de ErrorCode.RECIPE_NOT_FOUND =
  4045), donc RecipeDetailPanel tombait dans son état d'erreur générique
  au lieu du message "Cette recette n'existe pas." — bug dans mon propre
  test, sans rapport avec le refactor.
- pnpm lint (biome) : les fichiers touchés par le refactor précédent
  avaient quelques soucis de formatage/tri d'imports (des sed multi-
  fichiers, pas d'édition via l'outil habituel) — corrigés par
  `biome check --write`.

Vérifié : ces 3 specs + recipe-form.cy.ts passent maintenant dans le job
CI GitHub Actions (Linux, Cypress s'y exécute réellement — contrairement
à cet environnement Windows sandboxé, voir les commits précédents) ; 102
tests Mocha + 32 scénarios Cucumber toujours au vert en local.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-18 20:49:25 +02:00

148 lines
5.8 KiB
TypeScript

// Mocks the API via cy.intercept — see auth.cy.ts for the rationale (no
// live backend in this CI job; apps/api's own Mocha/Cucumber suites cover
// real API behavior against a real database).
const signupResponse = {
id: 1,
firstName: "Alice",
lastName: "Martin",
email: "alice@example.com",
tokenVersion: 0,
houseId: null as number | null,
dietId: null,
};
/** Signs up and lands on the wizard's first step (regime) — shared setup for every scenario below. */
function signupAndReachOnboarding() {
cy.intercept("GET", "**/auth/me", { statusCode: 401 });
cy.intercept("POST", "**/auth/signup", { statusCode: 201, body: signupResponse }).as("signup");
cy.intercept("GET", /\/planning\?/, { statusCode: 200, body: null });
cy.visit("/signup");
cy.get("#firstName").type("Alice");
cy.get("#lastName").type("Martin");
cy.get("#email").type("alice@example.com");
cy.get("#password").type("correct-horse-battery-staple");
cy.contains("button", "Créer mon profil").click();
cy.wait("@signup");
}
describe("Onboarding wizard (regime → foyer → allergens)", () => {
it("walks through all three steps, creating a household on the way, and lands on the home", () => {
cy.intercept("GET", "**/reference/diets", {
statusCode: 200,
body: [
{ id: 1, key: "omnivore" },
{ id: 2, key: "vegetarian" },
],
});
cy.intercept("PATCH", "**/profile/diet", {
statusCode: 200,
body: { ...signupResponse, dietId: 2 },
}).as("updateDiet");
cy.intercept("GET", "**/house/current", { statusCode: 200, body: null });
cy.intercept("POST", "**/house", {
statusCode: 201,
body: { id: 1, name: "Chez Alice", adminId: 1, inviteCode: "ABCD2345", members: [] },
}).as("createHouse");
cy.intercept("GET", "**/reference/allergies", {
statusCode: 200,
body: [
{ id: 1, key: "peanuts", kind: "ALLERGY" },
{ id: 2, key: "gluten", kind: "INTOLERANCE" },
],
});
cy.intercept("PATCH", "**/profile/allergies", { statusCode: 200, body: [1] }).as(
"updateAllergies",
);
signupAndReachOnboarding();
// Step 1/3 — dietary regime.
cy.url().should("include", "/onboarding/regime");
cy.contains("Étape 1 sur 3").should("be.visible");
cy.get("#diet").select("Végétarien");
cy.contains("button", "Continuer").click();
cy.wait("@updateDiet").its("request.body").should("deep.equal", { dietId: 2 });
// Step 2/3 — household, optional: creating one here.
cy.url().should("include", "/onboarding/foyer");
cy.contains("Étape 2 sur 3").should("be.visible");
cy.get("#houseName").type("Chez Alice");
cy.contains("button", "Créer").click();
cy.wait("@createHouse").its("request.body").should("deep.equal", { name: "Chez Alice" });
// Step 3/3 — allergens (grouped into two lists) and intolerances, then finish.
cy.url().should("include", "/onboarding/allergenes");
cy.contains("Étape 3 sur 3").should("be.visible");
cy.contains("legend", "Allergies").should("be.visible");
cy.contains("legend", "Intolérances").should("be.visible");
cy.contains("label", "Arachides").find("input[type=checkbox]").check();
cy.contains("button", "Terminer").click();
cy.wait("@updateAllergies")
.its("request.body")
.should("deep.equal", { allergyIds: [1] });
cy.url().should("eq", `${Cypress.config().baseUrl}/`);
cy.contains("h1", "Planning de la semaine").should("be.visible");
});
it("lets the regime and allergens steps be skipped without changing anything", () => {
cy.intercept("GET", "**/reference/diets", { statusCode: 200, body: [] });
cy.intercept("PATCH", "**/profile/diet", { statusCode: 200, body: signupResponse }).as(
"updateDiet",
);
cy.intercept("GET", "**/house/current", { statusCode: 200, body: null });
cy.intercept("GET", "**/reference/allergies", { statusCode: 200, body: [] });
cy.intercept("PATCH", "**/profile/allergies", { statusCode: 200, body: [] }).as(
"updateAllergies",
);
signupAndReachOnboarding();
cy.url().should("include", "/onboarding/regime");
cy.contains("button", "Continuer").click();
cy.wait("@updateDiet").its("request.body").should("deep.equal", { dietId: null });
cy.url().should("include", "/onboarding/foyer");
cy.contains("button", "Passer cette étape").click();
cy.url().should("include", "/onboarding/allergenes");
cy.contains("button", "Terminer").click();
cy.wait("@updateAllergies").its("request.body").should("deep.equal", { allergyIds: [] });
cy.url().should("eq", `${Cypress.config().baseUrl}/`);
});
it("lets the household step be completed by joining an existing household instead of creating one", () => {
cy.intercept("GET", "**/reference/diets", { statusCode: 200, body: [] });
cy.intercept("PATCH", "**/profile/diet", { statusCode: 200, body: signupResponse });
cy.intercept("GET", "**/house/current", { statusCode: 200, body: null });
cy.intercept("POST", "**/house/join", {
statusCode: 200,
body: {
id: 1,
name: "Chez Bob",
adminId: 2,
inviteCode: "ABCD2345",
members: [
{ id: 1, firstName: "Alice", lastName: "Martin" },
{ id: 2, firstName: "Bob", lastName: "Dupont" },
],
},
}).as("joinHouse");
cy.intercept("GET", "**/reference/allergies", { statusCode: 200, body: [] });
cy.intercept("PATCH", "**/profile/allergies", { statusCode: 200, body: [] });
signupAndReachOnboarding();
cy.contains("button", "Continuer").click();
cy.url().should("include", "/onboarding/foyer");
cy.get("#inviteCode").type("abcd2345");
cy.contains("button", "Rejoindre").click();
cy.wait("@joinHouse").its("request.body").should("deep.equal", { inviteCode: "ABCD2345" });
cy.url().should("include", "/onboarding/allergenes");
});
});