// @vitest-environment happy-dom import { act, createElement } from "react"; import { createRoot, type Root } from "react-dom/client"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; const mocks = vi.hoisted(() => ({ error: vi.fn(), success: vi.fn() })); vi.mock("sonner", () => ({ toast: mocks })); import { MediaUploader } from "./media-uploader"; let container: HTMLDivElement; let root: Root; const fetchUpload = vi.fn(); const onReady = vi.fn(); const onUploadingChange = vi.fn(); beforeEach(async () => { vi.clearAllMocks(); vi.stubGlobal("IS_REACT_ACT_ENVIRONMENT", true); vi.stubGlobal("fetch", fetchUpload); container = document.createElement("div"); document.body.append(container); root = createRoot(container); await act(async () => root.render(createElement(MediaUploader, { onReady, onUploadingChange }))); }); afterEach(async () => { await act(async () => root.unmount()); container.remove(); vi.unstubAllGlobals(); }); async function selectImage() { const input = container.querySelector("input")!; Object.defineProperty(input, "files", { configurable: true, value: [new File(["image"], "test.png", { type: "image/png" })] }); await act(async () => input.dispatchEvent(new Event("change", { bubbles: true }))); } describe("media upload responses", () => { it("reports HTTP 503 when the network replaces the API error with HTML", async () => { fetchUpload.mockResolvedValueOnce(new Response("503 Service Unavailable", { status: 503, headers: { "Content-Type": "text/html" }, })); await selectImage(); expect(mocks.error).toHaveBeenCalledWith(expect.stringContaining("HTTP 503")); expect(onReady).not.toHaveBeenCalled(); expect(onUploadingChange.mock.calls).toEqual([[true], [false]]); expect(container.querySelector("input")?.disabled).toBe(false); }); it("preserves JSON API error details", async () => { fetchUpload.mockResolvedValueOnce(Response.json({ error: "uploads-busy" }, { status: 429 })); await selectImage(); expect(mocks.error).toHaveBeenCalledWith("uploads-busy"); expect(onReady).not.toHaveBeenCalled(); expect(container.querySelector("input")?.disabled).toBe(false); }); it("passes a successful upload to the editor", async () => { const media = { id: "media", url: "https://cdn.test/image.png", fileName: "test.png", width: 1, height: 1 }; fetchUpload.mockResolvedValueOnce(Response.json(media, { status: 201 })); await selectImage(); expect(fetchUpload).toHaveBeenCalledWith("/api/admin/media", expect.objectContaining({ method: "POST", body: expect.any(FormData) })); expect(onReady).toHaveBeenCalledExactlyOnceWith(media); expect(mocks.success).toHaveBeenCalledTimes(1); expect(onUploadingChange.mock.calls).toEqual([[true], [false]]); }); });