import { describe, expect, it, vi } from "vitest"; import { createToolcraftSourceAssetPresentationResources } from "./source-asset-presentation-resources"; describe("source asset presentation resources", () => { it("reuses one object URL per active resource and revokes it on release", async () => { const releaseResourceRef = vi.fn(); const retainResourceRef = vi.fn(() => releaseResourceRef); const revokeObjectUrl = vi.fn(); const resources = createToolcraftSourceAssetPresentationResources({ createObjectUrl: vi.fn(() => "blob:media-image-a"), resolveResource: vi.fn(async () => new Uint8Array([1, 2, 3])), retainResourceRef, revokeObjectUrl, }); const first = await resources.retain("media:image:a", "image/png"); const second = await resources.retain("media:image:a", "image/png"); expect(first.url).toBe(second.url); expect(retainResourceRef).toHaveBeenCalledTimes(1); first.release(); expect(revokeObjectUrl).not.toHaveBeenCalled(); second.release(); expect(revokeObjectUrl).toHaveBeenCalledWith(first.url); expect(releaseResourceRef).toHaveBeenCalledTimes(1); }); it("releases reachability when resource resolution fails", async () => { const releaseResourceRef = vi.fn(); const resources = createToolcraftSourceAssetPresentationResources({ createObjectUrl: vi.fn(() => "blob:unused"), resolveResource: vi.fn(async () => null), retainResourceRef: () => releaseResourceRef, revokeObjectUrl: vi.fn(), }); await expect( resources.retain("media:file:missing", "application/octet-stream"), ).rejects.toThrow(/unavailable/u); expect(releaseResourceRef).toHaveBeenCalledTimes(1); }); });