import { describe, expect, it, vi } from "vitest"; import { createValidModelDocument } from "../../model-import/canonical/model-document-test-support"; import { createToolcraftModelPresentation, type ToolcraftModelRenderBinding, } from "./model-render-binding"; import { createToolcraftLazyThreeModelRenderBinding } from "./lazy-three-model-render-binding"; describe("lazy Three model render binding", () => { it("loads once on first resource creation and delegates the complete binding", async () => { const resource = { id: "resource" }; const inner: ToolcraftModelRenderBinding = { create: vi.fn(() => resource), dispose: vi.fn(), hitTest: vi.fn(() => true), renderExport: vi.fn(), renderPreview: vi.fn(), update: vi.fn(), }; const load = vi.fn(async () => inner as ToolcraftModelRenderBinding); const binding = createToolcraftLazyThreeModelRenderBinding(load); const canonicalDocument = createValidModelDocument(); const presentation = createToolcraftModelPresentation( { activeDocumentRef: "document-1", id: "model-1", layerId: "layer-1", lifecycle: "clean", }, { bounds: canonicalDocument.bounds, phase: "clean", purpose: "preview", target: "source.model", viewport: { height: 100, width: 100 }, }, ); const context = { acquirePresentation: vi.fn(), signal: new AbortController().signal, }; const first = await binding.create(presentation, context); const second = await binding.create(presentation, context); binding.renderPreview(first, { height: 100, host: document.createElement("div"), pixelRatio: 1, selected: false, width: 100, }); expect(binding.hitTest(first, { clientX: 1, clientY: 2 })).toBe(true); binding.dispose(first); expect(load).toHaveBeenCalledTimes(1); expect(inner.create).toHaveBeenCalledTimes(2); expect(inner.renderPreview).toHaveBeenCalledTimes(1); expect(inner.hitTest).toHaveBeenCalledTimes(1); expect(inner.dispose).toHaveBeenCalledWith(resource); binding.dispose(second); }); it("loads and delegates preview preparation before the first resource", async () => { const inner = { create: vi.fn(), dispose: vi.fn(), disposePreparedPreview: vi.fn(), hitTest: vi.fn(), preparePreview: vi.fn(), renderExport: vi.fn(), renderPreview: vi.fn(), update: vi.fn(), } satisfies ToolcraftModelRenderBinding; const load = vi.fn(async () => inner as ToolcraftModelRenderBinding); const binding = createToolcraftLazyThreeModelRenderBinding(load); await binding.preparePreview?.({ height: 720, host: document.createElement("div"), pixelRatio: 1, target: "source.model", width: 1280, }); binding.disposePreparedPreview?.(); await Promise.resolve(); expect(load).toHaveBeenCalledTimes(1); expect(inner.preparePreview).toHaveBeenCalledTimes(1); expect(inner.disposePreparedPreview).toHaveBeenCalledTimes(1); }); });