import { test, expect } from "bun:test"; import { normalizeInputSync, normalizeInput } from "./normalize.ts"; test("structured FillEvent → fast path", () => { const n = normalizeInputSync({ kind: "baseline_fill", role: "Welder", city: "Nashville", state: "TN", count: 4, }); expect(n.extraction_method).toBe("structured"); expect(n.role).toBe("Welder"); expect(n.city).toBe("Nashville"); expect(n.state).toBe("TN"); expect(n.count).toBe(4); expect(n.confidence).toBe("high"); expect(n.missing_fields.length).toBe(0); }); test("misplacement kind → rescue intent", () => { const n = normalizeInputSync({ kind: "misplacement", role: "Welder", city: "Nashville", state: "TN", count: 1 }); expect(n.intent).toBe("rescue"); }); test("structured with full state name normalizes to abbrev", () => { const n = normalizeInputSync({ role: "Welder", city: "Nashville", state: "Tennessee" }); expect(n.state).toBe("TN"); }); test("natural-language regex path extracts count + role + city + state", () => { const n = normalizeInputSync("I need 3 Welders in Nashville, TN for next week"); expect(n.role).toBe("Welder"); expect(n.city).toBe("Nashville"); expect(n.state).toBe("TN"); expect(n.count).toBe(3); expect(n.intent).toBe("fill"); expect(n.extraction_method).toBe("regex"); }); test("natural language with plural role + full state name", () => { const n = normalizeInputSync("fill 5 Forklift Operators in Chicago, Illinois"); expect(n.role).toBe("Forklift Operator"); expect(n.city).toBe("Chicago"); expect(n.state).toBe("IL"); expect(n.count).toBe(5); }); test("rescue intent keyword beats fill", () => { const n = normalizeInputSync("we need to rescue the Nashville welder fill, 2 workers"); expect(n.intent).toBe("rescue"); expect(n.count).toBe(2); expect(n.role).toBe("Welder"); }); test("partial input reports missing fields with confidence=low or medium", () => { const n = normalizeInputSync("need welders"); expect(n.role).toBe("Welder"); expect(n.city).toBeNull(); expect(n.state).toBeNull(); expect(n.count).toBeNull(); expect(n.missing_fields).toContain("city"); expect(n.missing_fields).toContain("state"); expect(n.confidence).toBe("low"); }); test("empty object does NOT go through structured path (no role or city)", () => { const n = normalizeInputSync({}); expect(n.extraction_method).toBe("regex"); }); test("async normalizeInput on clean structured input matches sync", async () => { const input = { role: "Welder", city: "Nashville", state: "TN", count: 3 }; const sync = normalizeInputSync(input); const async_ = await normalizeInput(input); expect(async_.role).toBe(sync.role); expect(async_.city).toBe(sync.city); expect(async_.state).toBe(sync.state); expect(async_.count).toBe(sync.count); });