import { describe, test, expect } from "vitest"; import { decorationPlan } from "../src/trackChangesModel"; describe("decorationPlan (INV-49)", () => { test("derives insertion ranges + deletion hints from original→replacement", () => { // anchorStart 10; original 'the brown fox' → 'the red fox' const plan = decorationPlan(10, "the brown fox", "the red fox"); // one changed run: 'brown ' → 'red ' (word-level); insertion 'red ' tinted, // deletion hint 'brown ' shown at the run start. expect(plan.insertions.length).toBeGreaterThan(0); expect(plan.deletions.length).toBeGreaterThan(0); // insertion offsets are in buffer coords (>= anchorStart) and lie within the applied text for (const ins of plan.insertions) { expect(ins.start).toBeGreaterThanOrEqual(10); expect(ins.end).toBeLessThanOrEqual(10 + "the red fox".length); } // a deletion hint carries the struck original text at a buffer offset expect(plan.deletions[0].text).toContain("brown"); }); test("pure insertion (no deletion) yields an insertion range and no deletion hint", () => { // 'hello' → 'hello world': ' world' is a pure word-level insertion (no removed tokens) const plan = decorationPlan(0, "hello", "hello world"); expect(plan.insertions.length).toBe(1); expect(plan.deletions.length).toBe(0); }); });