import { afterEach, describe, expect, it, vi } from "vitest"; import { downloadSeedreamLayerComposition } from "@/lib/client/seedream-layer-compose"; describe("Seedream layer composition download", () => { afterEach(() => { vi.unstubAllGlobals(); vi.restoreAllMocks(); }); it("streams private assets through the same-origin download route instead of following the signed preview redirect", async () => { const fetchMock = vi.fn(async (input: RequestInfo | URL) => { const url = String(input); if (url.includes("inline=1")) throw new TypeError("Failed to fetch"); return new Response(new Blob(["image"]), { status: 200 }); }); const close = vi.fn(); const drawImage = vi.fn(); const save = vi.fn(); const translate = vi.fn(); const rotate = vi.fn(); const restore = vi.fn(); const click = vi.fn(); const anchor = { href: "", download: "", click, remove: vi.fn() }; const canvas = { width: 0, height: 0, getContext: () => ({ clearRect: vi.fn(), drawImage, save, translate, rotate, restore }), toBlob: (callback: BlobCallback) => callback(new Blob(["png"], { type: "image/png" })) }; vi.stubGlobal("fetch", fetchMock); vi.stubGlobal("createImageBitmap", vi.fn(async () => ({ width: 100, height: 100, close }))); vi.stubGlobal("document", { createElement: (tag: string) => tag === "canvas" ? canvas : anchor, body: { appendChild: vi.fn() } }); vi.stubGlobal("window", { setTimeout: (callback: () => void) => { callback(); return 1; } }); vi.stubGlobal("URL", { createObjectURL: () => "blob:composition", revokeObjectURL: vi.fn() }); await expect(downloadSeedreamLayerComposition({ items: [{ url: "/api/assets/private-layer/download?inline=1", visible: true, box: [0, 0, 1000, 1000], rotation: 90 }], width: 100, height: 100, fileName: "composition.png" })).resolves.toBeUndefined(); expect(fetchMock).toHaveBeenCalledWith("/api/assets/private-layer/download", { credentials: "same-origin" }); expect(drawImage).toHaveBeenCalledOnce(); expect(save).toHaveBeenCalledOnce(); expect(translate).toHaveBeenCalledWith(50, 50); expect(rotate).toHaveBeenCalledWith(Math.PI / 2); expect(restore).toHaveBeenCalledOnce(); expect(click).toHaveBeenCalledOnce(); expect(close).toHaveBeenCalledOnce(); }); });