// @vitest-environment jsdom import { act } from 'react'; import { createRoot } from 'react-dom/client'; import { afterEach, expect, it, vi } from 'vitest'; import type { ImportedDataset } from '../../src/domain/dataset'; import type { UnifiedResultProjection } from '../../src/domain/unified-result'; import { createReferenceRecognizer } from '../../src/domain/reference-recognition'; import { bundledReferenceCatalogs } from '../../server/reference-data/reference-catalogs'; import { appendPolicyObservationsToDataset } from '../../src/features/project-import/policy-observations-to-dataset'; import { FindingReader } from '../../src/features/finding-reader/FindingReader'; import { makeSheet } from '../../src/importers/sheet-factory'; afterEach(() => { vi.unstubAllGlobals(); document.body.replaceChildren(); }); it.each([false, true])('retains recognized references when opening the scanner Reader (GPOs: %s)', async withGpos => { vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true); const sheet = makeSheet('All Records', [ ['Title', 'Status', 'Category'], ['Synthetic scanner finding', 'Fail', 'Synthetic'], ['Synthetic indexed finding without references', 'Pass', 'Synthetic'], ['Synthetic unindexed finding', 'Fail', 'Synthetic'] ], '', 'Synthetic', { isProjectSheet: true }); const references = createReferenceRecognizer(bundledReferenceCatalogs)([ { key: 'attack', label: 'MITRE ATT&CK', value: 'T1059.001' }, { key: 'description', label: 'Description', value: 'T9999 D3-CH' } ]); const recognition = { runId: 'synthetic-reference-run', recognizerVersion: '1.0.0', createdAt: '2026-09-26T00:00:00Z', references }; sheet.analysis.records.forEach((record, index) => { record.findingOccurrenceId = `synthetic-occurrence-${index}`; }); sheet.analysis.records[0].referenceRecognition = recognition; sheet.analysis.records[1].referenceRecognition = { ...recognition, references: [] }; const dataset = { sheets: [sheet], rawText: '', profileId: 'generic', scanTool: 'Synthetic' } as ImportedDataset; const observation = { sourceKind: 'policy-observation', sourceResultId: 'synthetic-policy', projectId: 'synthetic', assessmentId: 'slot', policyBackupInstanceId: 'synthetic-backup', title: 'Synthetic GPO setting', importedAt: '2026-09-26T00:00:00Z', policyScope: 'computer', policyDeliveryMechanism: 'registry-policy', policyIdentityStatus: 'resolved', policyIdentityKey: 'synthetic-setting', policyState: 'configured', policyValues: [{ kind: 'registry-policy', operation: 'set-value', key: 'Software\\Synthetic', valueName: 'Mode', registryType: 4, data: 0 }] } as unknown as UnifiedResultProjection; const projected = appendPolicyObservationsToDataset(dataset, 'Synthetic', withGpos ? [observation] : [])!; const records = projected.sheets[0].analysis.records; expect(records).toHaveLength(withGpos ? 4 : 3); expect(records[0].referenceRecognition).toEqual(recognition); expect(records[1].referenceRecognition?.references).toEqual([]); expect(records[2].referenceRecognition).toBeUndefined(); if (withGpos) expect(records[3].referenceRecognition).toBeUndefined(); const host = document.createElement('div'); document.body.append(host); const root = createRoot(host); try { const record = records[0]; await act(async () => root.render( {}} onNext={() => {}} onReview={() => {}}/>)); const section = host.querySelector('[aria-label="Catalog references"]')!; expect(section).not.toBeNull(); expect(section.textContent).toContain('ATT&CK T1059.001'); expect(section.textContent).toContain('D3FEND D3-CH'); expect(section.textContent).toContain('Mentioned · Not found in this catalog'); expect(section.textContent).not.toContain('Not indexed yet'); const details = section.querySelector('details')!; await act(async () => details.querySelector('summary')!.click()); expect(details.open).toBe(true); expect(details.textContent).toContain('MITRE ATT&CK · attack'); expect(details.textContent).toContain('synthetic-reference-run'); expect(details.textContent).toContain(references[0].catalogVersion); expect(details.textContent).toContain(references[0].catalogSha256); } finally { await act(async () => root.unmount()); } });