import { fireEvent, render, screen } from "@testing-library/react"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { CompDocDialog } from "@/app/(protected)/workorders/_components/comp-doc/comp-doc-dialog"; import type { WorkOrderTableRow } from "@/domain/work-orders/types/work-order-table-row"; vi.mock("@/domain/locations/use-cases/use-location-detail", () => ({ useLocationDetail: () => ({ data: undefined }), })); vi.mock("react-toastify", () => ({ toast: vi.fn(), })); const SCHEDULED_ON = "2026-06-01"; function baseRow(overrides: Partial = {}): WorkOrderTableRow { return { id: 42, woNumber: "WO-42", site: "SEA1", type: "PM", dispatcherId: "u1", dispatcherName: "Dispatcher", scheduledOn: SCHEDULED_ON, completedDate: "", targetWeek: "", dayGroup: "", dayLabel: "", location: "Seattle", locationId: "mock-loc-1", pm: "HVAC", company: "Vendor Co", tech: "Tech One", techPhone: "", apptStart: "", apptEnd: "", apptTime: "", status: "Scheduled", docStatus: "No", pocName: "Amazon Rep", pocPhone: "", pocNotes: "", dueDate: "", rescheduleCount: 0, carriedOver: 0, originalWeek: "", originalDate: "", isPastDue: false, scheduleWeekOnly: false, mediaCount: 0, title: "PM — SEA1", priority: "Sev 3", ...overrides, }; } describe("CompDocDialog Save Draft / Generate completion contract", () => { const onSave = vi.fn(); const onDateCompletedChange = vi.fn(); beforeEach(() => { onSave.mockReset(); onDateCompletedChange.mockReset(); }); function renderDialog(row: WorkOrderTableRow) { // Mirrors board wiring: only completedDate / docStatus — never scheduledOn or lifecycle. const patches: Array> = []; const client = new QueryClient({ defaultOptions: { queries: { retry: false }, mutations: { retry: false } }, }); render( { onSave(data, status); patches.push({ docStatus: status }); }} onDateCompletedChange={(date) => { onDateCompletedChange(date); patches.push({ completedDate: date }); }} /> , ); return { patches }; } function changeDateCompleted(value: string) { const dateInput = document.querySelector('input[type="date"]'); expect(dateInput).not.toBeNull(); fireEvent.change(dateInput!, { target: { value } }); } it("Save draft emits completedDate without writing scheduledOn or lifecycle Completed", () => { const row = baseRow(); const { patches } = renderDialog(row); changeDateCompleted("2026-07-15"); fireEvent.click(screen.getByRole("button", { name: /save draft/i })); expect(onDateCompletedChange).toHaveBeenCalledWith("2026-07-15"); expect(onSave).toHaveBeenCalledWith(expect.any(Object), "No"); expect(patches).toEqual([{ docStatus: "No" }, { completedDate: "2026-07-15" }]); expect(patches.some((patch) => "scheduledOn" in patch)).toBe(false); expect(patches.some((patch) => patch.status === "Completed")).toBe(false); expect(row.scheduledOn).toBe(SCHEDULED_ON); expect(row.status).toBe("Scheduled"); }); it("Generate emits completedDate and doc Yes without auto-setting lifecycle Completed", () => { const row = baseRow({ completedDate: "2026-07-01" }); const { patches } = renderDialog(row); changeDateCompleted("2026-07-20"); fireEvent.click(screen.getByRole("button", { name: /^generate$/i })); expect(onDateCompletedChange).toHaveBeenCalledWith("2026-07-20"); expect(onSave).toHaveBeenCalledWith( expect.objectContaining({ generatedAt: expect.any(String) }), "Yes", ); expect(patches).toEqual([{ docStatus: "Yes" }, { completedDate: "2026-07-20" }]); expect(patches.some((patch) => "scheduledOn" in patch)).toBe(false); expect(patches.some((patch) => patch.status === "Completed")).toBe(false); expect(row.scheduledOn).toBe(SCHEDULED_ON); expect(row.status).toBe("Scheduled"); }); });