// 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'); }); });