This commit is contained in:
2026-04-12 01:06:31 +07:00
commit 10d660cbcb
1066 changed files with 228596 additions and 0 deletions

View File

@@ -0,0 +1,138 @@
#!/usr/bin/env node
/**
* test-path-extractor.cjs - Unit tests for path-extractor module
*/
const { extractFromToolInput, extractFromCommand, looksLikePath } = require('../path-extractor.cjs');
const toolInputTests = [
{
input: { file_path: 'packages/web/src/index.js' },
expected: ['packages/web/src/index.js'],
desc: 'file_path extraction'
},
{
input: { path: 'node_modules' },
expected: ['node_modules'],
desc: 'path extraction'
},
{
input: { pattern: '**/node_modules/**' },
expected: ['**/node_modules/**'],
desc: 'pattern extraction'
},
{
input: { command: 'ls packages/web/node_modules' },
hasPath: 'packages/web/node_modules',
desc: 'command path extraction'
},
{
input: { file_path: '/home/user/project/node_modules/pkg/index.js' },
expected: ['/home/user/project/node_modules/pkg/index.js'],
desc: 'absolute path extraction'
},
{
input: { file_path: 'packages/web/node_modules/react/package.json', path: 'src' },
hasPath: 'packages/web/node_modules',
desc: 'multiple params extraction'
}
];
const commandTests = [
{ cmd: 'ls packages/web/node_modules', hasPath: 'packages/web/node_modules', desc: 'ls with subfolder' },
{ cmd: 'cat "path with spaces/file.js"', hasPath: 'path with spaces/file.js', desc: 'quoted path' },
{ cmd: "cat 'single/quoted/path.js'", hasPath: 'single/quoted/path.js', desc: 'single quoted path' },
{ cmd: 'cd apps/api/node_modules && ls', hasPath: 'apps/api/node_modules', desc: 'cd with chained command' },
{ cmd: 'rm -rf node_modules', hasPath: 'node_modules', desc: 'rm with flags' },
{ cmd: 'cp -r dist/ backup/', hasPath: 'dist', desc: 'cp with flags' },
// Note: Build commands may extract 'build' as a blocked dir name, but this is handled
// at the dispatcher level (build commands bypass path checking entirely).
// The path extractor correctly identifies blocked dir names like 'build'.
{ cmd: 'npm run build', hasPath: 'build', desc: 'npm run build (extracts build)' },
{ cmd: 'pnpm build', hasPath: 'build', desc: 'pnpm build (extracts build)' },
{ cmd: 'cd build', hasPath: 'build', desc: 'cd build (extracts build)' },
{ cmd: 'yarn test', hasPath: null, desc: 'yarn test (no blocked paths)' },
{ cmd: 'npm install', hasPath: null, desc: 'npm install (no blocked paths)' },
];
const looksLikePathTests = [
{ str: 'packages/web/src', expected: true, desc: 'relative path with slashes' },
{ str: '/home/user/project', expected: true, desc: 'absolute path' },
{ str: './src/index.js', expected: true, desc: 'dot-relative path' },
{ str: '../parent/file.js', expected: true, desc: 'parent-relative path' },
{ str: 'file.txt', expected: true, desc: 'file with extension' },
{ str: 'node_modules', expected: true, desc: 'blocked dir name' },
{ str: 'ls', expected: false, desc: 'command word' },
{ str: 'npm', expected: false, desc: 'package manager' },
{ str: '-rf', expected: false, desc: 'flag' },
{ str: '123', expected: false, desc: 'number' },
];
console.log('Testing path-extractor module...\n');
let passed = 0;
let failed = 0;
// Tool input tests
console.log('--- Tool Input Tests ---');
for (const test of toolInputTests) {
const result = extractFromToolInput(test.input);
let success;
if (test.expected) {
success = test.expected.every(e => result.includes(e));
} else if (test.hasPath) {
success = result.some(p => p.includes(test.hasPath));
}
if (success) {
console.log(`\x1b[32m✓\x1b[0m ${test.desc}`);
passed++;
} else {
console.log(`\x1b[31m✗\x1b[0m ${test.desc}: got ${JSON.stringify(result)}`);
failed++;
}
}
// Command tests
console.log('\n--- Command Tests ---');
for (const test of commandTests) {
const result = extractFromCommand(test.cmd);
let success;
if (test.hasPath === null) {
// Build commands should extract few/no blocked-related paths
success = result.length === 0 || !result.some(p =>
p.includes('node_modules') || p.includes('dist') || p.includes('build')
);
} else {
success = result.some(p => p.includes(test.hasPath));
}
if (success) {
console.log(`\x1b[32m✓\x1b[0m ${test.desc}: ${JSON.stringify(result)}`);
passed++;
} else {
console.log(`\x1b[31m✗\x1b[0m ${test.desc}: expected path containing '${test.hasPath}', got ${JSON.stringify(result)}`);
failed++;
}
}
// looksLikePath tests
console.log('\n--- looksLikePath Tests ---');
for (const test of looksLikePathTests) {
const result = looksLikePath(test.str);
const success = result === test.expected;
if (success) {
console.log(`\x1b[32m✓\x1b[0m ${test.desc}: '${test.str}' -> ${result}`);
passed++;
} else {
console.log(`\x1b[31m✗\x1b[0m ${test.desc}: expected ${test.expected}, got ${result}`);
failed++;
}
}
console.log(`\nResults: ${passed} passed, ${failed} failed`);
process.exit(failed > 0 ? 1 : 0);