test(humanizer): replace title-string assertions with ID-based checks

Wave 2 / Step 4 of v5.1.0 plain-language UX humanizer rollout. Re-anchors
34 title-string assertions across 4 test files so they survive Wave 3's
title/description/recommendation rewriting at the CLI layer.

Anchoring strategy per scanner:
- GAP findings: scanner + category + recommendation substring (humanizer
  preserves stable identifiers like CLAUDE.md, .mcp.json, hook in rec).
  Hardcoded CA-GAP-NNN IDs for positive checks.
- HKV findings: scanner + evidence regex (evidence preserved verbatim).
- SET findings: scanner + evidence regex (evidence preserved verbatim).
- PLH findings: scanner + hardcoded CA-PLH-NNN IDs (no evidence on most
  PLH findings, so ID is the only stable anchor for specific cases;
  negative checks use scanner + title-substring spanning raw + humanized).

Per docs/v5.1.0-test-audit.md classification: only (b) WILL BREAK
assertions modified. (a) shape-only assertions (error-message formatting,
pure existence checks) untouched. tests/lib/output.test.mjs and
tests/lib/diff-engine.test.mjs and tests/scanners/fix-engine.test.mjs
unchanged (synthetic test inputs, not scanner output).

Test count unchanged: 689/689 pass. IDs harvested via deterministic
runtime dump per fixture (resetCounter + scan).
This commit is contained in:
Kjell Tore Guttormsen 2026-05-01 17:22:55 +02:00
commit dff278f02a
4 changed files with 73 additions and 33 deletions

View file

@ -42,15 +42,21 @@ describe('GAP scanner — healthy project', () => {
});
it('does NOT report missing CLAUDE.md', () => {
assert.ok(!result.findings.some(f => f.title === 'No CLAUDE.md file'));
assert.ok(!result.findings.some(f =>
f.scanner === 'GAP' && f.category === 't1' && /CLAUDE\.md/.test(f.recommendation || '')
));
});
it('does NOT report missing MCP', () => {
assert.ok(!result.findings.some(f => f.title === 'No MCP servers configured'));
assert.ok(!result.findings.some(f =>
f.scanner === 'GAP' && f.category === 't1' && /\.mcp\.json/.test(f.recommendation || '')
));
});
it('does NOT report missing hooks', () => {
assert.ok(!result.findings.some(f => f.title === 'No hooks configured'));
assert.ok(!result.findings.some(f =>
f.scanner === 'GAP' && f.category === 't1' && /hook/i.test(f.recommendation || '')
));
});
it('has counts object with all severity levels', () => {
@ -93,11 +99,13 @@ describe('GAP scanner — minimal project', () => {
});
it('reports missing hooks', () => {
assert.ok(result.findings.some(f => f.title === 'No hooks configured'));
// CA-GAP-002 in minimal-project = t1_3 (No hooks configured); see docs/v5.1.0-test-audit.md.
assert.ok(result.findings.some(f => f.scanner === 'GAP' && f.id === 'CA-GAP-002'));
});
it('reports missing MCP', () => {
assert.ok(result.findings.some(f => f.title === 'No MCP servers configured'));
// CA-GAP-004 in minimal-project = t1_5 (No MCP servers configured).
assert.ok(result.findings.some(f => f.scanner === 'GAP' && f.id === 'CA-GAP-004'));
});
it('T1 gaps are medium severity', () => {
@ -147,7 +155,8 @@ describe('GAP scanner — empty project', () => {
});
it('reports T1 gaps including missing CLAUDE.md', () => {
assert.ok(result.findings.some(f => f.title === 'No CLAUDE.md file'));
// CA-GAP-001 in empty-project = t1_1 (No CLAUDE.md file).
assert.ok(result.findings.some(f => f.scanner === 'GAP' && f.id === 'CA-GAP-001'));
});
});