import { describe, expect, it } from "vitest"; import { CANCEL_STATUSES, PAYMENT_STATUS_RANK, canTransitionPaymentStatus, isCancelStatus, parsePaymentStatus, toPaymentDisplayStatus, } from "./payment-status.js"; describe("payment status ladder", () => { it("ranks the ladder in consumer order", () => { expect(PAYMENT_STATUS_RANK.scheduled).toBe(1); expect(PAYMENT_STATUS_RANK.payment_submitted).toBe(2); expect(PAYMENT_STATUS_RANK.issued).toBe(3); expect(PAYMENT_STATUS_RANK.outstanding).toBe(4); expect(PAYMENT_STATUS_RANK.cleared).toBe(5); }); it("maps internal statuses to CSV display strings", () => { expect(toPaymentDisplayStatus("payment_submitted")).toBe("Payment Submitted"); expect(toPaymentDisplayStatus("cleared")).toBe("Cleared"); }); it("parses display and internal status strings", () => { expect(parsePaymentStatus("Payment Submitted")).toBe("payment_submitted"); expect(parsePaymentStatus("OUTSTANDING")).toBe("outstanding"); expect(parsePaymentStatus("scheduled")).toBe("scheduled"); expect(parsePaymentStatus("voided")).toBeNull(); }); it("allows forward transitions and same-rank no-ops", () => { expect(canTransitionPaymentStatus("scheduled", "payment_submitted")).toBe(true); expect(canTransitionPaymentStatus("issued", "Outstanding")).toBe(true); expect(canTransitionPaymentStatus("outstanding", "outstanding")).toBe(true); expect(canTransitionPaymentStatus("outstanding", "cleared")).toBe(true); }); it("blocks non-cancel rank regression", () => { expect(canTransitionPaymentStatus("issued", "scheduled")).toBe(false); expect(canTransitionPaymentStatus("cleared", "outstanding")).toBe(false); expect(canTransitionPaymentStatus("payment_submitted", "Scheduled")).toBe(false); }); it("allows void from ranks below cleared", () => { for (const status of ["scheduled", "payment_submitted", "issued", "outstanding"] as const) { expect(canTransitionPaymentStatus(status, "voided")).toBe(true); expect(canTransitionPaymentStatus(status, "Cancelled")).toBe(true); } }); it("blocks all transitions once cleared, including void", () => { expect(canTransitionPaymentStatus("cleared", "voided")).toBe(false); expect(canTransitionPaymentStatus("cleared", "cleared")).toBe(false); expect(canTransitionPaymentStatus("cleared", "outstanding")).toBe(false); }); it("recognizes cancel vocabulary case-insensitively", () => { for (const status of CANCEL_STATUSES) { expect(isCancelStatus(status)).toBe(true); expect(isCancelStatus(status.toUpperCase())).toBe(true); } expect(isCancelStatus("Marked As Void")).toBe(true); expect(isCancelStatus("Cleared")).toBe(false); }); });