batchCooking/apps/api/features/step-definitions/profile.steps.ts
Nicolas 4b85531601 fix(api): les uids du catalogue sont en anglais, pas des slugs français
reference-seed-data.ts reste rédigé en français (c'est juste le libellé
d'autoring, jamais stocké/exposé), mais la clé stable (`Diet.key`/
`Category.key`/`Ingredient.key`) qu'on en dérive doit elle-même être un
identifiant anglais, indépendant de la langue d'autoring — pas juste le
même texte français passé à slugify().

- apps/api/src/db/catalog-en-keys.ts : dictionnaire écrit à la main
  (label français -> clé anglaise) pour les 5 régimes, 14 allergènes et
  437 ingrédients ; getEnglishKey() lève une erreur explicite si un
  nouvel élément n'a pas encore d'entrée plutôt que de retomber sur un
  slug français silencieux.
- scripts/validate-catalog-en-keys.ts : vérifie que chaque diet/allergène/
  ingrédient de reference-seed-data.ts a une entrée, et que les clés
  anglaises résultantes sont uniques (437/437, 14/14, 5/5 — zéro manquant,
  zéro collision).
- reference-seed-data.ts et scripts/generate-catalog-i18n.ts utilisent
  désormais getEnglishKey() au lieu de slugify(nom français).
- Nouvelle migration (20260818193000_catalog_keys_to_english) qui
  remappe les lignes déjà seedées avec un slug français (par la migration
  précédente) vers leur clé anglaise définitive.
- apps/web/src/locales/fr/translation.json régénéré : catalog.* est
  maintenant indexé par clé anglaise ("vegetarian", "eggs",
  "ground_beef"...), toujours avec le libellé français en valeur.
- Tests/step-definitions mis à jour (getEnglishKey() au lieu de
  slugify()) ; 102 tests Mocha + 32 scénarios Cucumber passent contre la
  base migrée. Vérifié aussi en direct via GET /reference/diets et
  /reference/allergies.

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

54 lines
2.2 KiB
TypeScript

import assert from "node:assert/strict";
import { Then, When } from "@cucumber/cucumber";
import { prisma } from "../../src/db/prisma.js";
import { getEnglishKey } from "../../src/db/catalog-en-keys.js";
import type { CustomWorld } from "../support/world.js";
/** Splits a comma-separated list of names from a `.feature` string into trimmed, non-empty parts. */
function splitNames(names: string): string[] {
return names
.split(",")
.map((name) => name.trim())
.filter(Boolean);
}
/**
* Resolves allergen names (as written in a `.feature` file, e.g.
* "Arachides") to their Allergy id — scenarios still name allergens by their
* French label for readability, so this slugifies before matching against
* `Category.key` (see reference.service.ts for why the key lives on
* Category, not Allergy).
*/
async function allergyIdsFor(names: string[]): Promise<number[]> {
const allergies = await prisma.allergy.findMany({ include: { category: true } });
return names.map((name) => {
const key = getEnglishKey(name);
const match = allergies.find((allergy) => allergy.category.key === key);
if (!match) throw new Error(`No seeded allergen named "${name}"`);
return match.id;
});
}
When("I set my regime to {string}", async function (this: CustomWorld, dietName: string) {
const diet = await prisma.diet.findFirstOrThrow({ where: { key: getEnglishKey(dietName) } });
this.response = await this.agent.patch("/profile/diet").send({ dietId: diet.id });
});
Then(
"my profile's regime should be {string}",
async function (this: CustomWorld, dietName: string) {
const diet = await prisma.diet.findFirstOrThrow({ where: { key: getEnglishKey(dietName) } });
assert.equal(this.response.body.dietId, diet.id);
},
);
When("I set my allergens to {string}", async function (this: CustomWorld, names: string) {
const allergyIds = await allergyIdsFor(splitNames(names));
this.response = await this.agent.patch("/profile/allergies").send({ allergyIds });
});
Then("my selected allergens should be {string}", async function (this: CustomWorld, names: string) {
const expected = (await allergyIdsFor(splitNames(names))).sort();
const actual = [...this.response.body].sort();
assert.deepEqual(actual, expected);
});