- 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>
81 lines
2.9 KiB
TypeScript
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([]);
|
|
});
|
|
});
|
|
});
|