feat(okr): coaching-hook klokke-seam + node-test fixtures (SC4) [skip-docs]
This commit is contained in:
parent
60174e8f5c
commit
b594eeb88c
2 changed files with 102 additions and 1 deletions
99
tests/coaching-hook.test.mjs
Normal file
99
tests/coaching-hook.test.mjs
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
// coaching-hook.test.mjs
|
||||
// Tester coaching-hook (SC4): graceful-exit-grener + gyldig-syklus-emisjon +
|
||||
// deterministisk fase via OKR_NOW klokke-seam. Spawner hooken som subprosess
|
||||
// med kontrollert cwd + env. Zero npm deps. Coaching leser kun cwd, saa én
|
||||
// temp-dir per test holder. Moenster: tests/inject-okr-context.test.mjs.
|
||||
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { execFileSync } from 'node:child_process';
|
||||
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from 'node:fs';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { join, dirname } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const HOOK = join(
|
||||
dirname(fileURLToPath(import.meta.url)),
|
||||
'..',
|
||||
'hooks',
|
||||
'scripts',
|
||||
'coaching-hook.mjs',
|
||||
);
|
||||
|
||||
function writeConfig(workDir, body) {
|
||||
const p = join(workDir, '.claude');
|
||||
mkdirSync(p, { recursive: true });
|
||||
writeFileSync(join(p, 'okr.local.md'), body);
|
||||
}
|
||||
|
||||
function runHook(cwd, okrNow) {
|
||||
// execFileSync returnerer stdout; hooken avslutter alltid med exit 0.
|
||||
const env = { ...process.env };
|
||||
if (okrNow) env.OKR_NOW = okrNow;
|
||||
else delete env.OKR_NOW;
|
||||
return execFileSync('node', [HOOK], { cwd, env, encoding: 'utf8' });
|
||||
}
|
||||
|
||||
function withWork(fn) {
|
||||
const work = mkdtempSync(join(tmpdir(), 'okrcoach-'));
|
||||
try {
|
||||
fn(work);
|
||||
} finally {
|
||||
rmSync(work, { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
|
||||
test('ingen config: exit 0, tom stdout (graceful)', () => {
|
||||
withWork((work) => {
|
||||
const out = runHook(work);
|
||||
assert.equal(out.trim(), '', 'ingen config -> tom stdout, ingen blokkering');
|
||||
});
|
||||
});
|
||||
|
||||
test('config uten id: exit 0, tom stdout', () => {
|
||||
withWork((work) => {
|
||||
writeConfig(work, '---\nnavn: "Org"\n---\n');
|
||||
const out = runHook(work);
|
||||
assert.equal(out.trim(), '', 'manglende id -> tom stdout');
|
||||
});
|
||||
});
|
||||
|
||||
test('ugyldig id: exit 0, tom stdout', () => {
|
||||
withWork((work) => {
|
||||
writeConfig(work, '---\nid: "ugyldig"\n---\n');
|
||||
const out = runHook(work);
|
||||
assert.equal(out.trim(), '', 'id som ikke matcher T/Q-moenster -> tom stdout');
|
||||
});
|
||||
});
|
||||
|
||||
test('gyldig syklus: emitterer systemMessage', () => {
|
||||
withWork((work) => {
|
||||
writeConfig(work, '---\nid: "T2-2026"\n---\n');
|
||||
const out = runHook(work);
|
||||
assert.match(out, /OKR coaching/, 'gyldig syklus skal emittere coaching-melding');
|
||||
});
|
||||
});
|
||||
|
||||
test('OKR_NOW tidlig fase: early-coaching', () => {
|
||||
withWork((work) => {
|
||||
writeConfig(work, '---\nid: "T2-2026"\n---\n');
|
||||
const out = runHook(work, '2026-05-05');
|
||||
assert.match(out, /Tidlig i syklusen/, 'uke 1 av T2 -> tidlig fase');
|
||||
});
|
||||
});
|
||||
|
||||
test('OKR_NOW midtveis fase: mid-coaching', () => {
|
||||
withWork((work) => {
|
||||
writeConfig(work, '---\nid: "T2-2026"\n---\n');
|
||||
const out = runHook(work, '2026-06-20');
|
||||
assert.match(out, /Midtveis i syklusen/, 'uke ~8 av T2 -> midtveis fase');
|
||||
});
|
||||
});
|
||||
|
||||
test('OKR_NOW sen fase: late-coaching', () => {
|
||||
withWork((work) => {
|
||||
writeConfig(work, '---\nid: "T2-2026"\n---\n');
|
||||
const out = runHook(work, '2026-08-25');
|
||||
assert.match(out, /sluttspurt/, 'uke ~16 av T2 -> sen fase');
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue