import { expect } from "chai"; import { type TechStepMappingRule, matchTechStep, normalizeText, } from "../src/lib/tech-step-matcher.js"; describe("tech-step-matcher", () => { describe("normalizeText", () => { it("lowercases and strips accents", () => { expect(normalizeText("Déglacer AU FOUR")).to.equal("deglacer au four"); }); }); describe("matchTechStep", () => { const simmer: TechStepMappingRule = { techStepId: 1, expression: "\\bmijot(er|ez|e|ant|é)\\b", weight: 15, }; const cook: TechStepMappingRule = { techStepId: 2, expression: "\\bcui(re|sez|sant|sson)\\b|\\bcuit(e|es|s)?\\b", weight: 10, }; const bake: TechStepMappingRule = { techStepId: 3, expression: "\\bcuire au four\\b|\\bcuisson au four\\b|\\benfourn(er|ez|é|ée|ées)\\b|\\bau four\\b", weight: 25, }; it("matches an exact expression", () => { expect(matchTechStep("Faire mijoter à feu doux", [simmer])).to.equal(1); }); it("is case- and accent-insensitive", () => { expect(matchTechStep("FAIRE MIJOTER", [simmer])).to.equal(1); expect(matchTechStep("faire mijoter", [simmer])).to.equal(1); }); it("returns null when nothing matches", () => { expect(matchTechStep("Servir immédiatement", [simmer, cook, bake])).to.be.null; }); it("picks the highest-weight match when several mappings match", () => { // "Cuire au four" matches both `cook` (weight 10) and `bake` (weight 25). expect(matchTechStep("Cuire au four pendant 30 minutes", [cook, bake])).to.equal(3); // Order-independent. expect(matchTechStep("Cuire au four pendant 30 minutes", [bake, cook])).to.equal(3); }); it("breaks a weight tie by lowest techStepId", () => { const a: TechStepMappingRule = { techStepId: 5, expression: "\\bmelanger\\b", weight: 10 }; const b: TechStepMappingRule = { techStepId: 2, expression: "\\bmelanger\\b", weight: 10 }; expect(matchTechStep("Mélanger les ingrédients", [a, b])).to.equal(2); }); }); });