mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-07 04:42:03 +00:00
83 lines
3 KiB
TypeScript
83 lines
3 KiB
TypeScript
|
|
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(
|
||
|
|
<SlideOverExtrasTab uploads={[]} isReadOnly={false} onUpload={onUpload} onRemove={vi.fn()} />,
|
||
|
|
);
|
||
|
|
|
||
|
|
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(
|
||
|
|
<SlideOverExtrasTab
|
||
|
|
uploads={[]}
|
||
|
|
mediaCounts={{ photos: 10, videos: 3 }}
|
||
|
|
isReadOnly={false}
|
||
|
|
onUpload={onUpload}
|
||
|
|
onRemove={vi.fn()}
|
||
|
|
/>,
|
||
|
|
);
|
||
|
|
|
||
|
|
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(
|
||
|
|
<SlideOverExtrasTab uploads={[]} isReadOnly={false} onUpload={onUpload} onRemove={vi.fn()} />,
|
||
|
|
);
|
||
|
|
|
||
|
|
selectFiles([video]);
|
||
|
|
|
||
|
|
await waitFor(() => expect(onUpload).toHaveBeenCalledWith([video]));
|
||
|
|
expect(toast.error).not.toHaveBeenCalled();
|
||
|
|
});
|
||
|
|
});
|