batchCooking/apps/api/test/reference.test.ts
Nicolas 5890c62462 fix(recipes): overflow des préférences + régimes liés aux ingrédients
- Fix overflow horizontal sur /parametres/preferences : <fieldset> a un
  min-width: min-content par défaut du navigateur, ce qui empêchait la
  grille de l'IngredientPicker de wrapper (page entière poussée à
  ~3100px de large). Reset min-width: 0 sur .disliked-ingredients-field.
- Recatégorise les laits/crèmes végétaux (coco, amande, avoine) de
  PRODUITS_LAITIERS_OEUFS vers LIQUIDES_BOISSONS — ce ne sont pas des
  produits laitiers.
- Nouveau modèle IngredientDiet (many-to-many ingrédient <-> régime) :
  quels régimes (Végétarien, Végan, Pescétarien) chaque ingrédient
  respecte. Omnivore volontairement absent (trivial) et Sans gluten
  aussi (déjà dérivable de l'allergène Gluten existant).
- reference-seed-data.ts : chaque groupe de catégorie porte un
  defaultDiets, avec dietNames en override pour les exceptions
  (fromages, viandes, poissons, sauces à base d'œuf/poisson...).
- IngredientView.diets exposé par /reference/ingredients et /recipes,
  affiché via DietBadges dans IngredientPicker et IngredientRow.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-18 11:01:57 +02:00

68 lines
2.7 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";
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: { name: string }) => d.name)).to.include("Végétarien");
expect(res.body[0]).to.have.keys(["id", "name"]);
});
});
describe("GET /reference/allergies", () => {
it("returns the seeded allergens with their name 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: { name: string }) => a.name)).to.include("Arachides");
expect(res.body[0]).to.have.keys(["id", "name", "kind"]);
});
it("classifies Gluten and Sulfites as intolerances, the rest as allergies", async () => {
const res = await request(app).get("/reference/allergies");
const byName = (name: string) => res.body.find((a: { name: string }) => a.name === name);
expect(byName("Gluten").kind).to.equal("INTOLERANCE");
expect(byName("Sulfites").kind).to.equal("INTOLERANCE");
expect(byName("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: { name: string }) => i.name)).to.include("Tomate");
expect(res.body[0]).to.have.keys(["id", "name", "icon", "category", "allergens", "diets"]);
});
it("resolves each ingredient's linked allergens, empty for one with none", async () => {
const res = await request(app).get("/reference/ingredients");
const byName = (name: string) => res.body.find((i: { name: string }) => i.name === name);
expect(byName("Œuf").allergens.map((a: { name: string }) => a.name)).to.include("Œufs");
expect(byName("Tomate").allergens).to.deep.equal([]);
});
});
});