import { describe, expect, it } from "vitest"; import { capturePromptAttachments, DEFAULT_FILE_MIME_TYPE, effectivePromptAttachmentDelivery, READ_FAILURE_MESSAGE, type CapturableFile } from "./promptAttachmentCapture"; function file(name: string, type: string, size = 10): CapturableFile { return { name, type, size }; } describe("capturePromptAttachments", () => { it("reads supported images as native inline image attachments", async () => { const result = await capturePromptAttachments( [file("shot.png", "image/png"), file("pic.webp", "image/webp")], (f) => Promise.resolve(`data-for-${f.name}`), ); expect(result.error).toBeUndefined(); expect(result.attachments).toEqual([ { kind: "image", name: "shot.png", mimeType: "image/png", data: "data-for-shot.png", size: 10 }, { kind: "image", name: "pic.webp", mimeType: "image/webp", data: "data-for-pic.webp", size: 10 }, ]); }); it("captures generic files with their browser MIME type", async () => { const result = await capturePromptAttachments( [file("report.pdf", "application/pdf", 1234), file("vector.svg", "image/svg+xml")], (f) => Promise.resolve(`data-for-${f.name}`), ); expect(result.error).toBeUndefined(); expect(result.attachments).toEqual([ { kind: "file", name: "report.pdf", mimeType: "application/pdf", data: "data-for-report.pdf", size: 1234 }, { kind: "file", name: "vector.svg", mimeType: "image/svg+xml", data: "data-for-vector.svg", size: 10 }, ]); }); it("uses application/octet-stream when the browser does not provide a MIME type", async () => { const result = await capturePromptAttachments([file("archive", "")], () => Promise.resolve("x")); expect(result.attachments[0]).toMatchObject({ kind: "file", name: "archive", mimeType: DEFAULT_FILE_MIME_TYPE }); }); it("derives fallback names for unnamed pasted attachments", async () => { const result = await capturePromptAttachments( [file("", "image/jpeg"), file("", "application/pdf")], () => Promise.resolve("x"), ); expect(result.attachments.map((attachment) => attachment.name)).toEqual(["pasted-image.jpg", "pasted-file.bin"]); }); it("reports a read failure without dropping other attachments", async () => { const result = await capturePromptAttachments( [file("bad.png", "image/png"), file("good.txt", "text/plain")], (f) => f.name === "bad.png" ? Promise.reject(new Error("boom")) : Promise.resolve("ok"), ); expect(result.error).toBe(READ_FAILURE_MESSAGE); expect(result.attachments.map((attachment) => attachment.name)).toEqual(["good.txt"]); }); it("returns no attachments and no error for an empty batch", async () => { const result = await capturePromptAttachments([], () => Promise.resolve("x")); expect(result).toEqual({ attachments: [] }); }); }); describe("effectivePromptAttachmentDelivery", () => { it("preserves inline delivery when all pending attachments are supported images", () => { expect(effectivePromptAttachmentDelivery("inline", [{ kind: "image", mimeType: "image/png" }])).toBe("inline"); }); it("preserves an explicit folder preference for supported images", () => { expect(effectivePromptAttachmentDelivery("folder", [{ kind: "image", mimeType: "image/png" }])).toBe("folder"); }); it("forces folder delivery when any attachment is a generic file", () => { expect(effectivePromptAttachmentDelivery("inline", [ { kind: "image", mimeType: "image/png" }, { kind: "file", mimeType: "application/pdf" }, ])).toBe("folder"); }); });