okr/tests/inject-okr-context.test.mjs

78 lines
2.6 KiB
JavaScript

// inject-okr-context.test.mjs
// Tester hybrid org-profil-resolusjon (SC6): prosjekt-lokal -> hjem-profil.
// Spawner hooken som subprosess med kontrollert cwd + HOME. Zero npm deps.
// Plassert i tests/ (ikke hooks/scripts/) pga. pathguard-vern av hook-mappa.
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',
'inject-okr-context.mjs',
);
function makeHomeProfil(homeDir, navn) {
const p = join(homeDir, '.claude', 'okr', 'org');
mkdirSync(p, { recursive: true });
writeFileSync(join(p, 'profil.md'), `---\nnavn: "${navn}"\n---\n`);
}
function makeProjectConfig(workDir, navn) {
const p = join(workDir, '.claude');
mkdirSync(p, { recursive: true });
writeFileSync(join(p, 'okr.local.md'), `---\nnavn: "${navn}"\n---\n`);
}
function runHook(cwd, home) {
// execFileSync returns stdout; the hook always exits 0.
return execFileSync('node', [HOOK], {
cwd,
env: { ...process.env, HOME: home },
encoding: 'utf8',
});
}
function withDirs(fn) {
const home = mkdtempSync(join(tmpdir(), 'okrhome-'));
const work = mkdtempSync(join(tmpdir(), 'okrwork-'));
try {
fn(home, work);
} finally {
rmSync(home, { recursive: true, force: true });
rmSync(work, { recursive: true, force: true });
}
}
test('kun-hjem: leser org fra hjem-profil, ingen syklus-kontekst', () => {
withDirs((home, work) => {
makeHomeProfil(home, 'HjemOrg');
const out = runHook(work, home);
assert.match(out, /HjemOrg/, 'org skal komme fra hjem-profil naar prosjekt-config mangler');
assert.doesNotMatch(out, /Tilgjengelige kontekstfiler/, 'kun-hjem har ingen prosjekt-lokalt syklus-tre (okrDir er cwd-bundet)');
});
});
test('begge: prosjekt-lokal vinner over hjem (mest-spesifikk-vinner)', () => {
withDirs((home, work) => {
makeHomeProfil(home, 'HjemOrg');
makeProjectConfig(work, 'ProsjektOrg');
const out = runHook(work, home);
assert.match(out, /ProsjektOrg/, 'prosjekt-lokal skal vinne');
assert.doesNotMatch(out, /HjemOrg/, 'hjem skal ikke leses naar prosjekt-config finnes');
});
});
test('ingen: exit 0, tom output (graceful, regresjonsvakt)', () => {
withDirs((home, work) => {
const out = runHook(work, home);
assert.equal(out.trim(), '', 'ingen config -> tom stdout, ingen blokkering');
});
});