import { fireEvent, render, screen } from "@testing-library/react"; import { describe, expect, it, vi } from "vitest"; import { StatusCell } from "@/app/(protected)/workorders/_components/list/table/cells/status-cell"; import type { WizardWOStatus } from "@/domain/work-orders/types/work-order-wizard"; import type { WorkOrderTableRow } from "@/domain/work-orders/types/work-order-table-row"; const incompleteRow = { id: "wo-1", status: "Scheduled", dispatcherId: "", dispatcherName: "", company: "", vendorId: "", tech: "", completedDate: "", woNumber: "", pm: "", docStatus: "", mediaCount: 0, type: "PM", } as WorkOrderTableRow; describe("StatusCell closability gate", () => { it("does not submit Completed when required work-order data is missing", () => { const onChangeStatus = vi.fn(); render( , ); fireEvent.click(screen.getByRole("button", { name: /scheduled/i })); const completed = screen.getByRole("button", { name: /^completed$/i }); expect(completed.hasAttribute("disabled")).toBe(true); expect(completed.getAttribute("title") ?? "").toContain("Fill in"); fireEvent.click(completed); expect(onChangeStatus).not.toHaveBeenCalledWith("Completed"); }); it("does not offer Canceled", () => { render(); fireEvent.click(screen.getByRole("button", { name: /scheduled/i })); expect(screen.queryByRole("button", { name: /^canceled$/i })).toBeNull(); }); it.each([ "Pending", "En Route", "On Site", "In Progress", "Rescheduled", "Pending Quote", ])("offers only manual transitions away from %s (SH-357, SH-358)", (current) => { const onChangeStatus = vi.fn(); render( , ); fireEvent.click(screen.getByRole("button", { name: new RegExp(current, "i") })); const offered = Array.from(document.querySelectorAll(".MuiPopover-paper button")).map( (button) => button.textContent?.trim(), ); expect(offered).not.toContain("Incomplete"); expect(offered).not.toContain("Scheduled"); expect(offered).not.toContain("Past Due"); expect(offered).not.toContain("Canceled"); expect(offered).not.toContain(current); expect(offered).toEqual( [ "Pending", "En Route", "On Site", "In Progress", "Completed", "Rescheduled", "Pending Quote", ].filter((status) => status !== current), ); }); it("offers every manual status, and no automatic one, from Incomplete or Scheduled", () => { for (const current of ["Incomplete", "Scheduled"] as const) { const { unmount } = render( , ); fireEvent.click(screen.getByRole("button", { name: new RegExp(current, "i") })); expect(screen.getByRole("button", { name: /^pending$/i })).toBeTruthy(); expect(screen.queryByRole("button", { name: /^incomplete$/i })).toBeNull(); expect(screen.queryByRole("button", { name: /^scheduled$/i })).toBeNull(); unmount(); } }); it("limits creation options to Incomplete, Pending, and Scheduled", () => { render( , ); fireEvent.click(screen.getByRole("button", { name: /incomplete/i })); expect(screen.getByRole("button", { name: /^pending$/i })).toBeTruthy(); expect(screen.queryByRole("button", { name: /^en route$/i })).toBeNull(); }); });