// 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/current", { 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, name: "Omnivore" }, { id: 2, name: "Végétarien" }, ], }); 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, name: "Arachides", kind: "ALLERGY" }, { id: 2, name: "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"); }); });