// Edits to a generated manifest, as notes: the diff, and the coalescing. // // Run with: pnpm test:scripts import assert from "node:assert/strict"; import { mkdtemp, rm } from "node:fs/promises"; import { tmpdir } from "node:os"; import path from "node:path"; import test from "node:test"; import { readNotes } from "../annotations/store.mjs"; import { editsBetween, editText, recordEdits } from "./edit-notes.mjs"; const m = () => ({ generatedBy: "polemics/video/make-videos.py", render: { fps: 30, chrome: { engine: "hyperframes" } }, timeline: [ { type: "clip", id: "a", start: 1, end: 5, quote: "q" }, { type: "clip", id: "b", start: 10, end: 15 }, { type: "card", id: "k" }, ], posts: [{ id: "p1", text: "t", attachTo: "a" }], ledger: [{ id: "c1", scope: "x" }], }); test("editsBetween names each change by entry and field", () => { const before = m(); const after = m(); after.timeline[0].quote = "new"; after.timeline[0].start = 2; after.timeline = [after.timeline[1], after.timeline[0], { type: "card", id: "k2" }]; after.posts[0].attachTo = "b"; after.ledger[0].scope = "y"; after.render.chrome.layout = "deck"; const e = editsBetween(before, after); const keyOf = (x) => `${x.entry ?? ""}|${x.field}`; assert.deepEqual( e.map(keyOf).sort(), ["a|quote", "a|start", "c1|ledger.scope", "k2|timeline+", "k|timeline-", "p1|posts.attachTo", "|render.chrome", "|timeline.order"].sort(), ); const quote = e.find((x) => x.field === "quote"); assert.deepEqual([quote.from, quote.to], ["q", "new"]); assert.deepEqual(editsBetween(before, m()), []); assert.match(editText({ entry: "a", field: "quote" }, "gen.py"), /^a quote changed in umtool\. Port it into the inputs of gen\.py/); }); test("recordEdits adds, coalesces, and deletes a note an edit put back", async () => { const dir = await mkdtemp(path.join(tmpdir(), "umtool-editnotes-")); const target = { file: path.join(dir, "notes.json"), subject: { kind: "video-project", project: "x/y" }, source: async () => ({ manifest: "~/x/y/video.manifest.json" }), }; try { let c = await recordEdits(target, [{ entry: "a", field: "start", from: 1, to: 2 }], "gen.py"); assert.deepEqual([c.added, c.updated, c.deleted], [1, 0, 0]); c = await recordEdits(target, [{ entry: "a", field: "start", from: 2, to: 3 }], "gen.py"); assert.deepEqual([c.added, c.updated], [0, 1]); let doc = (await readNotes(target.file)).doc; assert.equal(doc.notes.length, 1); assert.deepEqual([doc.notes[0].anchor.from, doc.notes[0].anchor.to], [1, 3]); assert.equal(doc.source.manifest, "~/x/y/video.manifest.json"); c = await recordEdits(target, [{ entry: "a", field: "start", from: 3, to: 1 }], "gen.py"); assert.equal(c.deleted, 1); assert.equal((await readNotes(target.file)).doc, null); } finally { await rm(dir, { recursive: true }); } });