import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; import { describe, expect, test } from "vitest"; import { buildEventsFromChanges, listSpecChanges } from "../src/changes.js"; import { JsonCharterDatabase } from "../src/db/json.js"; import { buildImportPlan } from "../src/spec-files.js"; async function makeProject(): Promise { const root = await fs.mkdtemp(path.join(os.tmpdir(), "charter-changes-")); await fs.mkdir(path.join(root, "spec")); return root; } describe("spec changes", () => { test("detects added, modified, and deleted spec documents against materialized state", async () => { const root = await makeProject(); await fs.writeFile(path.join(root, "spec", "a.md"), "---\nid: a\ntitle: A\nkind: note\n---\n\n# A\n", "utf8"); const initialPlan = await buildImportPlan({ projectRoot: root }); const db = new JsonCharterDatabase({ projectRoot: root, projectId: "charter" }); let snapshot = await db.loadSnapshot(); let changes = listSpecChanges(initialPlan, snapshot); expect(changes.map((change) => change.type)).toEqual(["added"]); for (const row of initialPlan.rows) await db.upsertDocument(row); for (const event of buildEventsFromChanges(initialPlan, changes)) await db.appendEvent(event); await db.saveSnapshot(); await fs.writeFile(path.join(root, "spec", "a.md"), "---\nid: a\ntitle: A\nkind: note\n---\n\n# A\n\nChanged.\n", "utf8"); await fs.writeFile(path.join(root, "spec", "b.md"), "---\nid: b\ntitle: B\nkind: note\n---\n\n# B\n", "utf8"); snapshot = await new JsonCharterDatabase({ projectRoot: root, projectId: "charter" }).loadSnapshot(); const changedPlan = await buildImportPlan({ projectRoot: root }); changes = listSpecChanges(changedPlan, snapshot); expect(changes.map((change) => [change.documentId, change.type])).toEqual([ ["b", "added"], ["a", "modified"], ]); await fs.rm(path.join(root, "spec", "a.md")); const deletedPlan = await buildImportPlan({ projectRoot: root }); const deletedChanges = listSpecChanges(deletedPlan, snapshot); expect(deletedChanges.map((change) => [change.documentId, change.type])).toEqual([ ["b", "added"], ["a", "deleted"], ]); }); });