Step 4 of v2.0 plan. statusLine hook reads context_window.used_percentage from stdin payload and prints display-only hint at 60% / 70%. NEVER runs git (research/03 — statusLine scripts can be cancelled mid-flight, unsafe for side effects). 9 tests cover thresholds, null payload, malformed JSON. Includes hook-helper.mjs copied from llm-security as test infrastructure.
78 lines
2.6 KiB
JavaScript
78 lines
2.6 KiB
JavaScript
// statusline-monitor.test.mjs — Tests statusLine hook display thresholds.
|
|
|
|
import { test } from 'node:test';
|
|
import { strict as assert } from 'node:assert';
|
|
import { dirname, join } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
import { runHook } from './hook-helper.mjs';
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
const HOOK = join(__dirname, '..', '..', 'hooks', 'scripts', 'statusline-monitor.mjs');
|
|
|
|
function payload(usedPercentage) {
|
|
return {
|
|
context_window: {
|
|
used_percentage: usedPercentage,
|
|
remaining_percentage: usedPercentage == null ? null : 100 - usedPercentage,
|
|
context_window_size: 200000,
|
|
},
|
|
model: { id: 'claude-opus-4-7', display_name: 'Opus' },
|
|
session_id: 'test-session',
|
|
};
|
|
}
|
|
|
|
test('< 60%: silent, no output', async () => {
|
|
const res = await runHook(HOOK, payload(45));
|
|
assert.equal(res.code, 0);
|
|
assert.equal(res.stdout.trim(), '', `expected empty stdout, got: "${res.stdout}"`);
|
|
});
|
|
|
|
test('60-69%: prints "vurder /graceful-handoff" hint with "60" or "kontekst" substring', async () => {
|
|
const res = await runHook(HOOK, payload(63));
|
|
assert.equal(res.code, 0);
|
|
assert.match(res.stdout, /kontekst/);
|
|
assert.match(res.stdout, /vurder.*graceful-handoff/);
|
|
});
|
|
|
|
test('≥ 70%: prints stronger hint with "kjør NÅ"', async () => {
|
|
const res = await runHook(HOOK, payload(75));
|
|
assert.equal(res.code, 0);
|
|
assert.match(res.stdout, /kontekst/);
|
|
assert.match(res.stdout, /kjør.*graceful-handoff.*NÅ/i);
|
|
});
|
|
|
|
test('exact threshold 60%: shows hint (not silent)', async () => {
|
|
const res = await runHook(HOOK, payload(60));
|
|
assert.equal(res.code, 0);
|
|
assert.match(res.stdout, /60/);
|
|
});
|
|
|
|
test('exact threshold 70%: shows urgent hint', async () => {
|
|
const res = await runHook(HOOK, payload(70));
|
|
assert.equal(res.code, 0);
|
|
assert.match(res.stdout, /NÅ/);
|
|
});
|
|
|
|
test('null used_percentage: silent (early session before first API call)', async () => {
|
|
const res = await runHook(HOOK, payload(null));
|
|
assert.equal(res.code, 0);
|
|
assert.equal(res.stdout.trim(), '');
|
|
});
|
|
|
|
test('missing context_window field: silent', async () => {
|
|
const res = await runHook(HOOK, { model: { id: 'foo' }, session_id: 'x' });
|
|
assert.equal(res.code, 0);
|
|
assert.equal(res.stdout.trim(), '');
|
|
});
|
|
|
|
test('empty stdin: silent', async () => {
|
|
const res = await runHook(HOOK, '');
|
|
assert.equal(res.code, 0);
|
|
assert.equal(res.stdout.trim(), '');
|
|
});
|
|
|
|
test('malformed JSON: silent (no crash)', async () => {
|
|
const res = await runHook(HOOK, '{not json');
|
|
assert.equal(res.code, 0);
|
|
assert.equal(res.stdout.trim(), '');
|
|
});
|