import { assertEquals } from "@std/assert"; import { pairs, pieces, trailing, wordChanges } from "./model.ts"; import type { FileDiff } from "./types.ts"; const file = (hunks: FileDiff["hunks"]): FileDiff => ({ path: "f.ts", from: null, status: "modified", modes: { old: null, new: null }, binary: false, hunks, }); const shape = (file: FileDiff, context?: number) => pieces(file, context).map((piece) => piece.kind === "gap" ? `gap ${piece.count}` : `${piece.kind} ${ piece.lines.map((l) => `${l.mark}${l.old ?? "_"}/${l.new ?? "_"}`).join(" ") }` ); Deno.test("a whole file folds its long unchanged stretches, keeping context beside each change", () => { const lines = Array.from({ length: 20 }, (_, i) => ` ${i + 1}`); lines.splice(9, 1, "-10", "+ten"); assertEquals(shape(file([{ old: 1, new: 1, lines }]), 2), [ "fold 1/1 2/2 3/3 4/4 5/5 6/6 7/7", "lines 8/8 9/9 -10/_ +_/10 11/11 12/12", "fold 13/13 14/14 15/15 16/16 17/17 18/18 19/19 20/20", ]); }); Deno.test("short unchanged stretches stay open, and lines a patch leaves out are counted", () => { const near = file([ { old: 3, new: 3, lines: [" 3", "-4", "+four", " 5", " 6", " 7", " 8", " 9", "+new", " 10"] }, { old: 20, new: 21, lines: [" 20", "-21", "\\ No newline at end of file"] }, ]); assertEquals(shape(near, 3), [ "gap 2", "lines 3/3 -4/_ +_/4 5/5 6/6 7/7 8/8 9/9 +_/10 10/11", "gap 9", "lines 20/21 -21/_", ]); const last = pieces(near).at(-1)!; assertEquals(last.kind === "lines" && last.lines.at(-1)!.newline, false); }); Deno.test("side by side, removals sit beside the additions that replace them", () => { const [piece] = pieces(file([{ old: 1, new: 1, lines: [" a", "-b", "-c", "+B", " d", "+e"] }])); const rows = pairs(piece.kind === "lines" ? piece.lines : []).map(({ old, new: neu }) => `${old?.text ?? "·"}|${neu?.text ?? "·"}` ); assertEquals(rows, ["a|a", "b|B", "c|·", "d|d", "·|e"]); }); Deno.test("within a changed line, only the words that changed are marked", () => { assertEquals(wordChanges("const total = a + b;", "const sum = a + b;"), { old: [[6, 11]], new: [[6, 9]], }); assertEquals(wordChanges("f(x)", "f(x, y)"), { old: [], new: [[3, 6]] }); // lines with little in common are just different lines assertEquals(wordChanges("import { a } from 'b';", "return value * 2;"), null); assertEquals(trailing("let x = 1; \r"), [10, 12]); assertEquals(trailing("let x = 1;"), null); });