69 lines · 2.7 KB
1 import { describe, it, expect } from 'vitest';
2 import { computeDiff } from '../diff.js';
3
4 describe('computeDiff', () => {
5 it('should return empty hunks for identical text', () => {
6 const hunks = computeDiff('hello\nworld', 'hello\nworld');
7 expect(hunks).toHaveLength(0);
8 });
9
10 it('should detect a single added line', () => {
11 const hunks = computeDiff('hello', 'hello\nworld');
12 expect(hunks).toHaveLength(1);
13 const addLines = hunks[0].lines.filter((l) => l.type === 'add');
14 expect(addLines.length).toBeGreaterThanOrEqual(1);
15 expect(addLines.some((l) => l.content === 'world')).toBe(true);
16 });
17
18 it('should detect a single deleted line', () => {
19 const hunks = computeDiff('hello\nworld', 'hello');
20 expect(hunks).toHaveLength(1);
21 const delLines = hunks[0].lines.filter((l) => l.type === 'delete');
22 expect(delLines.length).toBeGreaterThanOrEqual(1);
23 expect(delLines.some((l) => l.content === 'world')).toBe(true);
24 });
25
26 it('should detect modifications', () => {
27 const hunks = computeDiff('line1\nold\nline3', 'line1\nnew\nline3');
28 expect(hunks).toHaveLength(1);
29 const delLines = hunks[0].lines.filter((l) => l.type === 'delete');
30 const addLines = hunks[0].lines.filter((l) => l.type === 'add');
31 expect(delLines.length).toBeGreaterThanOrEqual(1);
32 expect(addLines.length).toBeGreaterThanOrEqual(1);
33 expect(delLines.some((l) => l.content === 'old')).toBe(true);
34 expect(addLines.some((l) => l.content === 'new')).toBe(true);
35 });
36
37 it('should handle adding to empty file', () => {
38 const hunks = computeDiff('', 'hello\nworld');
39 expect(hunks.length).toBeGreaterThanOrEqual(1);
40 const addLines = hunks.flatMap((h) => h.lines).filter((l) => l.type === 'add');
41 expect(addLines.length).toBeGreaterThanOrEqual(1);
42 });
43
44 it('should handle deleting entire file', () => {
45 const hunks = computeDiff('hello\nworld', '');
46 expect(hunks.length).toBeGreaterThanOrEqual(1);
47 const delLines = hunks.flatMap((h) => h.lines).filter((l) => l.type === 'delete');
48 expect(delLines.length).toBeGreaterThanOrEqual(1);
49 });
50
51 it('should include context lines', () => {
52 const old = 'a\nb\nc\nd\ne\nf\ng';
53 const new_ = 'a\nb\nc\nX\ne\nf\ng';
54 const hunks = computeDiff(old, new_, 2);
55 expect(hunks).toHaveLength(1);
56 const contextLines = hunks[0].lines.filter((l) => l.type === 'context');
57 expect(contextLines.length).toBeGreaterThan(0);
58 });
59
60 it('should produce valid hunks with line numbers', () => {
61 const hunks = computeDiff('a\nb\nc', 'a\nX\nc');
62 expect(hunks).toHaveLength(1);
63 // All lines should have at least one line number
64 for (const line of hunks[0].lines) {
65 expect(line.oldLineNo !== null || line.newLineNo !== null).toBe(true);
66 }
67 });
68 });
69