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,165 @@
#!/usr/bin/env node
/**
* test-broad-pattern-detector.cjs - Unit tests for broad pattern detection
*
* Tests the detection of overly broad glob patterns that would fill context.
*/
const {
isBroadPattern,
hasSpecificDirectory,
isHighLevelPath,
detectBroadPatternIssue,
suggestSpecificPatterns
} = require('../broad-pattern-detector.cjs');
// === isBroadPattern tests ===
const broadPatternTests = [
// Should be detected as broad - TypeScript/JavaScript
{ pattern: '**/*', expected: true, desc: 'all files everywhere' },
{ pattern: '**', expected: true, desc: 'double star alone' },
{ pattern: '*', expected: true, desc: 'single star alone' },
{ pattern: '**/.*', expected: true, desc: 'all dotfiles' },
// Should NOT be detected as broad (specific)
{ pattern: 'package.json', expected: false, desc: 'specific file' },
{ pattern: 'src/index.ts', expected: false, desc: 'specific file path' },
{ pattern: null, expected: false, desc: 'null pattern' },
{ pattern: '', expected: false, desc: 'empty pattern' },
];
// === isHighLevelPath tests ===
const highLevelPathTests = [
// High level (risky)
{ path: null, expected: true, desc: 'null path (uses CWD)' },
{ path: undefined, expected: true, desc: 'undefined path' },
{ path: '.', expected: true, desc: 'current directory' },
{ path: './', expected: true, desc: 'current directory with slash' },
{ path: '', expected: true, desc: 'empty path' },
{ path: '/home/user/worktrees/myproject', expected: true, desc: 'worktree root' },
{ path: 'myproject', expected: true, desc: 'single directory' },
// Specific (OK)
{ path: 'src/components', expected: false, desc: 'nested in src' },
{ path: 'lib/utils', expected: false, desc: 'nested in lib' },
{ path: 'packages/web/src', expected: false, desc: 'monorepo src' },
{ path: '/home/user/project/src', expected: false, desc: 'absolute with src' },
];
// === detectBroadPatternIssue integration tests ===
const integrationTests = [
// Should BLOCK
{
input: { pattern: '**/*.ts' },
expected: true,
desc: 'broad pattern, no path'
},
{
input: { pattern: '**/*.{ts,tsx}', path: '/home/user/worktrees/myproject' },
expected: true,
desc: 'broad pattern at worktree'
},
{
input: { pattern: '**/*', path: '.' },
expected: true,
desc: 'all files at current dir'
},
{
input: { pattern: '**/index.ts', path: 'myproject' },
expected: true,
desc: 'all index.ts at shallow path'
},
// Should ALLOW
{
input: { pattern: 'src/**/*.ts' },
expected: false,
desc: 'scoped to src'
},
{
input: { pattern: '**/*.ts', path: 'src/components' },
expected: false,
desc: 'broad pattern but specific path'
},
{
input: { pattern: 'package.json' },
expected: false,
desc: 'specific file'
},
{
input: { pattern: 'lib/**/*.js', path: '/home/user/project' },
expected: false,
desc: 'scoped pattern'
},
{
input: {},
expected: false,
desc: 'no pattern'
},
{
input: null,
expected: false,
desc: 'null input'
},
];
// Run tests
console.log('Testing broad-pattern-detector module...\n');
let passed = 0;
let failed = 0;
// Test isBroadPattern
console.log('\x1b[1m--- isBroadPattern ---\x1b[0m');
for (const test of broadPatternTests) {
const result = isBroadPattern(test.pattern);
const success = result === test.expected;
if (success) {
console.log(`\x1b[32m✓\x1b[0m ${test.desc}: "${test.pattern}" -> ${result ? 'BROAD' : 'OK'}`);
passed++;
} else {
console.log(`\x1b[31m✗\x1b[0m ${test.desc}: expected ${test.expected ? 'BROAD' : 'OK'}, got ${result ? 'BROAD' : 'OK'}`);
failed++;
}
}
// Test isHighLevelPath
console.log('\n\x1b[1m--- isHighLevelPath ---\x1b[0m');
for (const test of highLevelPathTests) {
const result = isHighLevelPath(test.path);
const success = result === test.expected;
if (success) {
console.log(`\x1b[32m✓\x1b[0m ${test.desc}: "${test.path}" -> ${result ? 'HIGH_LEVEL' : 'SPECIFIC'}`);
passed++;
} else {
console.log(`\x1b[31m✗\x1b[0m ${test.desc}: expected ${test.expected ? 'HIGH_LEVEL' : 'SPECIFIC'}, got ${result ? 'HIGH_LEVEL' : 'SPECIFIC'}`);
failed++;
}
}
// Test integration
console.log('\n\x1b[1m--- detectBroadPatternIssue (integration) ---\x1b[0m');
for (const test of integrationTests) {
const result = detectBroadPatternIssue(test.input);
const success = result.blocked === test.expected;
if (success) {
console.log(`\x1b[32m✓\x1b[0m ${test.desc} -> ${result.blocked ? 'BLOCKED' : 'ALLOWED'}`);
passed++;
} else {
console.log(`\x1b[31m✗\x1b[0m ${test.desc}: expected ${test.expected ? 'BLOCKED' : 'ALLOWED'}, got ${result.blocked ? 'BLOCKED' : 'ALLOWED'}`);
failed++;
}
}
// Test suggestions
console.log('\n\x1b[1m--- suggestSpecificPatterns ---\x1b[0m');
const suggestions = suggestSpecificPatterns('**/*.ts');
if (suggestions.length > 0 && suggestions.some(s => s.includes('src/'))) {
console.log(`\x1b[32m✓\x1b[0m suggestions for **/*.ts include src-scoped patterns`);
passed++;
} else {
console.log(`\x1b[31m✗\x1b[0m suggestions should include src-scoped patterns`);
failed++;
}
console.log(`\n\x1b[1mResults:\x1b[0m ${passed} passed, ${failed} failed`);
process.exit(failed > 0 ? 1 : 0);