Ouvrir le popover de correction depuis un highlight existant tombait sur la liste de choix (avec l'option "Aucune technique ici"), pas sur la vue metadonnees — pour voir/editer les ingredients/ustensiles deja rattaches a une technique correctement detectee, il fallait recliquer cette meme technique dans la liste, sans aucun indice que c'est ce qu'il fallait faire (rien ne la distingue des autres dans cette liste). Resultat cote utilisateur : la fonctionnalite de correction/edition de metadonnees etait techniquement presente mais invisible en pratique. TechStepCorrectionPopover demarre desormais selectionne sur `previousTechStepId` quand il est defini (un clic sur un highlight existant) — droit dans la vue Ingredients/Ustensiles, deja pre-remplie. "Changer" reste disponible pour rejoindre la liste complete (relabelliser ou supprimer la correspondance). Tests Cypress (component + e2e) mis a jour pour ce nouveau point d'entree par defaut. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
185 lines
6.4 KiB
TypeScript
185 lines
6.4 KiB
TypeScript
import { Given, Then, When } from "@badeball/cypress-cucumber-preprocessor";
|
|
|
|
const oeufs = { id: 2, key: "eggs", kind: "ALLERGY" };
|
|
|
|
const omelette = {
|
|
id: 2,
|
|
name: "Omelette",
|
|
description: null,
|
|
picture: null,
|
|
portions: 2,
|
|
authorId: 1,
|
|
visibility: "PERSONAL",
|
|
allergens: [oeufs],
|
|
diets: [],
|
|
isFavorite: false,
|
|
};
|
|
|
|
const omeletteDetail = {
|
|
...omelette,
|
|
description: "Une omelette toute simple.",
|
|
ingredients: [
|
|
{
|
|
ingredient: {
|
|
id: 10,
|
|
key: "egg",
|
|
icon: "EGG",
|
|
category: "dairyAndCheese",
|
|
subcategory: "eggs",
|
|
allergens: [oeufs],
|
|
diets: [],
|
|
},
|
|
quantity: 3,
|
|
unit: { id: 1, key: "piece", type: "COUNT", toBaseFactor: 1 },
|
|
},
|
|
],
|
|
steps: [
|
|
{ id: 1, description: "Battre les œufs.", picture: null, order: 1, techSteps: [] },
|
|
{
|
|
id: 2,
|
|
description: "Cuire à la poêle.",
|
|
picture: null,
|
|
order: 2,
|
|
// "Cuire" -> the `cook` technique, matching real reference-seed-data.ts
|
|
// (`\bcui(re|sez|sant|sson)\b`) — "poêle" itself matches nothing
|
|
// (that's `panFry`'s "sauter", a different word).
|
|
techSteps: [{ techStep: { id: 1, key: "cook" }, start: 0, end: 5, source: "auto" }],
|
|
},
|
|
],
|
|
};
|
|
|
|
Given("the disliked ingredients list is empty", () => {
|
|
cy.intercept("GET", "**/profile/disliked-ingredients", { statusCode: 200, body: [] });
|
|
});
|
|
|
|
Given("the recipe catalog contains {string}", () => {
|
|
cy.intercept("GET", /\/recipes\?/, { statusCode: 200, body: [omelette] });
|
|
});
|
|
|
|
Given("recipe 2's detail is available", () => {
|
|
cy.intercept("GET", "**/recipes/2", { statusCode: 200, body: omeletteDetail }).as("getRecipe");
|
|
});
|
|
|
|
Given("toggling recipe 2's favorite will succeed", () => {
|
|
cy.intercept("POST", "**/recipes/2/favorite", { statusCode: 204 }).as("favorite");
|
|
});
|
|
|
|
Given("deleting recipe 2 will succeed", () => {
|
|
cy.intercept("DELETE", "**/recipes/2", { statusCode: 204 }).as("deleteRecipe");
|
|
});
|
|
|
|
// Step 2 is `omeletteDetail`'s "Cuire à la poêle." step, whose only
|
|
// existing match is `cook` (id 1) — see that fixture above. The response
|
|
// mirrors `SubmitTechStepCorrectionResult` (packages/shared): the audit
|
|
// record (reassigning the match to `simmer`, id 3, "Mijoter" — see `the
|
|
// tech steps reference list has options`, reference-data.steps.ts) plus
|
|
// the step's fresh `techSteps`, now showing that same reassignment as a
|
|
// `"manual"`-sourced entry — the API applies a correction immediately, it
|
|
// doesn't just record it (see `StepTechStepView.source`'s own doc comment).
|
|
Given('correcting step 2\'s "Cuire" match will succeed', () => {
|
|
cy.intercept("POST", "**/recipes/2/steps/2/corrections", {
|
|
statusCode: 201,
|
|
body: {
|
|
correction: {
|
|
id: 1,
|
|
start: 0,
|
|
end: 5,
|
|
previousTechStep: { id: 1, key: "cook" },
|
|
correctedTechStep: { id: 3, key: "simmer" },
|
|
createdAt: new Date().toISOString(),
|
|
},
|
|
techSteps: [
|
|
{
|
|
techStep: { id: 3, key: "simmer" },
|
|
start: 0,
|
|
end: 5,
|
|
source: "manual",
|
|
ingredients: [],
|
|
utensils: [],
|
|
},
|
|
],
|
|
},
|
|
}).as("correction");
|
|
});
|
|
|
|
When("I click the highlighted technique {string}", (text: string) => {
|
|
cy.contains(".step-tech-step", text).click();
|
|
});
|
|
|
|
Then("I should see the technique correction options", () => {
|
|
cy.get(".tech-step-correction-popover").should("be.visible");
|
|
});
|
|
|
|
// Picking a technique only *selects* it now — it takes a separate
|
|
// "Valider" click to actually submit (room was made for attaching
|
|
// ingredient/utensil metadata first, see `TechStepCorrectionPopover.tsx`'s
|
|
// own doc comment) — folded into this one step since nothing in this
|
|
// scenario cares about that intermediate state on its own. This step is
|
|
// only ever reached after clicking an *existing* highlight (see the
|
|
// previous step above), which now opens straight into that same
|
|
// technique's metadata view, not the pick list — "Changer" reaches the
|
|
// list this step actually needs to pick a different one from.
|
|
When("I choose {string} as the correct technique", (label: string) => {
|
|
cy.contains("button", "Changer").click();
|
|
cy.contains(".tech-step-correction-popover__list button", label).click();
|
|
cy.contains(".tech-step-correction-popover__confirm-button", "Valider").click();
|
|
});
|
|
|
|
Then(
|
|
"the highlighted technique {string} should be marked as a manual correction",
|
|
(text: string) => {
|
|
cy.contains(".step-tech-step", text).should("have.class", "step-tech-step--manual");
|
|
},
|
|
);
|
|
|
|
Then("the correction request should have been made", () => {
|
|
// Asserts the actual span, not just that *a* request fired — a real bug
|
|
// (StepDescription.tsx's click handler reading a shared, still-mutating
|
|
// `offset` variable by reference instead of a value captured at render
|
|
// time) once sent `end` all the way to the end of the description
|
|
// instead of "Cuire"'s own tight [0, 5) span, and a request-fired-only
|
|
// assertion here didn't catch it — found only via manual testing.
|
|
cy.wait("@correction")
|
|
.its("request.body")
|
|
.should("deep.include", { start: 0, end: 5, previousTechStepId: 1 });
|
|
});
|
|
|
|
Then("the recipe {string} should not be visible in the table", (name: string) => {
|
|
cy.contains(".recipe-table__name", name).should("not.exist");
|
|
});
|
|
|
|
Then("the recipe {string} should be marked as favorite", (name: string) => {
|
|
cy.contains(".recipe-table__name", name).find(".recipe-table__fav-mark").should("exist");
|
|
});
|
|
|
|
Then("the recipe {string} should not be marked as favorite", (name: string) => {
|
|
cy.contains(".recipe-table__name", name).find(".recipe-table__fav-mark").should("not.exist");
|
|
});
|
|
|
|
When("I click the favorite star", () => {
|
|
cy.get(".favorite-star-button").click();
|
|
});
|
|
|
|
Then("the favorite request should have been made", () => {
|
|
cy.wait("@favorite");
|
|
});
|
|
|
|
Then("the favorite star should be marked as favorite", () => {
|
|
cy.get(".favorite-star-button").should("have.class", "is-favorite");
|
|
});
|
|
|
|
When("I click {string} in the recipe detail panel", (text: string) => {
|
|
cy.contains(".recipe-detail-panel__danger-button", text).click();
|
|
});
|
|
|
|
When("I confirm the deletion in the recipe detail panel", () => {
|
|
cy.contains(".recipe-detail-panel__danger-button", "Confirmer la suppression").click();
|
|
});
|
|
|
|
Then("the delete request should have been made", () => {
|
|
cy.wait("@deleteRecipe");
|
|
});
|
|
|
|
Then("the URL should match the recipes list", () => {
|
|
cy.url().should("match", /\/recettes\/?$/);
|
|
});
|