import { describe, it, expect } from "vitest"; import { normalizeOrderItemStatusInput } from "./order-item-status"; describe("normalizeOrderItemStatusInput", () => { it("returns empty patch when no fields supplied", () => { expect(normalizeOrderItemStatusInput({})).toEqual({}); }); it("accepts a valid item_status", () => { expect(normalizeOrderItemStatusInput({ item_status: "processed" })).toEqual({ item_status: "processed", }); }); it("accepts a valid drv_status", () => { expect(normalizeOrderItemStatusInput({ drv_status: "assigned" })).toEqual({ drv_status: "assigned", driver_status: "assigned", }); }); it("accepts legacy driver_status and mirrors to drv_status", () => { expect(normalizeOrderItemStatusInput({ driver_status: "en_route" })).toEqual({ drv_status: "en_route", driver_status: "en_route", }); }); it("prefers drv_status when both drv_status and driver_status are sent", () => { expect( normalizeOrderItemStatusInput({ drv_status: "assigned", driver_status: "failed" }) ).toEqual({ drv_status: "assigned", driver_status: "assigned", }); }); it("passes through notes and problem_notes strings", () => { expect( normalizeOrderItemStatusInput({ notes: "All good", problem_notes: "Damaged carton", }) ).toEqual({ notes: "All good", problem_notes: "Damaged carton", }); }); it("ignores notes/problem_notes that are not strings", () => { // @ts-expect-error — verifying runtime guard expect(normalizeOrderItemStatusInput({ notes: 123 })).toEqual({}); }); it("throws on invalid item_status", () => { expect(() => normalizeOrderItemStatusInput({ item_status: "definitely_not_valid" }) ).toThrow(/Invalid item_status/); }); it("throws on invalid drv_status", () => { expect(() => normalizeOrderItemStatusInput({ drv_status: "teleported" }) ).toThrow(/Invalid driver status/); }); it("throws on invalid driver_status (legacy alias)", () => { expect(() => normalizeOrderItemStatusInput({ driver_status: "teleported" }) ).toThrow(/Invalid driver status/); }); it("combines a full valid patch in one call", () => { expect( normalizeOrderItemStatusInput({ item_status: "delivered", drv_status: "collected", notes: "Signed for", problem_notes: "", }) ).toEqual({ item_status: "delivered", drv_status: "collected", driver_status: "collected", notes: "Signed for", problem_notes: "", }); }); // The /deliveries + n8n flows need to PATCH `with_driver`, // `checked_in`, and `completed`. Regression test for the bug // where the whitelist was missing these — the route would // throw "Invalid item_status" and the operator would see a // 500 instead of a successful transition. it("accepts the new delivery-tracking statuses", () => { for (const s of ["with_driver", "checked_in", "completed"] as const) { expect(normalizeOrderItemStatusInput({ item_status: s })).toEqual({ item_status: s, }); } }); // Also regression-tests the gap that was there before // 2026-07-20: `invoiced` / `ready_invoice` / `stock_booked` // were valid on the PB schema but rejected by the validator. it("accepts invoicing + stock-booked statuses", () => { for (const s of ["invoiced", "ready_invoice", "stock_booked"] as const) { expect(normalizeOrderItemStatusInput({ item_status: s })).toEqual({ item_status: s, }); } }); });