import { describe, expect, test, tier } from 'claude-code/testing' import Parse from '../../../hooks/git/parse' import Limits from '../../../hooks/limits' tier('builtin') describe('parse-numstat', () => { test('NUL records: totals, binaries at 0/0, tabs in a path kept', () => { const parsed = Parse.parseNumstat( '3\t1\tsrc/a.ts\0-\t-\timg.png\x002\t0\ta\tb.ts\0', Limits.MAX_FILES, ) expect(parsed.stats).toEqual({ filesCount: 3, linesAdded: 5, linesRemoved: 1, }) expect(parsed.files.map(file => [file.path, file.isBinary])).toEqual([ ['src/a.ts', false], ['img.png', true], ['a\tb.ts', false], ]) expect( parsed.files.every(file => !file.isUntracked && !file.isPreSession), ).toBe(true) }) test('the cap keeps the first rows but counts every row', () => { const parsed = Parse.parseNumstat('1\t0\ta\x001\t0\tb\x001\t0\tc\0', 2) expect(parsed.files.map(file => file.path)).toEqual(['a', 'b']) expect(parsed.stats.filesCount).toBe(3) }) test('a line with fewer than three fields is no row', () => { expect( Parse.parseNumstat('\0warning: x\0', Limits.MAX_FILES).stats.filesCount, ).toBe(0) }) test('a non-ASCII path arrives as its own characters', () => { expect( Parse.parseNumstat('1\t1\tdocs/caf\u00e9.md\0', Limits.MAX_FILES).files[0] ?.path, ).toBe('docs/caf\u00e9.md') }) test('a rename record keeps the new path and remembers the old', () => { const parsed = Parse.parseNumstat( '2\t1\t\0src/old.ts\0src/new.ts\x003\t0\tkept.ts\0', Limits.MAX_FILES, ) expect( parsed.files.map(file => [file.path, file.renamedFrom, file.added]), ).toEqual([ ['src/new.ts', 'src/old.ts', 2], ['kept.ts', null, 3], ]) expect(parsed.stats.filesCount).toBe(2) }) })