import { fireEvent, render, screen, waitFor } from "@testing-library/react"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { MediaUploadModal } from "@/app/(protected)/workorders/_components/media/media-upload-modal"; import type { WorkOrderTableRow } from "@/domain/work-orders/types/work-order-table-row"; const uploadMutateAsync = vi.fn(); const deleteMutate = vi.fn(); const categorizeMutate = vi.fn(); vi.mock("@/domain/work-orders/use-cases/use-work-order-detail", () => ({ useWorkOrderBoardDetail: () => ({ data: { info: { status: "Scheduled", rowVersion: "DETAIL-VER==" }, media: [ { id: "11", fileName: "before.jpg", url: "https://example.com/before.jpg", category: "Before", isLegacy: false, }, ], comments: [], audit: [], completion: {}, }, isLoading: false, }), })); vi.mock("@/domain/work-orders/use-cases/use-work-order-mutations", () => ({ useUploadWorkOrderMedia: () => ({ mutate: vi.fn(), mutateAsync: uploadMutateAsync, isPending: false, }), useUpdateWorkOrderMediaCategory: () => ({ mutate: categorizeMutate, isPending: false }), useDeleteWorkOrderMedia: () => ({ mutate: deleteMutate, isPending: false }), })); function baseRow(): WorkOrderTableRow { return { id: 7, woNumber: "WO-7", site: "SEA1", type: "Emergency", severity: 1, dispatcherId: "u1", dispatcherName: "Dispatcher", scheduledOn: "2026-06-01", completedDate: "", targetWeek: "", dayGroup: "", dayLabel: "", location: "Seattle", locationId: "loc-1", pm: "", serviceNotes: "", extraServices: [], vendorId: "", company: "", tech: "", techPhone: "", apptStart: "", apptEnd: "", apptTime: "", status: "Scheduled", docStatus: "", pocName: "", pocPhone: "", pocNotes: "", additionalContacts: [], dueDate: "", rescheduleCount: 0, carriedOver: 0, originalWeek: "", originalDate: "", isPastDue: false, scheduleWeekOnly: false, mediaCount: 1, title: "Emergency", priority: "Sev 1", primaryDispatchId: null, rowVersion: "ROW-VER==", dispatchRowVersion: "", flagColor: null, isAddOn: false, upliftSummary: { hasUplift: false, pendingCount: 0 }, }; } function renderModal() { const client = new QueryClient({ defaultOptions: { queries: { retry: false }, mutations: { retry: false } }, }); return render( , ); } describe("MediaUploadModal API wiring", () => { beforeEach(() => { uploadMutateAsync.mockReset(); deleteMutate.mockReset(); categorizeMutate.mockReset(); }); it("renders persisted media from board detail (refresh-safe)", async () => { renderModal(); await waitFor(() => { expect(screen.getByText("before.jpg")).toBeInTheDocument(); }); expect(screen.getByText("Photos & Videos")).toBeInTheDocument(); expect( screen.getByText("Accepted: JPG, PNG, MP4, MOV · Max 50MB per file"), ).toBeInTheDocument(); expect(screen.queryByText(/categorize after upload/i)).not.toBeInTheDocument(); }); it("offers no purpose picker — the table modal only uploads and removes", async () => { renderModal(); await waitFor(() => { expect(screen.getByText("before.jpg")).toBeInTheDocument(); }); expect(screen.queryByLabelText(/category for before\.jpg/i)).not.toBeInTheDocument(); expect(screen.queryByText(/categorize after upload/i)).not.toBeInTheDocument(); expect(categorizeMutate).not.toHaveBeenCalled(); }); it("shows only the file name under each tile — no purpose label", async () => { renderModal(); await waitFor(() => { expect(screen.getByText("before.jpg")).toBeInTheDocument(); }); expect(screen.queryByText("Before")).not.toBeInTheDocument(); expect(screen.queryByText("Extra")).not.toBeInTheDocument(); }); it("removes media with workOrderVersion from detail.info.rowVersion", async () => { renderModal(); await waitFor(() => { expect(screen.getByText("before.jpg")).toBeInTheDocument(); }); fireEvent.click(screen.getByRole("button", { name: /^remove$/i })); expect(deleteMutate).toHaveBeenCalledWith({ mediaId: "11", workOrderVersion: "DETAIL-VER==", }); }); });