Assessor_2.0/tests/features/regulatory-mapping-panel.te...

60 lines
3.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { renderToStaticMarkup } from 'react-dom/server';
import { describe, expect, it } from 'vitest';
import { RegulatoryMappingPanel } from '../../src/features/finding-reader/RegulatoryMappingPanel';
import type { RegulatoryMappingResponse } from '../../src/domain/regulatory-mapping';
const response: RegulatoryMappingResponse = {
version: 1, projectId: 'project-1', resultProjectionId: 'scanner-finding:occurrence-1', generationEnabled: true,
state: 'succeeded', decisions: [], run: {
version: 1, id: 'regulatory-mapping-abc', ruleKey: 'purple-knight:A-SmbSigning', sourceTool: 'purple-knight', sourceRuleId: 'A-SmbSigning',
status: 'succeeded', queryHash: 'a'.repeat(64),
preparedQuery: { schemaVersion: 1, query: 'Synthetic public query.', specificity: 'topic', publicTopics: ['Synthetic topic'] },
corpusId: 'iso-test', corpusVersion: 'v2', sourceHashes: ['b'.repeat(64)], embeddingModel: 'bge-m3',
retrievalVersion: 'test', promptVersion: 'test', outputSchemaVersion: 1, model: 'work-model',
createdAt: '2026-09-15T10:00:00.000Z', updatedAt: '2026-09-15T10:00:00.000Z',
candidates: [{
controlId: '5.1', annexAControlId: 'A.5.1', title: 'Synthetic title', score: 0.91,
evidence: [{ chunkId: 'chunk-1', textSha256: 'c'.repeat(64), sourceSha256: 'b'.repeat(64), sourceStandard: 'ISO/IEC 27002',
sectionKind: 'purpose', pageStart: 12, pageEnd: 13, text: 'Synthetic evidence text.' }]
}, {
controlId: '5.2', annexAControlId: 'A.5.2', title: 'Other synthetic title', score: 0.72,
evidence: [{ chunkId: 'chunk-2', textSha256: 'd'.repeat(64), sourceSha256: 'b'.repeat(64), sourceStandard: 'ISO/IEC 27001',
sectionKind: 'control', pageStart: 14, pageEnd: 14, text: 'Other synthetic evidence.' }]
}],
result: { schemaVersion: 1, outcome: 'mapped', mappings: [{ controlId: '5.1', relationship: 'primary', confidence: 'high',
rationale: 'Synthetic rationale.', evidenceChunkIds: ['chunk-1'] }] }
}
};
describe('regulatory mapping panel', () => {
it('renders proposed controls before collapsed other candidates with page-referenced evidence and review actions', () => {
const html = renderToStaticMarkup(<RegulatoryMappingPanel response={response} loading={false} error="" onStart={() => {}} onDecision={() => {}}/>);
expect(html.indexOf('A.5.1 — Synthetic title')).toBeLessThan(html.indexOf('Other retrieved controls'));
expect(html).not.toContain('5.1 · A.5.1');
expect(html).toContain('primary · high confidence');
expect(html).toContain('pages 12–13');
expect(html).toContain('ISO/IEC 27002 · purpose');
expect(html).not.toContain('Synthetic evidence text.');
expect(html).toContain('Accept');
expect(html).toContain('Reject');
expect(html).toContain('not proof of compliance');
});
it('surfaces the structural failure detail alongside the safe error code', () => {
const failed: RegulatoryMappingResponse = {
...response, state: 'failed',
run: { ...response.run!, status: 'failed', result: undefined,
errorCode: 'regulatory_mapping_invalid_output', errorDetail: 'mappings[0].evidenceChunkIds[0] is not grounded in the supplied control.' }
};
const html = renderToStaticMarkup(<RegulatoryMappingPanel response={failed} loading={false} error="" onStart={() => {}} onDecision={() => {}}/>);
expect(html).toContain('regulatory_mapping_invalid_output');
expect(html).toContain('is not grounded in the supplied control.');
});
it('shows a concrete disabled reason without exposing a generation action', () => {
const html = renderToStaticMarkup(<RegulatoryMappingPanel response={{ ...response, generationEnabled: false, state: 'unsupported', disabledReason: 'Qdrant is unavailable.', run: undefined }} loading={false} error="" onStart={() => {}} onDecision={() => {}}/>);
expect(html).toContain('Qdrant is unavailable.');
expect(html).not.toContain('Generate proposals');
});
});