import { describe, expect, it } from "vitest"; import { createRequestSchema, matchShotCodes, parseShotCodes, resolveLineStage, waitingSeverity, } from "./delivery-request-state"; describe("parseShotCodes", () => { it("takes codes out of a pasted message whatever separates them", () => { expect(parseShotCodes("UNG_116_010, UNG_116_020\nUNG_116_030; 116-A-0040")).toEqual([ "UNG_116_010", "UNG_116_020", "UNG_116_030", "116-A-0040", ]); }); it("drops repeats regardless of case", () => { expect(parseShotCodes("ung_116_010 UNG_116_010")).toEqual(["ung_116_010"]); }); }); describe("matchShotCodes", () => { const shots = [ { id: "a", shotCode: "UNG_116_010", clientCode: "116_A_0010" }, { id: "b", shotCode: "UNG_116_020", clientCode: null }, ]; it("matches our code or the client's, in any case", () => { const { matched, unmatched } = matchShotCodes(["116_a_0010", "ung_116_020"], shots); expect(matched.map((s) => s.id)).toEqual(["a", "b"]); expect(unmatched).toEqual([]); }); it("reports what it could not match instead of dropping it", () => { expect(matchShotCodes(["UNG_116_010", "UNG_116_999"], shots).unmatched).toEqual(["UNG_116_999"]); }); it("counts a shot once when both of its codes are given", () => { expect(matchShotCodes(["UNG_116_010", "116_A_0010"], shots).matched).toHaveLength(1); }); }); describe("resolveLineStage", () => { const logged = new Date("2026-09-30T14:00:00Z"); const before = new Date("2026-09-20T10:00:00Z"); const after = new Date("2026-10-01T10:00:00Z"); const base = { requestCreatedAt: logged, packages: [], manual: { deliveredAt: null, url: null, sharedWith: null }, exportStatuses: [], }; it("walks a shot from not ready through to delivered", () => { expect(resolveLineStage(base)).toBe("NOT_READY"); expect(resolveLineStage({ ...base, exportStatuses: ["READY_FOR_QC"] })).toBe("IN_QC"); expect(resolveLineStage({ ...base, exportStatuses: ["READY_FOR_QC", "READY_FOR_DELIVERY"] })).toBe("READY"); const pkg = { status: "BUILDING", uploadedAt: null, deliveredAt: null }; expect(resolveLineStage({ ...base, packages: [pkg] })).toBe("BUILDING"); expect(resolveLineStage({ ...base, packages: [{ ...pkg, status: "READY" }] })).toBe("BUILT"); expect(resolveLineStage({ ...base, packages: [{ ...pkg, status: "READY", uploadedAt: after }] })).toBe("UPLOADED"); expect( resolveLineStage({ ...base, packages: [{ status: "DELIVERED", uploadedAt: after, deliveredAt: after }] }) ).toBe("DELIVERED"); }); it("does not let a delivery from before the request close it", () => { expect( resolveLineStage({ ...base, packages: [{ status: "DELIVERED", uploadedAt: before, deliveredAt: before }] }) ).toBe("NOT_READY"); }); it("closes on a manual delivery only with a link and a recipient", () => { const sameDay = new Date("2026-09-30T12:00:00Z"); const manual = { deliveredAt: sameDay, url: "https://x.example/f", sharedWith: "Sam" }; expect(resolveLineStage({ ...base, manual })).toBe("DELIVERED"); expect(resolveLineStage({ ...base, manual: { ...manual, url: null } })).toBe("NOT_READY"); expect(resolveLineStage({ ...base, manual: { ...manual, sharedWith: null } })).toBe("NOT_READY"); expect(resolveLineStage({ ...base, manual: { ...manual, deliveredAt: before } })).toBe("NOT_READY"); }); }); describe("waitingSeverity", () => { const now = new Date("2026-09-30T12:00:00Z").getTime(); const hoursAgo = (h: number) => new Date(now - h * 3600_000); it("escalates with age", () => { expect(waitingSeverity(hoursAgo(2), null, now)).toBe("normal"); expect(waitingSeverity(hoursAgo(30), null, now)).toBe("warning"); expect(waitingSeverity(hoursAgo(50), null, now)).toBe("critical"); }); it("is critical once past the due date, however new", () => { expect(waitingSeverity(hoursAgo(2), hoursAgo(1), now)).toBe("critical"); }); }); describe("createRequestSchema", () => { const base = { projectId: "p", deliverable: "EXR", requestedBy: "Sam" }; it("needs exactly one way of naming the shots", () => { expect(createRequestSchema.safeParse(base).success).toBe(false); expect(createRequestSchema.safeParse({ ...base, episode: "116" }).success).toBe(true); expect(createRequestSchema.safeParse({ ...base, episode: "116", shotCodes: "UNG_116_010" }).success).toBe(false); }); it("needs to know who asked", () => { expect(createRequestSchema.safeParse({ ...base, episode: "116", requestedBy: " " }).success).toBe(false); }); });