import { describe, expect, test } from "bun:test"; import { adjustHunkLineNumbers, getPatchFromContents } from "../diff"; describe("adjustHunkLineNumbers", () => { test("shifts hunk line numbers by offset", () => { const hunks = [ { oldStart: 1, oldLines: 3, newStart: 1, newLines: 4, lines: [" a", "-b", "+c", "+d", " e"] }, ] as any[]; const result = adjustHunkLineNumbers(hunks, 10); expect(result[0].oldStart).toBe(11); expect(result[0].newStart).toBe(11); }); test("returns original hunks for zero offset", () => { const hunks = [ { oldStart: 5, oldLines: 2, newStart: 5, newLines: 2, lines: [] }, ] as any[]; const result = adjustHunkLineNumbers(hunks, 0); expect(result).toBe(hunks); // same reference }); test("handles negative offset", () => { const hunks = [ { oldStart: 10, oldLines: 2, newStart: 10, newLines: 2, lines: [] }, ] as any[]; const result = adjustHunkLineNumbers(hunks, -5); expect(result[0].oldStart).toBe(5); expect(result[0].newStart).toBe(5); }); test("handles empty hunks array", () => { expect(adjustHunkLineNumbers([], 10)).toEqual([]); }); }); describe("getPatchFromContents", () => { test("returns hunks for different content", () => { const hunks = getPatchFromContents({ filePath: "test.txt", oldContent: "hello\nworld", newContent: "hello\nplanet", }); expect(hunks.length).toBe(1); const allLines = hunks[0].lines; expect(allLines).toContain("-world"); expect(allLines).toContain("+planet"); }); test("returns empty hunks for identical content", () => { const hunks = getPatchFromContents({ filePath: "test.txt", oldContent: "same content", newContent: "same content", }); expect(hunks).toEqual([]); }); test("handles content with ampersands", () => { const hunks = getPatchFromContents({ filePath: "test.txt", oldContent: "a & b", newContent: "a & c", }); expect(hunks.length).toBeGreaterThan(0); // Verify ampersands are unescaped in the output const allLines = hunks.flatMap((h: any) => h.lines); expect(allLines.some((l: string) => l.includes("&"))).toBe(true); }); test("handles empty old content (new file)", () => { const hunks = getPatchFromContents({ filePath: "test.txt", oldContent: "", newContent: "new content", }); expect(hunks.length).toBeGreaterThan(0); const allLines = hunks.flatMap((h: any) => h.lines); expect(allLines.some((l: string) => l.startsWith("+"))).toBe(true); }); test("handles content with dollar signs", () => { const hunks = getPatchFromContents({ filePath: "test.txt", oldContent: "price: $5", newContent: "price: $10", }); expect(hunks.length).toBeGreaterThan(0); const allLines = hunks.flatMap((h: any) => h.lines); expect(allLines.some((l: string) => l.includes("$"))).toBe(true); // Verify dollar signs are unescaped (not the token) expect(allLines.some((l: string) => l.includes("<<:DOLLAR_TOKEN:>>"))).toBe(false); }); test("handles deleting all content", () => { const hunks = getPatchFromContents({ filePath: "test.txt", oldContent: "line1\nline2\nline3", newContent: "", }); expect(hunks.length).toBeGreaterThan(0); const allLines = hunks.flatMap((h: any) => h.lines); expect(allLines.some((l: string) => l.startsWith("-"))).toBe(true); expect(allLines.every((l: string) => l.startsWith("-") || l.startsWith(" ") || l.startsWith("\\"))).toBe(true); }); test("ignoreWhitespace treats indentation changes as identical", () => { const old = "function foo() {\n return 42;\n}\n"; const nw = "function foo() {\n\treturn 42;\n}\n"; const hunks = getPatchFromContents({ filePath: "test.txt", oldContent: old, newContent: nw, ignoreWhitespace: true, }); expect(hunks).toEqual([]); }); });