batchCooking/apps/api/test/reference.test.ts
Nicolas 1d9bb6d112 feat(web,api): zone dangereuse rouge, préférences élargies, onglet favoris par défaut, e2e recettes, catalogue en uid+i18n
- Zone dangereuse (compte) : le bouton "Supprimer mon compte" est rouge.
- Pages préférences/paramétrage : contenu centré et élargi (32rem -> 56rem)
  au lieu de coller à gauche sur un écran large.
- Page recettes : l'onglet "Favoris" est sélectionné par défaut.
- Ajout de apps/web/cypress/e2e/recipes.cy.ts (onglets, recherche, sélection
  master-detail, favori, suppression, lien nouvelle recette).
- Catalogue de référence (ingrédients/régimes/allergènes) : la colonne
  `name` (le libellé français, utilisé comme clé unique) devient `key`, un
  slug stable et opaque au sens produit (ex. "vegetarien", "boeuf_hache").
  Le libellé lui-même déménage entièrement côté client, dans
  apps/web/src/locales/fr/translation.json sous le namespace `catalog.*`,
  résolu via `t(\`catalog.ingredients.${key}\`)` etc. — même schéma que
  IngredientCategory/IngredientSubcategory. Migration Prisma
  (rename + backfill des ~456 lignes déjà seedées), seed/service/tests API
  et composants web mis à jour en conséquence.
  - apps/api/src/utils/slugify.ts + scripts/generate-catalog-i18n.ts
    (regénère le fichier de traduction depuis reference-seed-data.ts).
  - 102 tests Mocha + 32 scénarios Cucumber passent contre la base migrée.

Note : cypress run plante dans cet environnement (le processus GPU
Chromium/Electron crash même headless, indépendamment des flags) — les
recipes.cy.ts n'ont pas pu être exécutés ici ; vérifiés par lecture du code
source des composants visés et par un passage manuel dans le navigateur de
prévisualisation.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-18 19:44:30 +02:00

81 lines
2.9 KiB
TypeScript

import { expect } from "chai";
import request from "supertest";
import { createApp } from "../src/app.js";
import { prisma } from "../src/db/prisma.js";
import { resetDatabase } from "../test-support/reset-db.js";
import { slugify } from "../src/utils/slugify.js";
describe("Reference data", () => {
const app = createApp();
beforeEach(async () => {
await resetDatabase();
});
after(async () => {
await prisma.$disconnect();
});
describe("GET /reference/diets", () => {
it("returns the seeded regimes, no session required", async () => {
const res = await request(app).get("/reference/diets");
expect(res.status).to.equal(200);
expect(res.body).to.have.length(5);
expect(res.body.map((d: { key: string }) => d.key)).to.include(slugify("Végétarien"));
expect(res.body[0]).to.have.keys(["id", "key"]);
});
});
describe("GET /reference/allergies", () => {
it("returns the seeded allergens with their key resolved, no session required", async () => {
const res = await request(app).get("/reference/allergies");
expect(res.status).to.equal(200);
expect(res.body).to.have.length(14);
expect(res.body.map((a: { key: string }) => a.key)).to.include(slugify("Arachides"));
expect(res.body[0]).to.have.keys(["id", "key", "kind"]);
});
it("classifies Gluten and Sulfites as intolerances, the rest as allergies", async () => {
const res = await request(app).get("/reference/allergies");
const byKey = (name: string) =>
res.body.find((a: { key: string }) => a.key === slugify(name));
expect(byKey("Gluten").kind).to.equal("INTOLERANCE");
expect(byKey("Sulfites").kind).to.equal("INTOLERANCE");
expect(byKey("Arachides").kind).to.equal("ALLERGY");
expect(res.body.filter((a: { kind: string }) => a.kind === "INTOLERANCE")).to.have.length(2);
});
});
describe("GET /reference/ingredients", () => {
it("returns the seeded ingredients, no session required", async () => {
const res = await request(app).get("/reference/ingredients");
expect(res.status).to.equal(200);
expect(res.body.length).to.be.greaterThan(0);
expect(res.body.map((i: { key: string }) => i.key)).to.include(slugify("Tomate"));
expect(res.body[0]).to.have.keys([
"id",
"key",
"icon",
"category",
"subcategory",
"allergens",
"diets",
]);
});
it("resolves each ingredient's linked allergens, empty for one with none", async () => {
const res = await request(app).get("/reference/ingredients");
const byKey = (name: string) =>
res.body.find((i: { key: string }) => i.key === slugify(name));
expect(byKey("Œuf").allergens.map((a: { key: string }) => a.key)).to.include(
slugify("Œufs"),
);
expect(byKey("Tomate").allergens).to.deep.equal([]);
});
});
});