import { describe, expect, it } from 'vitest'; // The reusable evaluation command is plain ESM so it can run directly with Node. // @ts-expect-error The script intentionally has no separate declaration file. import { changeFor, evaluateRun, validateBaseline } from '../../scripts/compare-regulatory-mappings.mjs'; function run(candidates: string[], mappings: Array<{ controlId: string; relationship: 'primary' | 'supporting' }>, status = 'succeeded') { return { run_status: status, data: { candidates: candidates.map((controlId, index) => ({ controlId, score: 1 / (61 + index) })), result: { mappings: mappings.map(mapping => ({ ...mapping, confidence: 'high' })) } } }; } const finding = { sourceRuleId: 'RULE-1', primary: '1.1', supporting: ['1.2'] }; describe('regulatory mapping comparison script', () => { it('allows a manual baseline with no primary and rejects duplicate relationships', () => { expect(() => validateBaseline({ schemaVersion: 1, scanners: [{ sourceTool: 'scanner', label: 'Scanner', findings: [{ sourceRuleId: 'RULE-1', primary: null, supporting: ['1.1'] }] }] })).not.toThrow(); expect(() => validateBaseline({ schemaVersion: 1, scanners: [{ sourceTool: 'scanner', label: 'Scanner', findings: [{ sourceRuleId: 'RULE-1', primary: '1.1', supporting: ['1.1'] }] }] })).toThrow(/duplicate controls/i); }); it('separates retrieval, selection, role and extra-control results', () => { const evaluation = evaluateRun(run( ['1.1', '1.2', '2.1'], [{ controlId: '1.1', relationship: 'supporting' }, { controlId: '2.1', relationship: 'primary' }] ), finding); expect(evaluation.retrievalGaps).toEqual([]); expect(evaluation.selectionGaps).toEqual(['1.2']); expect(evaluation.roleMismatches).toEqual(['1.1']); expect(evaluation.extras).toEqual(['2.1']); expect(evaluation.verdict).toBe('Incomplete + extras'); }); it('classifies opposing recall and extra-control changes as mixed', () => { const previous = evaluateRun(run(['1.1'], [{ controlId: '1.1', relationship: 'primary' }]), finding); const current = evaluateRun(run( ['1.1', '1.2', '2.1'], [ { controlId: '1.1', relationship: 'primary' }, { controlId: '1.2', relationship: 'supporting' }, { controlId: '2.1', relationship: 'supporting' } ] ), finding); expect(changeFor(previous, current)).toBe('Mixed'); }); });