Cancelled{po.cancelledAt ? ` on ${formatDate(po.cancelledAt)}` : ""}
diff --git a/App/tests/unit/cancel-po-controls.test.tsx b/App/tests/unit/cancel-po-controls.test.tsx
new file mode 100644
index 0000000..921dbb2
--- /dev/null
+++ b/App/tests/unit/cancel-po-controls.test.tsx
@@ -0,0 +1,45 @@
+import { describe, it, expect, vi } from "vitest";
+import { render, screen, fireEvent } from "@testing-library/react";
+
+vi.mock("next/navigation", () => ({ useRouter: () => ({ refresh: vi.fn(), push: vi.fn() }) }));
+vi.mock("@/app/(portal)/po/[id]/actions", () => ({ cancelPo: vi.fn(), supersedePo: vi.fn() }));
+
+import { CancelPoButton } from "@/components/po/cancel-po-controls";
+
+// Regression guard: the theme only defines danger / -50 / -100 / -700, so an
+// undefined shade like bg-danger-600 renders no background → the button was
+// invisible (white text on nothing). Both cancel buttons must use `bg-danger`.
+
+describe("CancelPoButton", () => {
+ it("renders the trigger as a filled red (bg-danger) button with white text", () => {
+ render(
);
+ const btn = screen.getByRole("button", { name: "Cancel PO" });
+ // standalone `bg-danger` (a defined token), NOT `bg-danger-600` (undefined → invisible)
+ expect(btn.className).toMatch(/(?:^|\s)bg-danger(?:\s|$)/);
+ expect(btn.className).toContain("text-white");
+ });
+
+ it("opens a modal whose confirm button is a visible filled danger button", () => {
+ render(
);
+ fireEvent.click(screen.getByRole("button", { name: "Cancel PO" }));
+
+ const confirm = screen.getByRole("button", { name: "Cancel this PO" });
+ expect(confirm.className).toMatch(/(?:^|\s)bg-danger(?:\s|$)/);
+ expect(confirm.className).toContain("text-white");
+
+ // Keep PO is always present as the safe default.
+ expect(screen.getByRole("button", { name: "Keep PO" })).toBeInTheDocument();
+ });
+
+ it("keeps the confirm action disabled until 'cancel' is typed and a reason given", () => {
+ render(
);
+ fireEvent.click(screen.getByRole("button", { name: "Cancel PO" }));
+
+ const confirm = screen.getByRole("button", { name: "Cancel this PO" }) as HTMLButtonElement;
+ expect(confirm.disabled).toBe(true);
+
+ fireEvent.change(screen.getByPlaceholderText(/Duplicate order/i), { target: { value: "No longer needed" } });
+ fireEvent.change(screen.getByPlaceholderText("cancel"), { target: { value: "cancel" } });
+ expect(confirm.disabled).toBe(false);
+ });
+});
--
2.45.3