import { describe, it } from 'node:test'; import assert from 'node:assert/strict'; import { planExportPath, buildPlanExportDocument } from '../../scanners/lib/campaign-export.mjs'; const NOW = '2026-06-23'; const SESSION = '20260623_101500'; describe('planExportPath', () => { it('targets /docs/config-audit-plan-.md', () => { assert.equal( planExportPath('/Users/ktg/repos/foo', SESSION), `/Users/ktg/repos/foo/docs/config-audit-plan-${SESSION}.md`, ); }); it('keys on sessionId (not date) so same-day audits do not collide', () => { const a = planExportPath('/r/x', '20260623_090000'); const b = planExportPath('/r/x', '20260623_180000'); assert.notEqual(a, b); }); it('throws on a missing/blank repoPath or sessionId (programmer error)', () => { assert.throws(() => planExportPath('', SESSION), TypeError); assert.throws(() => planExportPath('/r/x', ' '), TypeError); assert.throws(() => planExportPath('/r/x'), TypeError); }); }); describe('buildPlanExportDocument', () => { const base = { repoName: 'foo', repoPath: '/Users/ktg/repos/foo', sessionId: SESSION, planMarkdown: '## Action 1\nDo the thing.\n', now: NOW, }; it('prepends a provenance header, then the verbatim plan body', () => { const doc = buildPlanExportDocument(base); assert.match(doc, /^# Config-Audit Action Plan — foo\n/); assert.ok(doc.includes(`on ${NOW}.`)); assert.ok(doc.includes('`/Users/ktg/repos/foo`')); assert.ok(doc.includes(`\`${SESSION}\``)); // body is present verbatim, after the --- separator const [, body] = doc.split('\n---\n'); assert.ok(body.includes('## Action 1\nDo the thing.')); }); it('points at the existing execute/undo/record machinery (reuse, not reinvent)', () => { const doc = buildPlanExportDocument(base); assert.ok(doc.includes('/config-audit implement')); assert.ok(doc.includes('/config-audit rollback')); assert.ok(doc.includes(`/config-audit campaign set-status ${base.repoPath} implemented`)); }); it('is deterministic — same inputs produce identical bytes', () => { assert.equal(buildPlanExportDocument(base), buildPlanExportDocument({ ...base })); }); it('trims trailing whitespace on the body and ends with exactly one newline', () => { const doc = buildPlanExportDocument({ ...base, planMarkdown: 'body\n\n\n' }); assert.ok(doc.endsWith('body\n')); assert.ok(!doc.endsWith('body\n\n')); }); it('throws when any required field is missing or blank', () => { for (const k of ['repoName', 'repoPath', 'sessionId', 'planMarkdown', 'now']) { assert.throws(() => buildPlanExportDocument({ ...base, [k]: '' }), TypeError, `blank ${k}`); } assert.throws(() => buildPlanExportDocument(), TypeError); }); });