2026-08-25 15:11:25 -03:00
|
|
|
import { fireEvent, screen } from "@testing-library/react";
|
2026-09-08 11:33:21 -03:00
|
|
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
2026-08-24 15:16:51 -03:00
|
|
|
import { SlideOverExtrasTab } from "@/app/(protected)/workorders/_components/detail/tabs/slide-over-extras-tab";
|
2026-09-08 11:33:21 -03:00
|
|
|
import { workOrdersApi } from "@/domain/work-orders/api/work-orders-api";
|
2026-08-24 15:16:51 -03:00
|
|
|
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",
|
|
|
|
|
};
|
|
|
|
|
|
2026-08-25 12:03:36 -03:00
|
|
|
const avetaDoc: MediaFile = {
|
|
|
|
|
id: "m2",
|
|
|
|
|
name: "aveta-clearance.pdf",
|
|
|
|
|
fileType: "pdf",
|
|
|
|
|
url: "blob:2",
|
|
|
|
|
category: "Aveta",
|
|
|
|
|
};
|
|
|
|
|
|
2026-08-24 15:16:51 -03:00
|
|
|
describe("SlideOverExtrasTab Aveta", () => {
|
2026-09-08 11:33:21 -03:00
|
|
|
afterEach(() => {
|
|
|
|
|
vi.restoreAllMocks();
|
|
|
|
|
vi.unstubAllGlobals();
|
|
|
|
|
});
|
2026-08-25 12:03:36 -03:00
|
|
|
it("does not label the first extra document as Aveta when none is explicitly Aveta", () => {
|
2026-08-24 15:16:51 -03:00
|
|
|
renderWithProviders(
|
|
|
|
|
<SlideOverExtrasTab
|
|
|
|
|
uploads={[photo]}
|
|
|
|
|
avetaRequired
|
|
|
|
|
isReadOnly
|
|
|
|
|
onUpload={vi.fn()}
|
|
|
|
|
onRemove={vi.fn()}
|
|
|
|
|
/>,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
expect(screen.getByText("safety-form.pdf")).toBeInTheDocument();
|
2026-08-25 12:03:36 -03:00
|
|
|
expect(screen.getAllByText("Aveta")).toHaveLength(1);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("labels only an explicitly Aveta-categorized extra document", () => {
|
|
|
|
|
renderWithProviders(
|
|
|
|
|
<SlideOverExtrasTab
|
|
|
|
|
uploads={[photo, avetaDoc]}
|
|
|
|
|
avetaRequired
|
|
|
|
|
isReadOnly
|
|
|
|
|
onUpload={vi.fn()}
|
|
|
|
|
onRemove={vi.fn()}
|
|
|
|
|
/>,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
expect(screen.getByText("safety-form.pdf")).toBeInTheDocument();
|
|
|
|
|
expect(screen.getByText("aveta-clearance.pdf")).toBeInTheDocument();
|
|
|
|
|
expect(screen.getAllByText("Aveta").length).toBeGreaterThanOrEqual(2);
|
2026-08-24 15:16:51 -03:00
|
|
|
});
|
2026-08-25 15:11:25 -03:00
|
|
|
|
|
|
|
|
it("categorizes an Extra file as Aveta without auto-labeling the first upload", () => {
|
|
|
|
|
const onCategorize = vi.fn();
|
|
|
|
|
renderWithProviders(
|
|
|
|
|
<SlideOverExtrasTab
|
|
|
|
|
uploads={[photo]}
|
|
|
|
|
avetaRequired
|
|
|
|
|
isReadOnly={false}
|
|
|
|
|
onUpload={vi.fn()}
|
|
|
|
|
onRemove={vi.fn()}
|
|
|
|
|
onCategorize={onCategorize}
|
|
|
|
|
/>,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
fireEvent.change(screen.getByLabelText("Category for safety-form.pdf"), {
|
|
|
|
|
target: { value: "Aveta" },
|
|
|
|
|
});
|
|
|
|
|
expect(onCategorize).toHaveBeenCalledWith("m1", "Aveta");
|
|
|
|
|
expect(screen.queryByText("safety-form.pdf")).toBeInTheDocument();
|
|
|
|
|
});
|
2026-09-08 11:28:37 -03:00
|
|
|
|
2026-09-08 11:33:21 -03:00
|
|
|
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 open = vi.fn();
|
|
|
|
|
vi.stubGlobal("open", open);
|
|
|
|
|
|
|
|
|
|
renderWithProviders(
|
|
|
|
|
<SlideOverExtrasTab
|
|
|
|
|
uploads={[{ ...photo, url: "https://cdn.example.com/Assets/Documents/secret.pdf" }]}
|
|
|
|
|
workOrderId={10}
|
|
|
|
|
avetaRequired
|
|
|
|
|
isReadOnly
|
|
|
|
|
onUpload={vi.fn()}
|
|
|
|
|
onRemove={vi.fn()}
|
|
|
|
|
/>,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
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("blob:authorized", "_blank", "noopener,noreferrer");
|
|
|
|
|
});
|
|
|
|
|
|
2026-09-08 11:28:37 -03:00
|
|
|
it("shows Extra Docs accept copy with PDF DOC and 50MB", () => {
|
|
|
|
|
renderWithProviders(
|
|
|
|
|
<SlideOverExtrasTab uploads={[]} isReadOnly={false} onUpload={vi.fn()} onRemove={vi.fn()} />,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
expect(
|
|
|
|
|
screen.getByText("Accepted: JPG, PNG, MP4, MOV, PDF, DOC · Max 50 MB"),
|
|
|
|
|
).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");
|
|
|
|
|
});
|
2026-08-24 15:16:51 -03:00
|
|
|
});
|