import { computeRecipeDietViews, type DietView, type IngredientView } from "@batch-cooking/shared"; import { expect } from "chai"; /** * Pure regime derivation from `@batch-cooking/shared` — no DB, so this suite * skips `resetDatabase`. `recipe.service.ts`'s `toRecipeSummaryView` calls * it for every recipe read (issue #131 dropped the hand-tagged `RecipeDiet`). */ const VEGETARIAN: DietView = { id: 1, key: "vegetarian" }; const VEGAN: DietView = { id: 2, key: "vegan" }; const PESCATARIAN: DietView = { id: 3, key: "pescatarian" }; const GLUTEN_FREE: DietView = { id: 4, key: "glutenFree" }; /** A minimal ingredient fixture — only the fields `computeRecipeDietViews` reads. */ function ingredient( diets: DietView[], opts: { gluten?: boolean; placeholder?: boolean } = {}, ): Pick { return { diets, allergens: opts.gluten ? [{ id: 9, key: "gluten", kind: "INTOLERANCE" }] : [], isPlaceholder: opts.placeholder ?? false, }; } describe("computeRecipeDietViews", () => { it("keeps only the regimes every ingredient is compatible with", () => { const result = computeRecipeDietViews( [ ingredient([VEGETARIAN, VEGAN, PESCATARIAN]), ingredient([VEGETARIAN, PESCATARIAN]), // e.g. egg — not vegan ], GLUTEN_FREE, ); expect(result.map((d) => d.key)).to.deep.equal(["vegetarian", "pescatarian", "glutenFree"]); }); it("drops every ingredient-derived regime when one ingredient is compatible with none", () => { const result = computeRecipeDietViews( [ingredient([VEGETARIAN, VEGAN, PESCATARIAN]), ingredient([])], GLUTEN_FREE, ); // Still gluten-free — nothing carries the allergen. expect(result.map((d) => d.key)).to.deep.equal(["glutenFree"]); }); it("is not gluten-free when any ingredient carries the gluten allergen", () => { const result = computeRecipeDietViews( [ ingredient([VEGETARIAN, VEGAN, PESCATARIAN]), ingredient([VEGETARIAN, VEGAN, PESCATARIAN], { gluten: true }), ], GLUTEN_FREE, ); expect(result.map((d) => d.key)).to.deep.equal(["vegetarian", "vegan", "pescatarian"]); }); it("returns [] for a recipe with any placeholder (off-catalog) ingredient", () => { const result = computeRecipeDietViews( [ingredient([VEGETARIAN, VEGAN, PESCATARIAN]), ingredient([], { placeholder: true })], GLUTEN_FREE, ); expect(result).to.deep.equal([]); }); it("returns [] when there are no ingredients", () => { expect(computeRecipeDietViews([], GLUTEN_FREE)).to.deep.equal([]); }); it("omits gluten-free entirely when no glutenFree DietView is supplied", () => { const result = computeRecipeDietViews( [ingredient([VEGAN, VEGETARIAN, PESCATARIAN])], undefined, ); expect(result.map((d) => d.key)).to.deep.equal(["vegetarian", "vegan", "pescatarian"]); }); it("borrows each regime's DietView (id + key) from the ingredients themselves", () => { const result = computeRecipeDietViews( [ingredient([VEGETARIAN]), ingredient([VEGETARIAN])], undefined, ); expect(result).to.deep.equal([VEGETARIAN]); }); });