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 |