import { describe, it } from 'node:test'; import assert from 'node:assert/strict'; import { countChanges, wordDiff, WORD_DIFF_LIMIT } from './wordDiff'; const render = (tokens: ReturnType) => tokens ?.map((t) => t.op === 'same' ? t.text : `${t.op === 'add' ? '+' : '-'}[${t.text.trim()}]${t.text.endsWith(' ') ? ' ' : ''}`, ) .join(''); describe('wordDiff', () => { it('returns undefined for identical text', () => { assert.equal(wordDiff('hello world', 'hello world'), undefined); }); it('marks a replaced word', () => { assert.equal(render(wordDiff('see you at 5', 'see you at 6')), 'see you at -[5]+[6]'); }); it('marks insertions and deletions in place', () => { assert.equal( render(wordDiff('the quick fox', 'the quick brown fox jumps')), 'the quick +[brown] fox +[jumps]', ); assert.equal(render(wordDiff('a b c d', 'a d')), 'a -[b c] d'); }); it('ignores whitespace-only changes', () => { assert.equal(wordDiff('a b', 'a b'), undefined); assert.equal(wordDiff('a b\n', 'a b'), undefined); }); it('handles fully different text', () => { assert.deepEqual(wordDiff('one', 'two'), [ { op: 'del', text: 'one' }, { op: 'add', text: 'two' }, ]); }); it('gives up past the word limit', () => { const long = Array.from({ length: WORD_DIFF_LIMIT }, (_, i) => `w${i}`).join(' '); assert.equal(wordDiff(long, `${long} extra`), undefined); }); it('counts changed words', () => { const d = wordDiff('a b c', 'a x y z c'); assert.ok(d); assert.deepEqual(countChanges(d), { added: 3, removed: 1 }); }); });