batchCooking/apps/web/cypress/e2e/recipes.ts
Nicolas 77b55d7aeb refactor(catalog): authoring 100% anglais — uid camelCase, plus de français dans le code
Le catalogue de référence (diets/allergènes/ingrédients) était écrit en
français dans reference-seed-data.ts, avec une table de correspondance
séparée (catalog-en-keys.ts, 666 lignes, ~563 entrées) traduisant chaque
libellé français vers une clé anglaise snake_case, elle-même utilisée pour
peupler la colonne `key` en base et régénérer translation.json. Décision :
remplacer par un authoring 100% anglais camelCase directement dans le seed
— plus de détour, plus de table de correspondance.

- `Ingredient.name`/`allergenNames`/`dietNames` → `uid`/`allergenUids`/
  `dietUids`, valeurs en camelCase directement (ex: "Tomate" → "tomato",
  "Fruits à coque" → "treeNuts").
- `IngredientCategory`/`IngredientSubcategory` (enums Prisma) renommés du
  français SCREAMING_SNAKE_CASE (`PRODUITS_FRAIS`, `LEGUMES`...) vers
  l'anglais camelCase (`freshProduce`, `vegetables`...) — même mécanique
  de migration que le renommage d'enum précédent
  (20260818113250_ingredient_taxonomy_rework) : nouvelle colonne avec
  valeur par défaut sûre, jamais de cast direct (aucune valeur commune
  entre ancien et nouvel enum), seedReferenceData() corrige chaque ligne
  au démarrage suivant.
- Migration `20260819180000_catalog_camel_case_uids` : renomme les clés
  existantes (diet/category/ingredients, même mécanique que
  20260818193000_catalog_keys_to_english) + swap des deux enums. Un cas
  particulier corrigé à la main : "sesame_seeds" était à la fois la clé
  d'un allergène (Category) et d'un ingrédient qui se référence lui-même
  ("Graines de sésame") — les deux tables ont besoin de leur propre
  UPDATE.
- `catalog-en-keys.ts`, `slugify.ts`, `generate-catalog-i18n.ts`,
  `validate-catalog-en-keys.ts` — supprimés (plus de raison d'être).
  Conséquence assumée : `translation.json` n'est plus régénéré
  automatiquement, c'est désormais la seule source du texte FR, tenue à
  jour à la main en parallèle du uid (même clé qui les relie).
- `packages/shared/src/types/reference.ts`, `apps/web`'s
  `ingredient-icons.tsx` (CATEGORY_ICON/SUBCATEGORY_ICON), fixtures
  Cypress codées en dur — mis à jour avec les nouveaux noms.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-19 20:40:55 +02:00

103 lines
3 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,
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: "unité",
},
],
steps: [
{ id: 1, description: "Battre les œufs.", picture: null, order: 1 },
{ id: 2, description: "Cuire à la poêle.", picture: null, order: 2 },
],
};
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");
});
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");
});
Then("the recipe detail panel heading should be {string}", (text: string) => {
cy.get(".recipe-detail-panel").contains("h2", text).should("be.visible");
});
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\/?$/);
});