UNPKG

@nerdo/code-reviewer

Version:

A web-based visual git diff tool for reviewing code changes between commits, branches, and tags

136 lines (135 loc) 7.75 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const vitest_1 = require("vitest"); const GitFileRepository_1 = require("../GitFileRepository"); const simple_git_1 = __importDefault(require("simple-git")); vitest_1.vi.mock('simple-git'); (0, vitest_1.describe)('GitFileRepository', () => { (0, vitest_1.describe)('getFileTree', () => { (0, vitest_1.it)('should build file tree from git ls-tree output', async () => { const { gitFileRepository, mockGit } = makeTestGitFileRepository(); mockGit.raw.mockResolvedValue('src/index.ts\nsrc/utils.ts\nREADME.md\n'); const tree = await gitFileRepository.getFileTree('/repo', 'abc123'); (0, vitest_1.expect)(mockGit.raw).toHaveBeenCalledWith(['ls-tree', '-r', '--name-only', 'abc123']); (0, vitest_1.expect)(tree.type).toBe('directory'); (0, vitest_1.expect)(tree.children).toHaveLength(2); // src directory and README.md const srcDir = tree.children?.find(c => c.name === 'src'); (0, vitest_1.expect)(srcDir?.type).toBe('directory'); (0, vitest_1.expect)(srcDir?.children).toHaveLength(2); }); (0, vitest_1.it)('should handle empty repository', async () => { const { gitFileRepository, mockGit } = makeTestGitFileRepository(); mockGit.raw.mockResolvedValue(''); const tree = await gitFileRepository.getFileTree('/repo', 'abc123'); (0, vitest_1.expect)(tree.children).toHaveLength(0); }); }); (0, vitest_1.describe)('getFileChanges', () => { (0, vitest_1.it)('should map diff summary to file changes', async () => { const { gitFileRepository, mockGit } = makeTestGitFileRepository(); const diffSummary = makeTestDiffSummary(); mockGit.diffSummary.mockResolvedValue(diffSummary); const changes = await gitFileRepository.getFileChanges('/repo', 'abc123', 'def456'); (0, vitest_1.expect)(changes).toHaveLength(4); (0, vitest_1.expect)(changes[0].changeType).toBe('modified'); (0, vitest_1.expect)(changes[1].changeType).toBe('added'); (0, vitest_1.expect)(changes[2].changeType).toBe('deleted'); (0, vitest_1.expect)(changes[3].changeType).toBe('renamed'); (0, vitest_1.expect)(changes[3].previousPath).toBe('old.ts'); }); }); (0, vitest_1.describe)('getFileDiff', () => { (0, vitest_1.it)('should get diff with content for text files', async () => { const { gitFileRepository, mockGit } = makeTestGitFileRepository(); mockGit.show.mockImplementation((args) => { if (args[0] === 'abc123:test.ts') return Promise.resolve('old content'); if (args[0] === 'def456:test.ts') return Promise.resolve('new content'); return Promise.reject(new Error('File not found')); }); mockGit.raw.mockResolvedValue('1\t1\ttest.ts'); const diff = await gitFileRepository.getFileDiff('/repo', 'abc123', 'def456', 'test.ts'); (0, vitest_1.expect)(diff.path).toBe('test.ts'); (0, vitest_1.expect)(diff.oldContent).toBe('old content'); (0, vitest_1.expect)(diff.newContent).toBe('new content'); (0, vitest_1.expect)(diff.isBinary).toBe(false); (0, vitest_1.expect)(diff.hunks).toBeDefined(); }); (0, vitest_1.it)('should handle binary files', async () => { const { gitFileRepository, mockGit } = makeTestGitFileRepository(); mockGit.show.mockImplementation((args) => { if (args[0] === 'abc123:image.png') return Promise.resolve('binary content old'); if (args[0] === 'def456:image.png') return Promise.resolve('binary content new'); return Promise.reject(new Error('File not found')); }); mockGit.raw.mockResolvedValue('-\t-\timage.png'); const diff = await gitFileRepository.getFileDiff('/repo', 'abc123', 'def456', 'image.png'); (0, vitest_1.expect)(diff.isBinary).toBe(true); (0, vitest_1.expect)(diff.hunks).toHaveLength(0); }); (0, vitest_1.it)('should handle deleted files', async () => { const { gitFileRepository, mockGit } = makeTestGitFileRepository(); mockGit.show.mockImplementation((args) => { if (args[0] === 'abc123:deleted.ts') return Promise.resolve('content'); return Promise.reject(new Error('File not found')); }); mockGit.raw.mockResolvedValue('10\t0\tdeleted.ts'); const diff = await gitFileRepository.getFileDiff('/repo', 'abc123', 'def456', 'deleted.ts'); (0, vitest_1.expect)(diff.oldContent).toBe('content'); (0, vitest_1.expect)(diff.newContent).toBe(''); }); (0, vitest_1.it)('should handle unchanged files', async () => { const { gitFileRepository, mockGit } = makeTestGitFileRepository(); const sameContent = 'unchanged content'; mockGit.show.mockResolvedValue(sameContent); mockGit.raw.mockResolvedValue('0\t0\tunchanged.ts'); const diff = await gitFileRepository.getFileDiff('/repo', 'abc123', 'def456', 'unchanged.ts'); (0, vitest_1.expect)(diff.oldContent).toBe(sameContent); (0, vitest_1.expect)(diff.newContent).toBe(sameContent); (0, vitest_1.expect)(diff.hunks).toHaveLength(0); (0, vitest_1.expect)(diff.isBinary).toBe(false); }); }); (0, vitest_1.describe)('getFileContent', () => { (0, vitest_1.it)('should get file content at specific commit', async () => { const { gitFileRepository, mockGit } = makeTestGitFileRepository(); mockGit.show.mockResolvedValue('file content'); const content = await gitFileRepository.getFileContent('/repo', 'abc123', 'test.ts'); (0, vitest_1.expect)(mockGit.show).toHaveBeenCalledWith(['abc123:test.ts']); (0, vitest_1.expect)(content).toBe('file content'); }); (0, vitest_1.it)('should throw error for non-existent file', async () => { const { gitFileRepository, mockGit } = makeTestGitFileRepository(); mockGit.show.mockRejectedValue(new Error('pathspec')); await (0, vitest_1.expect)(gitFileRepository.getFileContent('/repo', 'abc123', 'nonexistent.ts')).rejects.toThrow('File nonexistent.ts not found in commit abc123'); }); }); function makeTestGitFileRepository() { const mockGit = { raw: vitest_1.vi.fn(), diffSummary: vitest_1.vi.fn(), show: vitest_1.vi.fn() }; // eslint-disable-next-line @typescript-eslint/no-explicit-any simple_git_1.default.mockReturnValue(mockGit); const gitFileRepository = new GitFileRepository_1.GitFileRepository(); return { gitFileRepository, mockGit }; } function makeTestDiffSummary() { return { files: [ { file: 'src/index.ts', insertions: 10, deletions: 5, changes: 15 }, { file: 'new.ts', insertions: 20, deletions: 0, changes: 20 }, { file: 'deleted.ts', insertions: 0, deletions: 30, changes: 30 }, { file: 'old.ts => new.ts', insertions: 5, deletions: 3, changes: 8 } ] }; } });