import { describe, expect, it, vi } from "vitest"; import { createToolcraftRuntimeSceneVisibility } from "../scene"; import { defineToolcraft } from "../schema/define-toolcraft"; import { createToolcraftState } from "../state/create-template-state"; import type { ToolcraftArtifactDownloadRequest, ToolcraftArtifactDownloadResult, } from "./artifact-download"; import { exportToolcraftSvgArtifact } from "./svg-artifact-export"; import { TOOLCRAFT_SVG_NAMESPACE } from "./svg-policy"; const visibility = createToolcraftRuntimeSceneVisibility({ renderDefaultImages: true, suppressedModelTargets: [], }); function createState() { return createToolcraftState( defineToolcraft({ canvas: { enabled: true }, panels: {} }), ); } describe("exportToolcraftSvgArtifact", () => { it("renders current vectors, downloads SVG, and reports monotonic progress", async () => { const progress: number[] = []; const downloadArtifact = vi.fn( ( _request: ToolcraftArtifactDownloadRequest, ): ToolcraftArtifactDownloadResult => ({ fileName: "column-graph.svg", }), ); const state = createState(); const result = await exportToolcraftSvgArtifact({ boundsProvider: undefined, downloadArtifact, productSceneRequired: true, rendererPipeline: null, reportProgress: (value) => progress.push(value), state, svgExportRenderer: { baseFileName: "column-graph", renderFrame: ({ container, frame, state: frameState }) => { expect(frameState).not.toBe(state); const rect = container.ownerDocument.createElementNS( TOOLCRAFT_SVG_NAMESPACE, "rect", ); rect.setAttribute("width", String(frame.width)); rect.setAttribute("height", String(frame.height)); rect.setAttribute("data-column-graph-background", "true"); container.append(rect); }, }, visibility, }); expect(progress).toEqual([0.1, 0.65, 0.9, 1]); expect(result).toMatchObject({ extension: ".svg", mediaType: "image/svg+xml", vectorElementCount: 1, }); expect(result.byteLength).toBeGreaterThan(0); expect(downloadArtifact).toHaveBeenCalledOnce(); const request = downloadArtifact.mock.calls[0]?.[0]; expect(request?.extension).toBe(".svg"); expect(request?.rawBaseFileName).toBe("column-graph"); expect(request?.blob.type).toBe("image/svg+xml;charset=utf-8"); await expect(request?.blob.text()).resolves.toContain( 'data-column-graph-background="true"', ); }); it("normalizes product renderer failures", async () => { await expect( exportToolcraftSvgArtifact({ boundsProvider: undefined, downloadArtifact: vi.fn(), productSceneRequired: false, rendererPipeline: null, reportProgress: vi.fn(), state: createState(), svgExportRenderer: { baseFileName: "broken", renderFrame: () => { throw new Error("renderer exploded"); }, }, visibility, }), ).rejects.toMatchObject({ feedback: { code: "svg-render-failed" }, }); }); });