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