mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-05-17 22:33:06 +08:00
302 lines
8.9 KiB
JavaScript
302 lines
8.9 KiB
JavaScript
/**
|
|
* Tests for scripts/hooks/ecc-context-monitor.js
|
|
*
|
|
* Run with: node tests/hooks/ecc-context-monitor.test.js
|
|
*/
|
|
|
|
const assert = require('assert');
|
|
const fs = require('fs');
|
|
const os = require('os');
|
|
const path = require('path');
|
|
|
|
const { run, evaluateConditions, detectLoop, severityLabel, costWarningsEnabled } = require('../../scripts/hooks/ecc-context-monitor');
|
|
const { getBridgePath, writeBridgeAtomic } = require('../../scripts/lib/session-bridge');
|
|
|
|
// Test helper
|
|
function test(name, fn) {
|
|
try {
|
|
fn();
|
|
console.log(` \u2713 ${name}`);
|
|
return true;
|
|
} catch (err) {
|
|
console.log(` \u2717 ${name}`);
|
|
console.log(` Error: ${err.message}`);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function withEnv(name, value, fn) {
|
|
const original = process.env[name];
|
|
try {
|
|
if (value === undefined) delete process.env[name];
|
|
else process.env[name] = value;
|
|
return fn();
|
|
} finally {
|
|
if (original === undefined) delete process.env[name];
|
|
else process.env[name] = original;
|
|
}
|
|
}
|
|
|
|
function runTests() {
|
|
console.log('\n=== Testing ecc-context-monitor.js ===\n');
|
|
|
|
let passed = 0;
|
|
let failed = 0;
|
|
|
|
// evaluateConditions — context warnings
|
|
console.log('evaluateConditions (context):');
|
|
|
|
if (
|
|
test('remaining 20% triggers CRITICAL context warning', () => {
|
|
const warnings = evaluateConditions({ context_remaining_pct: 20 });
|
|
const ctx = warnings.find(w => w.type === 'context');
|
|
assert.ok(ctx, 'Expected a context warning');
|
|
assert.strictEqual(ctx.severity, 3);
|
|
assert.ok(ctx.message.includes('CRITICAL'), 'Message should contain CRITICAL');
|
|
})
|
|
)
|
|
passed++;
|
|
else failed++;
|
|
|
|
if (
|
|
test('remaining 30% triggers WARNING context warning', () => {
|
|
const warnings = evaluateConditions({ context_remaining_pct: 30 });
|
|
const ctx = warnings.find(w => w.type === 'context');
|
|
assert.ok(ctx, 'Expected a context warning');
|
|
assert.strictEqual(ctx.severity, 2);
|
|
assert.ok(ctx.message.includes('WARNING'), 'Message should contain WARNING');
|
|
})
|
|
)
|
|
passed++;
|
|
else failed++;
|
|
|
|
if (
|
|
test('remaining 50% triggers no context warning', () => {
|
|
const warnings = evaluateConditions({ context_remaining_pct: 50 });
|
|
const ctx = warnings.find(w => w.type === 'context');
|
|
assert.strictEqual(ctx, undefined);
|
|
})
|
|
)
|
|
passed++;
|
|
else failed++;
|
|
|
|
// evaluateConditions — cost warnings
|
|
console.log('\nevaluateConditions (cost):');
|
|
|
|
if (
|
|
test('cost $55 triggers CRITICAL cost warning', () => {
|
|
const warnings = evaluateConditions({ total_cost_usd: 55 });
|
|
const cost = warnings.find(w => w.type === 'cost');
|
|
assert.ok(cost, 'Expected a cost warning');
|
|
assert.strictEqual(cost.severity, 3);
|
|
assert.ok(cost.message.includes('CRITICAL'), 'Message should contain CRITICAL');
|
|
})
|
|
)
|
|
passed++;
|
|
else failed++;
|
|
|
|
if (
|
|
test('cost $12 triggers WARNING cost warning', () => {
|
|
const warnings = evaluateConditions({ total_cost_usd: 12 });
|
|
const cost = warnings.find(w => w.type === 'cost');
|
|
assert.ok(cost, 'Expected a cost warning');
|
|
assert.strictEqual(cost.severity, 2);
|
|
assert.ok(cost.message.includes('WARNING'), 'Message should contain WARNING');
|
|
})
|
|
)
|
|
passed++;
|
|
else failed++;
|
|
|
|
if (
|
|
test('cost $6 triggers NOTICE cost warning', () => {
|
|
const warnings = evaluateConditions({ total_cost_usd: 6 });
|
|
const cost = warnings.find(w => w.type === 'cost');
|
|
assert.ok(cost, 'Expected a cost warning');
|
|
assert.strictEqual(cost.severity, 1);
|
|
assert.ok(cost.message.includes('NOTICE'), 'Message should contain NOTICE');
|
|
})
|
|
)
|
|
passed++;
|
|
else failed++;
|
|
|
|
if (
|
|
test('cost $2 triggers no cost warning', () => {
|
|
const warnings = evaluateConditions({ total_cost_usd: 2 });
|
|
const cost = warnings.find(w => w.type === 'cost');
|
|
assert.strictEqual(cost, undefined);
|
|
})
|
|
)
|
|
passed++;
|
|
else failed++;
|
|
|
|
if (
|
|
test('cost warnings can be suppressed without hiding context warnings', () => {
|
|
const warnings = evaluateConditions({ total_cost_usd: 55, context_remaining_pct: 20 }, { costWarnings: false });
|
|
assert.strictEqual(warnings.find(w => w.type === 'cost'), undefined);
|
|
const ctx = warnings.find(w => w.type === 'context');
|
|
assert.ok(ctx, 'Expected context warning to remain enabled');
|
|
assert.strictEqual(ctx.severity, 3);
|
|
})
|
|
)
|
|
passed++;
|
|
else failed++;
|
|
|
|
if (
|
|
test('ECC_CONTEXT_MONITOR_COST_WARNINGS=off disables only run-time cost warnings', () => {
|
|
const sessionId = `ctx-monitor-cost-off-${process.pid}-${Date.now()}`;
|
|
const input = JSON.stringify({ session_id: sessionId, tool_name: 'Bash' });
|
|
const warnPath = path.join(os.tmpdir(), `ecc-ctx-warn-${sessionId}.json`);
|
|
try {
|
|
writeBridgeAtomic(sessionId, {
|
|
context_remaining_pct: 20,
|
|
total_cost_usd: 55,
|
|
last_timestamp: new Date().toISOString()
|
|
});
|
|
const result = withEnv('ECC_CONTEXT_MONITOR_COST_WARNINGS', 'off', () => JSON.parse(run(input)));
|
|
const message = result.hookSpecificOutput.additionalContext;
|
|
assert.ok(message.includes('CONTEXT CRITICAL'), 'Expected context warning to remain');
|
|
assert.ok(!message.includes('COST CRITICAL'), 'Expected cost warning to be suppressed');
|
|
} finally {
|
|
fs.rmSync(getBridgePath(sessionId), { force: true });
|
|
fs.rmSync(warnPath, { force: true });
|
|
}
|
|
})
|
|
)
|
|
passed++;
|
|
else failed++;
|
|
|
|
if (
|
|
test('cost warning env defaults on and accepts false-like values', () => {
|
|
assert.strictEqual(withEnv('ECC_CONTEXT_MONITOR_COST_WARNINGS', undefined, () => costWarningsEnabled()), true);
|
|
assert.strictEqual(withEnv('ECC_CONTEXT_MONITOR_COST_WARNINGS', 'false', () => costWarningsEnabled()), false);
|
|
assert.strictEqual(withEnv('ECC_CONTEXT_MONITOR_COST_WARNINGS', '0', () => costWarningsEnabled()), false);
|
|
assert.strictEqual(withEnv('ECC_CONTEXT_MONITOR_COST_WARNINGS', 'yes', () => costWarningsEnabled()), true);
|
|
})
|
|
)
|
|
passed++;
|
|
else failed++;
|
|
|
|
// evaluateConditions — scope warnings
|
|
console.log('\nevaluateConditions (scope):');
|
|
|
|
if (
|
|
test('25 files triggers scope WARNING', () => {
|
|
const warnings = evaluateConditions({ files_modified_count: 25 });
|
|
const scope = warnings.find(w => w.type === 'scope');
|
|
assert.ok(scope, 'Expected a scope warning');
|
|
assert.strictEqual(scope.severity, 2);
|
|
assert.ok(scope.message.includes('SCOPE'), 'Message should contain SCOPE');
|
|
})
|
|
)
|
|
passed++;
|
|
else failed++;
|
|
|
|
if (
|
|
test('10 files triggers no scope warning', () => {
|
|
const warnings = evaluateConditions({ files_modified_count: 10 });
|
|
const scope = warnings.find(w => w.type === 'scope');
|
|
assert.strictEqual(scope, undefined);
|
|
})
|
|
)
|
|
passed++;
|
|
else failed++;
|
|
|
|
// detectLoop tests
|
|
console.log('\ndetectLoop:');
|
|
|
|
if (
|
|
test('3 identical entries returns detected true', () => {
|
|
const entries = [
|
|
{ tool: 'Bash', hash: 'aabbccdd' },
|
|
{ tool: 'Bash', hash: 'aabbccdd' },
|
|
{ tool: 'Bash', hash: 'aabbccdd' }
|
|
];
|
|
const result = detectLoop(entries);
|
|
assert.strictEqual(result.detected, true);
|
|
assert.strictEqual(result.tool, 'Bash');
|
|
assert.ok(result.count >= 3);
|
|
})
|
|
)
|
|
passed++;
|
|
else failed++;
|
|
|
|
if (
|
|
test('all different entries returns detected false', () => {
|
|
const entries = [
|
|
{ tool: 'Bash', hash: '11111111' },
|
|
{ tool: 'Edit', hash: '22222222' },
|
|
{ tool: 'Write', hash: '33333333' }
|
|
];
|
|
const result = detectLoop(entries);
|
|
assert.strictEqual(result.detected, false);
|
|
})
|
|
)
|
|
passed++;
|
|
else failed++;
|
|
|
|
if (
|
|
test('empty array returns detected false', () => {
|
|
const result = detectLoop([]);
|
|
assert.strictEqual(result.detected, false);
|
|
})
|
|
)
|
|
passed++;
|
|
else failed++;
|
|
|
|
// severityLabel tests
|
|
console.log('\nseverityLabel:');
|
|
|
|
if (
|
|
test('severity 3 returns critical', () => {
|
|
assert.strictEqual(severityLabel(3), 'critical');
|
|
})
|
|
)
|
|
passed++;
|
|
else failed++;
|
|
|
|
if (
|
|
test('severity 2 returns warning', () => {
|
|
assert.strictEqual(severityLabel(2), 'warning');
|
|
})
|
|
)
|
|
passed++;
|
|
else failed++;
|
|
|
|
if (
|
|
test('severity 1 returns notice', () => {
|
|
assert.strictEqual(severityLabel(1), 'notice');
|
|
})
|
|
)
|
|
passed++;
|
|
else failed++;
|
|
|
|
// run tests
|
|
console.log('\nrun:');
|
|
|
|
if (
|
|
test('empty input returns input unchanged', () => {
|
|
const result = run('');
|
|
assert.strictEqual(result, '');
|
|
})
|
|
)
|
|
passed++;
|
|
else failed++;
|
|
|
|
if (
|
|
test('input without session_id returns input unchanged', () => {
|
|
const input = JSON.stringify({ tool_name: 'Bash' });
|
|
const result = run(input);
|
|
assert.strictEqual(result, input);
|
|
})
|
|
)
|
|
passed++;
|
|
else failed++;
|
|
|
|
// Summary
|
|
console.log(`\nResults: ${passed} passed, ${failed} failed\n`);
|
|
return { passed, failed };
|
|
}
|
|
|
|
const { failed } = runTests();
|
|
process.exit(failed > 0 ? 1 : 0);
|