import { fireEvent, screen } from "@testing-library/react"; import { afterEach, describe, expect, it, vi } from "vitest"; import { toast } from "react-toastify"; import { SlideOverExtrasTab } from "@/app/(protected)/workorders/_components/detail/tabs/slide-over-extras-tab"; import { workOrdersApi } from "@/domain/work-orders/api/work-orders-api"; import type { MediaFile } from "@/domain/work-orders/types/work-order-media"; import { renderWithProviders } from "@/test/test-utils"; const photo: MediaFile = { id: "m1", name: "safety-form.pdf", fileType: "pdf", url: "blob:1", category: "Report", }; const avetaDoc: MediaFile = { id: "m2", name: "aveta-clearance.pdf", fileType: "pdf", url: "blob:2", category: "Aveta", }; describe("SlideOverExtrasTab Aveta", () => { afterEach(() => { vi.restoreAllMocks(); vi.unstubAllGlobals(); }); it("does not label the first extra document as Aveta when none is explicitly Aveta", () => { renderWithProviders( , ); expect(screen.getByText("safety-form.pdf")).toBeInTheDocument(); expect(screen.getAllByText("Aveta")).toHaveLength(1); }); it("labels only an explicitly Aveta-categorized extra document", () => { renderWithProviders( , ); expect(screen.getByText("safety-form.pdf")).toBeInTheDocument(); expect(screen.getByText("aveta-clearance.pdf")).toBeInTheDocument(); expect(screen.getAllByText("Aveta").length).toBeGreaterThanOrEqual(2); }); it("categorizes an Extra file as Aveta without auto-labeling the first upload", () => { const onCategorize = vi.fn(); renderWithProviders( , ); fireEvent.change(screen.getByLabelText("Category for safety-form.pdf"), { target: { value: "Aveta" }, }); expect(onCategorize).toHaveBeenCalledWith("m1", "Aveta"); expect(screen.queryByText("safety-form.pdf")).toBeInTheDocument(); }); it("opens Extra Docs through authenticated content instead of a static href", async () => { const blob = new Blob(["pdf"], { type: "application/pdf" }); const getMediaContent = vi.spyOn(workOrdersApi, "getMediaContent").mockResolvedValue(blob); const createObjectURL = vi.fn(() => "blob:authorized"); vi.stubGlobal("URL", { ...URL, createObjectURL, revokeObjectURL: vi.fn() }); const tab = { opener: window, location: { href: "about:blank" }, close: vi.fn(), }; const open = vi.fn(() => tab); vi.stubGlobal("open", open); renderWithProviders( , ); expect(screen.queryByRole("link")).not.toBeInTheDocument(); fireEvent.click(screen.getByRole("button", { name: "safety-form.pdf" })); await vi.waitFor(() => { expect(getMediaContent).toHaveBeenCalledWith(10, "m1"); }); expect(createObjectURL).toHaveBeenCalledWith(blob); expect(open).toHaveBeenCalledWith("about:blank", "_blank"); expect(tab.opener).toBeNull(); expect(tab.location.href).toBe("blob:authorized"); }); it("shows an error when the browser blocks the document tab", async () => { const getMediaContent = vi.spyOn(workOrdersApi, "getMediaContent"); const toastError = vi.spyOn(toast, "error").mockImplementation(vi.fn()); vi.stubGlobal( "open", vi.fn(() => null), ); renderWithProviders( , ); fireEvent.click(screen.getByRole("button", { name: "safety-form.pdf" })); expect(toastError).toHaveBeenCalledWith( "Unable to open this document. Please allow pop-ups and try again.", ); expect(getMediaContent).not.toHaveBeenCalled(); }); it("shows Extra Docs accept copy with PDF DOC and 50MB", () => { renderWithProviders( , ); expect( screen.getByText("Accepted: JPG, PNG, MP4, MOV, PDF, DOC ยท Max 50MB per file"), ).toBeInTheDocument(); const input = document.querySelector('input[type="file"]'); expect(input?.getAttribute("accept")).toContain(".pdf"); expect(input?.getAttribute("accept")).toContain(".doc"); expect(input?.getAttribute("accept")).toContain(".docx"); }); it("disables document opening until the work order id is available", () => { renderWithProviders( , ); expect(screen.getByRole("button", { name: "safety-form.pdf" })).toBeDisabled(); }); it("labels each extra item with its type and category", () => { const sitePhoto: MediaFile = { id: "m3", name: "site.jpg", fileType: "image", url: "blob:3", category: "Photo", purpose: "Extra", }; const walkthrough: MediaFile = { id: "m4", name: "walkthrough.mp4", fileType: "video", url: "blob:4", category: "Video", purpose: "Extra", }; renderWithProviders( , ); expect(screen.getByRole("group", { name: "Photo, Extra: site.jpg" })).toBeInTheDocument(); expect( screen.getByRole("group", { name: "Video, Extra: walkthrough.mp4" }), ).toBeInTheDocument(); expect( screen.getByRole("group", { name: "PDF, Aveta: aveta-clearance.pdf" }), ).toBeInTheDocument(); }); });