The theme only defines danger / danger-50 / danger-100 / danger-700, so bg-danger-600 / danger-500 / danger-200 generated no CSS — the modal confirm button was white-on-nothing (invisible) and the header button wasn't red. - Header "Cancel PO" button → solid red (bg-danger text-white hover:bg-danger-700) - Modal "Cancel this PO" confirm button → bg-danger (now visible) - Inputs/asterisk/banner border → defined danger tokens Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
45 lines
2.2 KiB
TypeScript
45 lines
2.2 KiB
TypeScript
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(<CancelPoButton poId="po1" poNumber="PO-1" />);
|
|
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(<CancelPoButton poId="po1" poNumber="PO-1" />);
|
|
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(<CancelPoButton poId="po1" poNumber="PO-1" />);
|
|
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);
|
|
});
|
|
});
|