import { readFile } from "node:fs/promises"; import { describe, expect, it } from "vitest"; const createStudioUrl = new URL("../components/create-studio.tsx", import.meta.url); async function pasteFlowSource() { const source = await readFile(createStudioUrl, "utf8"); const start = source.indexOf("function handleImagePaste("); const end = source.indexOf("async function uploadTemplatePreview(", start); expect(start).toBeGreaterThanOrEqual(0); expect(end).toBeGreaterThan(start); return { source, flow: source.slice(start, end) }; } describe("create studio image paste wiring", () => { it("handles paste in both the prompt and workspace, leaving text paste to the browser", async () => { const { source, flow } = await pasteFlowSource(); expect(source).toContain("onPaste={handleImagePaste}"); expect(source).toContain("onPasteImage={handleImagePaste}"); expect(flow.indexOf("if (!files.length && !imageURL) return;")).toBeLessThan(flow.indexOf("event.preventDefault()")); expect(flow).toContain("clipboardImageFiles(event.clipboardData)"); }); it("requires confirmation before downloading an entire URL and keeps canceled links as native text paste", async () => { const { flow } = await pasteFlowSource(); expect(flow).toContain("files.length ? null : clipboardImageURL(event.clipboardData)"); const confirmation = flow.indexOf("if (imageURL && !window.confirm("); expect(confirmation).toBeGreaterThanOrEqual(0); expect(confirmation).toBeLessThan(flow.indexOf("event.preventDefault()")); expect(flow).toContain('fetch("/api/assets/import-image"'); expect(flow).toContain('headers: { "Content-Type": "application/json" }'); expect(flow).toContain("receiveMaterialAssets(() => importImageURL(imageURL), options, 1)"); expect(flow).toContain("receiveMaterialAssets(() => uploadAssetFiles(selectedFiles), options, allFiles.length)"); expect(flow).toContain("new URL(imageURL).hostname"); expect(flow).toContain('asset.kind !== "image"'); expect(flow).toContain('options.importedURL && options.seedreamSourceMode === "single"'); }); it("blocks concurrent uploads and discards a stale result after a mode or target switch", async () => { const { flow } = await pasteFlowSource(); expect(flow).toContain("if (uploadingRef.current || busy)"); expect(flow).toContain("uploadingRef.current = true"); expect(flow).toContain("uploadingRef.current = false"); expect(flow).toContain("options.paste.contextKey !== pasteContextRef.current"); expect(flow.indexOf("options.paste.contextKey !== pasteContextRef.current")) .toBeLessThan(flow.indexOf("setMaterials(next)")); }); it("routes special modes through existing source limits and adds references only for basic image or video", async () => { const { flow } = await pasteFlowSource(); expect(flow).toContain('imageCreationMode === "interactive" ? "append" : "single"'); expect(flow).toContain("isSeedreamLayerInputFile(files[0])"); expect(flow).toContain("if (selectedSeedreamSource && !window.confirm("); expect(flow).toContain("options.maxFiles = 1"); expect(flow).toContain("options.replaceAll = true"); expect(flow).toContain("options.maxFiles = remaining"); expect(flow).toContain("insertReferences: !specializedImageMode"); expect(flow).toContain('const labels = addedMaterials.map((material) => material.label || "");'); expect(flow).toContain("insertClipboardImageReferences(items[pasted.mode], labels, selection)"); }); });