diff --git a/web/test/canvas-asset-repair.test.ts b/web/test/canvas-asset-repair.test.ts index 57f905fc9..1d517bb41 100644 --- a/web/test/canvas-asset-repair.test.ts +++ b/web/test/canvas-asset-repair.test.ts @@ -1,6 +1,7 @@ import { beforeEach, describe, expect, test } from "bun:test"; -import { collectCanvasMediaAssetIds, rebindInconsistentCanvasAssets, repairMissingCanvasAssets } from "@/services/canvas-asset-repair"; +import { collectCanvasMediaAssetIds, rebindInconsistentCanvasAssets, repairMissingCanvasAssets, repairMissingCanvasVideoPreviews } from "@/services/canvas-asset-repair"; +import { ApiError } from "@/services/api/request"; import { useAssetStore, type Asset } from "@/stores/use-asset-store"; import { useCanvasStore, type CanvasProject } from "@/stores/canvas/use-canvas-store"; import { CanvasNodeType, type CanvasNodeData } from "@/types/canvas"; @@ -137,3 +138,29 @@ describe("collectCanvasMediaAssetIds", () => { expect(collectCanvasMediaAssetIds(projects)).toEqual(new Set(["asset-a", "asset-b"])); }); }); + +describe("repairMissingCanvasVideoPreviews", () => { + test("only clears confirmed missing preview resources, not network failures", async () => { + const node = { ...videoNode("node-1", "asset-1", "resource:video-1"), metadata: { ...videoNode("node-1", "asset-1", "resource:video-1").metadata, videoPreview: { storageKey: "resource:poster-1" } } }; + useCanvasStore.setState({ projects: [project("canvas-1", [node])] }); + + await expect(repairMissingCanvasVideoPreviews(undefined, async () => { throw new Error("offline"); })).rejects.toThrow("offline"); + expect(useCanvasStore.getState().projects[0].nodes[0].metadata?.videoPreview).toBeDefined(); + + const result = await repairMissingCanvasVideoPreviews(undefined, async () => { throw new ApiError("missing", { status: 404 }); }); + expect(result).toEqual({ clearedPreviews: 1, updatedProjects: 1 }); + expect(useCanvasStore.getState().projects[0].nodes[0].metadata?.videoPreview).toBeUndefined(); + }); + + test("preserves edits made while resource lookup is pending", async () => { + const node = { ...videoNode("node-1", "asset-1", "resource:video-1"), metadata: { ...videoNode("node-1", "asset-1", "resource:video-1").metadata, videoPreview: { storageKey: "resource:poster-1" } } }; + useCanvasStore.setState({ projects: [project("canvas-1", [node])] }); + let rejectLookup!: (error: unknown) => void; + const repair = repairMissingCanvasVideoPreviews(undefined, () => new Promise((_, reject) => { rejectLookup = reject; })); + useCanvasStore.getState().updateProject("canvas-1", { title: "user edit" }); + rejectLookup(new ApiError("missing", { status: 404 })); + await repair; + expect(useCanvasStore.getState().projects[0].title).toBe("user edit"); + expect(useCanvasStore.getState().projects[0].nodes[0].metadata?.videoPreview).toBeUndefined(); + }); +});