import { describe, expect, it, vi } from "vitest"; import type { ToolcraftControlSchema } from "../schema/types"; import { toolcraftFileSourceAssetHandler } from "./file-source-asset-handler"; import { toolcraftImageSourceAssetHandler } from "./image-source-asset-handler"; import type { ToolcraftSourceAssetPrepareContext } from "./source-asset-types"; function createContext( kind: "file" | "image", file: File, ): ToolcraftSourceAssetPrepareContext { const target = `source.${kind}`; const claim = { handlerKind: kind, rootFileNames: [file.name], specificity: 100, } as const; const control: ToolcraftControlSchema = { assetKind: kind, target, type: "fileDrop", }; return { batch: { files: [file], origin: "panel", target }, canvasFrame: { kind: "finite", size: { height: 200, unit: "px", width: 300 }, }, claim, control, jobId: "binary-media-handler-test", plan: { claim, logicalAssetCount: 1, replaceExisting: true, sourceTarget: target, target, }, reportOperation: vi.fn(), signal: new AbortController().signal, stageResource: vi.fn(async () => undefined), }; } describe("image and file source asset handlers", () => { it.each([ ["image" as const, toolcraftImageSourceAssetHandler, "image/png"], ["file" as const, toolcraftFileSourceAssetHandler, "text/plain"], ])("stages %s bytes before returning a durable record", async ( kind, handler, contentType, ) => { const file = new File([new Uint8Array([1, 2, 3])], `${kind}.bin`, { type: contentType, }); const context = createContext(kind, file); const prepared = await handler.prepare(context); const asset = prepared.assets[0]; expect(asset).toMatchObject({ assetKind: kind, lifecycle: "ready", resourceRef: expect.stringMatching( new RegExp(`^media:${kind}:sha256:[0-9a-f]{64}$`, "u"), ), }); expect(asset).not.toHaveProperty("dataUrl"); expect(context.stageResource).toHaveBeenCalledWith( asset?.resourceRef, new Uint8Array([1, 2, 3]), { contentType, durable: true }, ); expect(prepared.stagedResourceRefs).toEqual([asset?.resourceRef]); }); });