mirror of
https://github.com/proffesor-for-testing/agentic-qe.git
synced 2026-09-19 08:45:47 +08:00
2253d05618
Remove the nested v3/ subdirectory by moving all active source code, tests, configs, and assets directly to the project root. Archive v2/ (dead code, 847MB) to v2-archive.tar.gz. Key changes: - Move v3/src/ → src/, v3/tests/ → tests/, v3/packages/ → packages/ - Move v3/tsconfig.json, v3/vitest.config.ts to root - Merge v3/package.json into root package.json (ESM, scripts, deps, exports) - Merge v3/scripts/ into scripts/, v3/implementation/ into docs/implementation/ - Update all CI workflows to remove "cd v3 &&" and v3/ path prefixes - Fix all init installer path resolution (3-level-up → 2-level-up) - Fix hooks to use "node ./dist/cli/bundle.js" instead of bare "aqe" - Update settings.json ADR/DDD directories to docs/implementation/ - Fix helper scripts (statusline, adr-compliance, ddd-tracker, guidance-hooks) - Update 58 agent definitions: aqe/v3/ → aqe/ memory namespaces - Update 15 guidance shards: v3/src/ → src/ path references - Fix sync interfaces: remove v3/ and v2/ path references - Fix test path calculations (process.cwd() + '..' no longer needed) - Fix flaky perf test threshold (500ms → 1000ms for CI environments) - Fix complexity-analyzer test to match ADR-051 keyword-based eligibility Build passes, 17,901 tests pass, CLI and MCP bundles verified. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
179 lines
6.2 KiB
TypeScript
179 lines
6.2 KiB
TypeScript
/**
|
|
* Unit Tests for CLI File Discovery (Fix #280)
|
|
*
|
|
* Tests the shared walkSourceFiles utility that replaced
|
|
* duplicated inline walkers in test/coverage/security/code commands.
|
|
*/
|
|
|
|
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
import { mkdirSync, writeFileSync, rmSync } from 'fs';
|
|
import { join } from 'path';
|
|
import { tmpdir } from 'os';
|
|
import { walkSourceFiles } from '../../../../src/cli/utils/file-discovery';
|
|
|
|
describe('walkSourceFiles (Fix #280)', () => {
|
|
let tempDir: string;
|
|
|
|
beforeEach(() => {
|
|
tempDir = join(tmpdir(), `aqe-test-${Date.now()}`);
|
|
mkdirSync(tempDir, { recursive: true });
|
|
});
|
|
|
|
afterEach(() => {
|
|
rmSync(tempDir, { recursive: true, force: true });
|
|
});
|
|
|
|
it('should find TypeScript files', () => {
|
|
writeFileSync(join(tempDir, 'index.ts'), 'export const x = 1;');
|
|
writeFileSync(join(tempDir, 'app.tsx'), 'export default App;');
|
|
|
|
const files = walkSourceFiles(tempDir);
|
|
expect(files.length).toBe(2);
|
|
expect(files.some(f => f.endsWith('.ts'))).toBe(true);
|
|
expect(files.some(f => f.endsWith('.tsx'))).toBe(true);
|
|
});
|
|
|
|
it('should find Python files', () => {
|
|
writeFileSync(join(tempDir, 'main.py'), 'print("hello")');
|
|
writeFileSync(join(tempDir, 'util.pyw'), 'pass');
|
|
|
|
const files = walkSourceFiles(tempDir);
|
|
expect(files.length).toBe(2);
|
|
});
|
|
|
|
it('should find Go files', () => {
|
|
writeFileSync(join(tempDir, 'main.go'), 'package main');
|
|
|
|
const files = walkSourceFiles(tempDir);
|
|
expect(files.length).toBe(1);
|
|
expect(files[0]).toContain('.go');
|
|
});
|
|
|
|
it('should find Rust files', () => {
|
|
writeFileSync(join(tempDir, 'lib.rs'), 'fn main() {}');
|
|
|
|
const files = walkSourceFiles(tempDir);
|
|
expect(files.length).toBe(1);
|
|
expect(files[0]).toContain('.rs');
|
|
});
|
|
|
|
it('should find Java and Kotlin files', () => {
|
|
writeFileSync(join(tempDir, 'App.java'), 'class App {}');
|
|
writeFileSync(join(tempDir, 'Main.kt'), 'fun main() {}');
|
|
|
|
const files = walkSourceFiles(tempDir);
|
|
expect(files.length).toBe(2);
|
|
});
|
|
|
|
it('should find C/C++ files', () => {
|
|
writeFileSync(join(tempDir, 'main.c'), 'int main() {}');
|
|
writeFileSync(join(tempDir, 'lib.cpp'), 'class Lib {};');
|
|
writeFileSync(join(tempDir, 'lib.h'), '#pragma once');
|
|
|
|
const files = walkSourceFiles(tempDir);
|
|
expect(files.length).toBe(3);
|
|
});
|
|
|
|
it('should skip node_modules', () => {
|
|
const nmDir = join(tempDir, 'node_modules', 'pkg');
|
|
mkdirSync(nmDir, { recursive: true });
|
|
writeFileSync(join(nmDir, 'index.ts'), 'export {};');
|
|
writeFileSync(join(tempDir, 'src.ts'), 'export {};');
|
|
|
|
const files = walkSourceFiles(tempDir);
|
|
expect(files.length).toBe(1);
|
|
expect(files[0]).toContain('src.ts');
|
|
});
|
|
|
|
it('should skip dist and build dirs', () => {
|
|
for (const dir of ['dist', 'build']) {
|
|
const d = join(tempDir, dir);
|
|
mkdirSync(d, { recursive: true });
|
|
writeFileSync(join(d, 'bundle.js'), 'var x;');
|
|
}
|
|
writeFileSync(join(tempDir, 'app.js'), 'const x = 1;');
|
|
|
|
const files = walkSourceFiles(tempDir);
|
|
expect(files.length).toBe(1);
|
|
});
|
|
|
|
it('should skip __pycache__ and .venv', () => {
|
|
for (const dir of ['__pycache__', '.venv']) {
|
|
const d = join(tempDir, dir);
|
|
mkdirSync(d, { recursive: true });
|
|
writeFileSync(join(d, 'mod.py'), 'pass');
|
|
}
|
|
writeFileSync(join(tempDir, 'main.py'), 'pass');
|
|
|
|
const files = walkSourceFiles(tempDir);
|
|
expect(files.length).toBe(1);
|
|
});
|
|
|
|
it('should exclude test files when includeTests is false', () => {
|
|
writeFileSync(join(tempDir, 'app.ts'), 'export {};');
|
|
writeFileSync(join(tempDir, 'app.test.ts'), 'it("works", () => {});');
|
|
writeFileSync(join(tempDir, 'app.spec.ts'), 'describe("app", () => {});');
|
|
|
|
const files = walkSourceFiles(tempDir, { includeTests: false });
|
|
expect(files.length).toBe(1);
|
|
expect(files[0]).toContain('app.ts');
|
|
});
|
|
|
|
it('should include test files when includeTests is true', () => {
|
|
writeFileSync(join(tempDir, 'app.ts'), 'export {};');
|
|
writeFileSync(join(tempDir, 'app.test.ts'), 'it("works", () => {});');
|
|
|
|
const files = walkSourceFiles(tempDir, { includeTests: true });
|
|
expect(files.length).toBe(2);
|
|
});
|
|
|
|
it('should return only test files when testsOnly is true', () => {
|
|
writeFileSync(join(tempDir, 'app.ts'), 'export {};');
|
|
writeFileSync(join(tempDir, 'app.test.ts'), 'it("works", () => {});');
|
|
writeFileSync(join(tempDir, 'app.spec.js'), 'describe("x", () => {});');
|
|
writeFileSync(join(tempDir, 'test_main.py'), 'def test_x(): pass');
|
|
|
|
const files = walkSourceFiles(tempDir, { testsOnly: true });
|
|
expect(files.length).toBe(3);
|
|
expect(files.every(f =>
|
|
f.includes('.test.') || f.includes('.spec.') || f.includes('test_')
|
|
)).toBe(true);
|
|
});
|
|
|
|
it('should respect maxDepth option', () => {
|
|
const deep = join(tempDir, 'a', 'b', 'c');
|
|
mkdirSync(deep, { recursive: true });
|
|
writeFileSync(join(tempDir, 'root.ts'), 'export {};');
|
|
writeFileSync(join(tempDir, 'a', 'level1.ts'), 'export {};');
|
|
writeFileSync(join(tempDir, 'a', 'b', 'level2.ts'), 'export {};');
|
|
writeFileSync(join(deep, 'level3.ts'), 'export {};');
|
|
|
|
const files = walkSourceFiles(tempDir, { maxDepth: 2 });
|
|
expect(files.length).toBe(3); // root + level1 + level2
|
|
});
|
|
|
|
it('should handle non-existent path gracefully', () => {
|
|
const files = walkSourceFiles(join(tempDir, 'nonexistent'));
|
|
expect(files).toEqual([]);
|
|
});
|
|
|
|
it('should handle single file path', () => {
|
|
const filePath = join(tempDir, 'single.ts');
|
|
writeFileSync(filePath, 'export {};');
|
|
|
|
const files = walkSourceFiles(filePath);
|
|
expect(files.length).toBe(1);
|
|
expect(files[0]).toBe(filePath);
|
|
});
|
|
|
|
it('should ignore non-source extensions', () => {
|
|
writeFileSync(join(tempDir, 'readme.md'), '# Hello');
|
|
writeFileSync(join(tempDir, 'data.json'), '{}');
|
|
writeFileSync(join(tempDir, 'styles.css'), 'body {}');
|
|
writeFileSync(join(tempDir, 'image.png'), 'binary');
|
|
|
|
const files = walkSourceFiles(tempDir);
|
|
expect(files.length).toBe(0);
|
|
});
|
|
});
|