BMAD-METHOD/test/test-abs-path-leak.js

99 lines
3.2 KiB
JavaScript

/**
* Absolute Path Leak Detection Test Runner
*
* Tests checkAbsolutePathLeaks() from validate-file-refs.js. Focused on Windows
* drive paths, which use a single separator (C:\Users) and were previously missed.
*
* Usage: node test/test-abs-path-leak.js
* Exit codes: 0 = all tests pass, 1 = test failures
*/
const { checkAbsolutePathLeaks } = require('../tools/validate-file-refs.js');
// ANSI color codes
const colors = {
reset: '[0m',
green: '[32m',
red: '[31m',
cyan: '[36m',
};
let totalTests = 0;
let passedTests = 0;
const failures = [];
/**
* Run a single named test case, recording the result and printing a status line.
* @param {string} name - Human-readable test description.
* @param {Function} fn - Test body; throw to signal failure.
*/
function test(name, fn) {
totalTests++;
try {
fn();
passedTests++;
console.log(` ${colors.green}OK${colors.reset} ${name}`);
} catch (error) {
console.log(` ${colors.red}XX${colors.reset} ${name} ${colors.red}${error.message}${colors.reset}`);
failures.push({ name, message: error.message });
}
}
/**
* Throw an Error with `message` when `condition` is falsy.
* @param {boolean} condition - Expression that must hold.
* @param {string} message - Failure message.
*/
function assert(condition, message) {
if (!condition) throw new Error(message);
}
/**
* Count the leak lines detected in a content string.
* @param {string} content - File content to scan (filePath is only used for labelling).
* @returns {number} Number of lines flagged as absolute-path leaks.
*/
function leakCount(content) {
return checkAbsolutePathLeaks('fixture.md', content).length;
}
console.log(`\n${colors.cyan}Absolute Path Leak Detection${colors.reset}\n`);
test('Windows single-backslash drive path is detected', () => {
assert(leakCount('See C:\\Users\\alex\\notes.md for details.') === 1, 'C:\\Users... not detected');
});
test('Windows forward-slash drive path is detected', () => {
assert(leakCount('See C:/Users/alex/notes.md for details.') === 1, 'C:/Users... not detected');
});
test('Unix /Users path is detected', () => {
assert(leakCount('open /Users/alex/secret.md') === 1, '/Users path not detected');
});
test('Unix /home path is detected', () => {
assert(leakCount('open /home/alex/secret.md') === 1, '/home path not detected');
});
test('relative paths are not flagged', () => {
assert(leakCount('load `./workflow.md` and ../shared/util.md') === 0, 'relative path falsely flagged');
});
test('leaks inside fenced code blocks are ignored', () => {
const content = ['```bash', 'cat C:\\Users\\alex\\secret.md', '```'].join('\n');
assert(leakCount(content) === 0, 'leak inside code block should be stripped');
});
// --- Summary ---
console.log(`\n${colors.cyan}${'='.repeat(55)}${colors.reset}`);
console.log(`Total: ${totalTests} Passed: ${colors.green}${passedTests}${colors.reset} Failed: ${totalTests - passedTests}`);
console.log(`${colors.cyan}${'='.repeat(55)}${colors.reset}\n`);
if (failures.length > 0) {
for (const failure of failures) console.log(`${colors.red}XX${colors.reset} ${failure.name}: ${failure.message}`);
process.exit(1);
}
console.log(`${colors.green}All tests passed!${colors.reset}\n`);
process.exit(0);