import { fireEvent, render, screen, waitFor } from "@testing-library/react"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { toast } from "react-toastify"; import { WorkOrderSlideOver } from "@/app/(protected)/workorders/_components/detail/work-order-slide-over"; import type { WorkOrderTableRow } from "@/domain/work-orders/types/work-order-table-row"; vi.mock("@/providers/auth-context", async (importOriginal) => { const actual = await importOriginal(); return { ...actual, useAuthContext: () => ({ user: { id: "u1" } }) }; }); vi.mock("@/domain/work-orders/use-cases/use-work-order-detail", () => ({ useWorkOrderBoardDetail: () => ({ data: undefined, isLoading: false, isFetching: false, error: null, refetch: vi.fn(), }), })); // A completion-doc upload that settles successfully. The mock forwards any onSuccess the // caller passes; the fix means the slide-over passes none (no follow-up docStatus patch). vi.mock("@/domain/work-orders/use-cases/use-work-order-mutations", () => ({ useAddWorkOrderComment: () => ({ mutate: vi.fn(), isPending: false }), useUpdateWorkOrderComment: () => ({ mutate: vi.fn(), isPending: false }), useUploadWorkOrderMedia: () => ({ mutate: vi.fn(), mutateAsync: vi.fn(), isPending: false }), useUpdateWorkOrderMediaCategory: () => ({ mutate: vi.fn(), isPending: false }), useDeleteWorkOrderMedia: () => ({ mutate: vi.fn(), isPending: false }), useUploadCompletionDoc: () => ({ mutate: (_vars: unknown, options?: { onSuccess?: () => void | Promise }) => { void options?.onSuccess?.(); }, isPending: false, }), })); vi.mock("react-toastify", () => ({ toast: { error: vi.fn(), success: vi.fn() } })); function baseRow(overrides: Partial = {}): WorkOrderTableRow { return { id: 42, woNumber: "WO-42", site: "SEA1", type: "PM", severity: null, dispatcherId: "u1", dispatcherName: "Dispatcher", scheduledOn: "2026-07-20", completedDate: "", targetWeek: "", dayGroup: "07/20", dayLabel: "Mon", location: "Seattle", locationId: "loc-1", pm: "HVAC", serviceNotes: "", extraServices: [], company: "Vendor Co", tech: "Tech", techPhone: "", vendorId: "v1", apptStart: "", apptEnd: "", apptTime: "", status: "Scheduled", docStatus: "No", pocName: "", pocPhone: "", pocNotes: "", additionalContacts: [], dueDate: "", rescheduleCount: 0, carriedOver: 0, originalWeek: "", originalDate: "", isPastDue: false, scheduleWeekOnly: false, mediaCount: 0, title: "PM — SEA1", priority: "Sev 3", primaryDispatchId: null, rowVersion: "v1", dispatchRowVersion: "", flagColor: null, isAddOn: false, upliftSummary: { hasUplift: false, pendingCount: 0 }, ...overrides, }; } describe("WorkOrderSlideOver signed PDF upload (SH-380)", () => { beforeEach(() => { vi.clearAllMocks(); }); it("does not issue a docStatus patch or surface an error after a successful upload", async () => { const row = baseRow(); // A follow-up docStatus patch would carry the pre-upload version and reject; assert none runs. const onSave = vi.fn( ( _id: string | number, _patch: Partial, options?: { onSuccess?: () => void; onError?: (error: Error) => void }, ) => { options?.onError?.(new Error("The record was modified by another user.")); }, ); render( , ); fireEvent.click(screen.getByRole("tab", { name: /completion doc/i })); const pdfInput = document.querySelector('input[accept="application/pdf,.pdf"]'); expect(pdfInput).not.toBeNull(); fireEvent.change(pdfInput!, { target: { files: [ new File([new Uint8Array([0x25, 0x50, 0x44, 0x46, 0x2d])], "signed.pdf", { type: "application/pdf", }), ], }, }); await waitFor(() => { expect(vi.mocked(toast.error)).not.toHaveBeenCalled(); }); expect(onSave).not.toHaveBeenCalled(); }); });