GitNexus/gitnexus/test/integration/filesystem-walker.test.ts
abhigyanpatwari 8a100a76d3 test: add test suite with vitest (unit + integration + fixtures)
- 59 test files covering unit and integration tests
- vitest config with coverage thresholds and fork pooling
- Test fixtures (mini-repo + multi-language sample code)
- Add vitest + coverage-v8 to devDependencies
- Add test scripts (test, test:integration, test:all, test:watch, test:coverage)
- Move typescript to devDependencies where it belongs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 20:07:02 +05:30

92 lines
3.7 KiB
TypeScript

import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import fs from 'fs/promises';
import path from 'path';
import os from 'os';
import { walkRepositoryPaths, readFileContents } from '../../src/core/ingestion/filesystem-walker.js';
describe('filesystem-walker', () => {
let tmpDir: string;
beforeAll(async () => {
tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'gn-walker-test-'));
// Create test directory structure
await fs.mkdir(path.join(tmpDir, 'src'), { recursive: true });
await fs.mkdir(path.join(tmpDir, 'src', 'components'), { recursive: true });
await fs.mkdir(path.join(tmpDir, 'node_modules', 'lodash'), { recursive: true });
await fs.mkdir(path.join(tmpDir, '.git'), { recursive: true });
await fs.writeFile(path.join(tmpDir, 'src', 'index.ts'), 'export const main = () => {}');
await fs.writeFile(path.join(tmpDir, 'src', 'utils.ts'), 'export const helper = () => {}');
await fs.writeFile(path.join(tmpDir, 'src', 'components', 'Button.tsx'), 'export const Button = () => <div/>');
await fs.writeFile(path.join(tmpDir, 'node_modules', 'lodash', 'index.js'), 'module.exports = {}');
await fs.writeFile(path.join(tmpDir, '.git', 'HEAD'), 'ref: refs/heads/main');
await fs.writeFile(path.join(tmpDir, 'package.json'), '{}');
await fs.writeFile(path.join(tmpDir, 'src', 'image.png'), Buffer.from([0x89, 0x50, 0x4E, 0x47]));
});
afterAll(async () => {
try {
await fs.rm(tmpDir, { recursive: true, force: true });
} catch { /* best-effort */ }
});
describe('walkRepositoryPaths', () => {
it('discovers source files', async () => {
const files = await walkRepositoryPaths(tmpDir);
const paths = files.map(f => f.path.replace(/\\/g, '/'));
expect(paths.some(p => p.includes('src/index.ts'))).toBe(true);
expect(paths.some(p => p.includes('src/utils.ts'))).toBe(true);
});
it('discovers nested files', async () => {
const files = await walkRepositoryPaths(tmpDir);
const paths = files.map(f => f.path.replace(/\\/g, '/'));
expect(paths.some(p => p.includes('components/Button.tsx'))).toBe(true);
});
it('skips node_modules', async () => {
const files = await walkRepositoryPaths(tmpDir);
const paths = files.map(f => f.path.replace(/\\/g, '/'));
expect(paths.every(p => !p.includes('node_modules'))).toBe(true);
});
it('skips .git directory', async () => {
const files = await walkRepositoryPaths(tmpDir);
const paths = files.map(f => f.path.replace(/\\/g, '/'));
expect(paths.every(p => !p.includes('.git/'))).toBe(true);
});
it('returns file sizes', async () => {
const files = await walkRepositoryPaths(tmpDir);
for (const file of files) {
expect(typeof file.size).toBe('number');
expect(file.size).toBeGreaterThan(0);
}
});
it('calls progress callback', async () => {
const onProgress = vi.fn();
await walkRepositoryPaths(tmpDir, onProgress);
expect(onProgress).toHaveBeenCalled();
});
});
describe('readFileContents', () => {
it('reads file contents by relative paths', async () => {
const contents = await readFileContents(tmpDir, ['src/index.ts', 'src/utils.ts']);
expect(contents.get('src/index.ts')).toContain('main');
expect(contents.get('src/utils.ts')).toContain('helper');
});
it('handles empty path list', async () => {
const contents = await readFileContents(tmpDir, []);
expect(contents.size).toBe(0);
});
it('skips non-existent files gracefully', async () => {
const contents = await readFileContents(tmpDir, ['nonexistent.ts']);
expect(contents.size).toBe(0);
});
});
});