feat(recipe-generation): matsäkerhetslint för rå fågel/fläsk/ägg/fisk
This commit is contained in:
@@ -68,6 +68,27 @@ const mockIngredients: CanonicalIngredientLookup = {
|
||||
isBeef: false,
|
||||
isAlcohol: false,
|
||||
},
|
||||
chicken_breast: {
|
||||
id: "chicken_breast",
|
||||
nutritionPer100: {
|
||||
basis: "per_100_g",
|
||||
values: {
|
||||
kcal: 165, proteinG: 31, carbsG: 0, fatG: 3.6,
|
||||
saturatedFatG: 1, fiberG: 0, sugarG: 0, saltG: 0.1,
|
||||
},
|
||||
},
|
||||
defaultUnit: "GRAM",
|
||||
densityGPerMl: null,
|
||||
gramsPerPiece: null,
|
||||
allergens: [],
|
||||
isVegan: false,
|
||||
isVegetarian: false,
|
||||
containsGluten: false,
|
||||
containsLactose: false,
|
||||
isPork: false,
|
||||
isBeef: false,
|
||||
isAlcohol: false,
|
||||
},
|
||||
};
|
||||
return db[id] ?? undefined;
|
||||
},
|
||||
@@ -211,4 +232,38 @@ describe("verifyCandidate", () => {
|
||||
expect(result.status).toBe("unverified");
|
||||
expect(result.reasons.some((r) => r.includes("dubblett"))).toBe(true);
|
||||
});
|
||||
|
||||
it("kräver genomstekningssteg för rå fågel (positivt)", async () => {
|
||||
const c = makeCandidate({
|
||||
ingredients: [
|
||||
{ canonicalIngredientId: "chicken_breast", displayNameSv: "kycklingfilé", quantity: 500, unit: "GRAM", optional: false, note: null },
|
||||
{ canonicalIngredientId: "ris", displayNameSv: "ris", quantity: 300, unit: "GRAM", optional: false, note: null },
|
||||
{ canonicalIngredientId: "krossade_tomater", displayNameSv: "krossade tomater", quantity: 400, unit: "GRAM", optional: false, note: null },
|
||||
],
|
||||
steps: [
|
||||
{ stepNumber: 1, instructionSv: "Stek kycklingen tills den är genomstekt och innertemperaturen är 72°C.", timerSeconds: null, temperatureC: null, tip: null },
|
||||
{ stepNumber: 2, instructionSv: "Tillsätt ris och tomater, koka klart.", timerSeconds: null, temperatureC: null, tip: null },
|
||||
],
|
||||
});
|
||||
const result = await verifyCandidate(c, mockIngredients, noSimilarity);
|
||||
expect(result.status).toBe("verified");
|
||||
expect(result.reasons).not.toContain("Receptet innehåller rått kött/fågel/ägg/fisk men saknar steg för genomstekning/temperatur.");
|
||||
});
|
||||
|
||||
it("markerar unverified när rå fågel saknar genomstekningssteg (negativt)", async () => {
|
||||
const c = makeCandidate({
|
||||
ingredients: [
|
||||
{ canonicalIngredientId: "chicken_breast", displayNameSv: "kycklingfilé", quantity: 500, unit: "GRAM", optional: false, note: null },
|
||||
{ canonicalIngredientId: "ris", displayNameSv: "ris", quantity: 300, unit: "GRAM", optional: false, note: null },
|
||||
{ canonicalIngredientId: "krossade_tomater", displayNameSv: "krossade tomater", quantity: 400, unit: "GRAM", optional: false, note: null },
|
||||
],
|
||||
steps: [
|
||||
{ stepNumber: 1, instructionSv: "Stek kycklingen i pannan.", timerSeconds: null, temperatureC: null, tip: null },
|
||||
{ stepNumber: 2, instructionSv: "Tillsätt ris och tomater, koka klart.", timerSeconds: null, temperatureC: null, tip: null },
|
||||
],
|
||||
});
|
||||
const result = await verifyCandidate(c, mockIngredients, noSimilarity);
|
||||
expect(result.status).toBe("unverified");
|
||||
expect(result.reasons).toContain("Receptet innehåller rått kött/fågel/ägg/fisk men saknar steg för genomstekning/temperatur.");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user