import { fireEvent, waitFor } from "@testing-library/react"; import { beforeEach, 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 { probeVideoDurationSeconds } from "@/lib/probe-video-duration"; import { renderWithProviders } from "@/test/test-utils"; vi.mock("react-toastify", () => ({ toast: { error: vi.fn() } })); vi.mock("@/lib/probe-video-duration", () => ({ probeVideoDurationSeconds: vi.fn() })); const MB = 1_000_000; function phoneFile(name: string, type: string, size: number): File { return { name, type, size } as File; } function selectFiles(files: File[]) { const input = document.querySelector('input[type="file"]'); fireEvent.change(input as HTMLInputElement, { target: { files } }); } describe("SlideOverExtrasTab SH-116 media contract", () => { beforeEach(() => { vi.mocked(toast.error).mockClear(); vi.mocked(probeVideoDurationSeconds).mockReset(); vi.mocked(probeVideoDurationSeconds).mockResolvedValue(30); }); it("rejects a video longer than 90 seconds before upload", async () => { vi.mocked(probeVideoDurationSeconds).mockResolvedValue(95); const onUpload = vi.fn(); renderWithProviders( , ); selectFiles([phoneFile("IMG_0700.MOV", "video/quicktime", 40 * MB)]); await waitFor(() => expect(toast.error).toHaveBeenCalledWith("Videos must be 90 seconds or shorter."), ); expect(onUpload).not.toHaveBeenCalled(); }); it("rejects the 11th photo and 4th video counted across the whole work order", async () => { const onUpload = vi.fn(); const report = phoneFile("inspection.pdf", "application/pdf", 2 * MB); renderWithProviders( , ); selectFiles([ phoneFile("IMG_0701.jpg", "image/jpeg", 2 * MB), phoneFile("IMG_0702.MOV", "video/quicktime", 20 * MB), report, ]); await waitFor(() => expect(onUpload).toHaveBeenCalledTimes(1)); expect(onUpload).toHaveBeenCalledWith([report]); expect(toast.error).toHaveBeenCalledWith("A work order can have at most 10 photos."); expect(toast.error).toHaveBeenCalledWith("A work order can have at most 3 videos."); }); it("accepts a ~60 MB phone video whose duration the browser cannot read", async () => { vi.mocked(probeVideoDurationSeconds).mockResolvedValue(null); const onUpload = vi.fn(); const video = phoneFile("IMG_0703.MOV", "", 60 * MB); renderWithProviders( , ); selectFiles([video]); await waitFor(() => expect(onUpload).toHaveBeenCalledWith([video])); expect(toast.error).not.toHaveBeenCalled(); }); });