import { test, expect } from "@playwright/test"; import { CanvasRevisionConflict, VideoCanvasSaveQueue } from "@/lib/video-canvas/save-queue"; test("coalesces edits made during a save and uses the returned revision", async () => { let release!: (value: string) => void; const calls: string[][] = []; const queue = new VideoCanvasSaveQueue("initial", "r0", async (value, revision) => { calls.push([value, revision]); return calls.length === 1 ? new Promise(resolve => { release = resolve; }) : "r2"; }, () => {}); queue.update("first"); const pending = queue.flush(); queue.update("second"); queue.update("latest"); expect(queue.flush()).toBe(pending); release("r1"); await pending; expect(calls).toEqual([["first", "r0"], ["latest", "r1"]]); expect(queue.dirty).toBe(false); }); test("failed save retains edits and retries only the latest snapshot", async () => { const calls: string[][] = []; const queue = new VideoCanvasSaveQueue("initial", "r0", async (value, revision) => { calls.push([value, revision]); if (calls.length === 1) throw new Error("offline"); return "r1"; }, () => {}); queue.update("first"); await queue.flush(); expect(queue.dirty).toBe(true); expect(queue.failed).toBe(true); queue.update("latest"); await queue.flush(); expect(calls).toEqual([["first", "r0"], ["latest", "r0"]]); expect(queue.dirty).toBe(false); }); test("revision conflict cannot be retried as an overwrite", async () => { let calls = 0; const queue = new VideoCanvasSaveQueue("initial", "r0", async () => { calls++; throw new CanvasRevisionConflict("changed elsewhere"); }, () => {}); queue.update("first"); await queue.flush(); queue.update("latest"); await queue.flush(); expect(calls).toBe(1); expect(queue.dirty).toBe(true); }); test("unchanged canvas does not write", async () => { let calls = 0; const queue = new VideoCanvasSaveQueue("initial", "r0", async () => { calls++; return "r1"; }, () => {}); queue.update("initial"); await queue.flush(); expect(calls).toBe(0); });