import { describe, expect, it, vi } from "vitest"; import type { ToolcraftCommand } from "../state/types"; import { createFileHandler, createLease, createRepository, createStateHarness, fileControl, fileDraft, prepared, testFile, } from "./source-asset-coordinator-test-support"; import { createToolcraftSourceAssetCoordinator } from "../composition/source-asset-coordinator"; import { createToolcraftSourceAssetRegistry } from "./source-asset-registry"; describe("source asset coordinator compensation", () => { it("compensates a post-commit dispatch failure with complete reachability collection", async () => { const harness = createStateHarness(); const state = harness.getState(); const analysis = { boundaryEdges: 0, diagnostics: [], disconnectedComponents: 1, nonManifoldEdges: 0, outcome: "clean" as const, triangles: 1, vertices: 3, }; harness.setState({ ...state, mediaAssets: [ { activeDocumentRef: "document:active", analysis, assetKind: "model", fileName: "kept.glb", id: "model-1", layerId: "layer-1", lifecycle: "clean", mimeType: "model/gltf-binary", originalAnalysis: analysis, originalDocumentRef: "document:original", position: { x: 0, y: 0 }, size: { height: 512, unit: "px", width: 512 }, sourceBundleDigest: "digest", sourceBundleRef: "source:kept", topologyProfile: "realtime-mesh", }, ], }); const dispatch = vi.fn((_command: ToolcraftCommand) => { throw new Error("dispatch failed"); }); const lease = createLease(); const repository = createRepository([lease]); const handler = createFileHandler(async () => prepared(fileDraft("failed.txt")), ); const coordinator = createToolcraftSourceAssetCoordinator({ dispatch, getState: harness.getState, registry: createToolcraftSourceAssetRegistry([handler]), repository, }); await expect( coordinator.importBatch( { files: [testFile("failed.txt")], origin: "panel", target: "source.files", }, fileControl(), ), ).resolves.toMatchObject({ kind: "rejected" }); expect(lease.commit).toHaveBeenCalledTimes(1); expect(lease.rollback).not.toHaveBeenCalled(); expect(repository.collect).toHaveBeenCalledTimes(1); const reachableRefs = repository.collect.mock .calls[0]?.[0] as ReadonlySet; expect([...reachableRefs]).toEqual( expect.arrayContaining([ "document:active", "document:original", "source:kept", ]), ); }); });