import { vi } from "vitest"; import { encodeToolcraftModelDocument } from "../../model-import/canonical/model-document-codec"; import { createValidModelDocument } from "../../model-import/canonical/model-document-test-support"; import type { ToolcraftModelPresentationLease, ToolcraftModelRenderBinding, } from "./model-render-binding"; export function deferred() { let resolve!: (value: Value | PromiseLike) => void; let reject!: (reason: unknown) => void; const promise = new Promise((yes, no) => { resolve = yes; reject = no; }); return { promise, reject, resolve }; } export const exportRequest = { asset: { activeDocumentRef: "document:a", id: "model-1", layerId: "layer-1", lifecycle: "clean" as const, sourceTarget: "source.model", }, phase: "clean" as const, target: "source.model", }; export function exportContext(signal = new AbortController().signal) { return { height: 200, pixelRatio: 1, signal, width: 300 }; } export function createLifetimeFixture(phase: "create" | "render" = "render") { const entered = deferred(); const pending = deferred(); const events: string[] = []; const leases: ToolcraftModelPresentationLease[] = []; const signals: AbortSignal[] = []; const bytes = encodeToolcraftModelDocument(createValidModelDocument()); const resolveResource = vi.fn(async () => bytes); const binding: ToolcraftModelRenderBinding = { create: vi.fn(async (presentation, context) => { signals.push(context.signal); const lease = await context.acquirePresentation( presentation.canonicalDocumentRef, { purpose: presentation.purpose, signal: context.signal }, ); leases.push(lease); if (phase === "create") { entered.resolve(); await pending.promise; } return lease; }), dispose: vi.fn((lease) => { events.push("resource"); lease.release(); }), disposePreparedPreview: vi.fn(() => { events.push("prepared"); }), hitTest: vi.fn(() => false), renderExport: vi.fn(async (_resource, context) => { signals.push(context.signal); if (phase === "render") { entered.resolve(); await pending.promise; } await context.onRendered?.(document.createElement("canvas")); }), renderPreview: vi.fn(), update: vi.fn(), }; return { binding, entered, events, leases, pending, resolveResource, signals }; }