import { describe, expect, it } from 'vitest'; import { createReferenceRecognizer } from '../../src/domain/reference-recognition'; import { bundledReferenceCatalogs, referenceSnapshot } from '../../server/reference-data/reference-catalogs'; const recognize = createReferenceRecognizer(bundledReferenceCatalogs); const field = (value: string, label = 'Description') => ({ key: 'source', label, value, path: '/original/source' }); describe('framework-wide reference recognition', () => { it('distinguishes declared IDs, mentioned IDs, unknown IDs and exact declared titles', () => { expect(recognize([field('T1059.001; TA0002', 'MITRE ATT&CK')]).map(ref => [ref.id, ref.evidence, ref.status])) .toEqual([['T1059.001', 'declared', 'active'], ['TA0002', 'declared', 'active']]); expect(recognize([field('Consider T1059.001 and D3-CH, plus T9999.')]).map(ref => [ref.id, ref.evidence, ref.status])) .toEqual([['T1059.001', 'mentioned', 'active'], ['T9999', 'mentioned', 'not-in-catalog'], ['D3-CH', 'mentioned', 'active']]); expect(recognize([field('PowerShell; Execution', 'MITRE ATT&CK')]).map(ref => [ref.id, ref.matchedBy])) // PowerShell names both a historical technique and a current sub-technique: do not guess. .toEqual([['TA0002', 'exact-title']]); expect(recognize([field('PowerShell; Execution; Credential Hardening')])).toEqual([]); expect(recognize([field('Credential Hardening', 'D3FEND')])[0]).toMatchObject({ id: 'D3-CH', evidence: 'declared', matchedBy: 'exact-title' }); }); it('retains every repeated original occurrence and UTF-16 offsets without rewriting source values', () => { const original = field('😀 See t1059.001 then T1059.001.'); const before = structuredClone(original); const refs = recognize([original]); expect(refs).toHaveLength(2); for (const ref of refs) expect(original.value.slice(ref.source.start, ref.source.end)).toBe(ref.source.text); expect(refs[0].source).toMatchObject({ start: 7, end: 16, offsetUnit: 'utf16', text: 't1059.001', fieldPath: '/original/source' }); expect(original).toEqual(before); }); it('uses rawValue when retained and traces nested JSON leaves otherwise', () => { expect(recognize([{ ...field('T1003'), rawValue: 'T1059.001' }])[0]).toMatchObject({ id: 'T1059.001', source: { representation: 'rawValue' } }); const refs = recognize([{ ...field(''), value: { 'a/b': ['T1003', 'D3-CH'] } }]); expect(refs.map(ref => ref.source.valuePath)).toEqual(['/a~1b/0', '/a~1b/1']); }); it.each(['T10590', 'T1059.0001', 'T1059.01', 'hostT1059', 'T1059host', 'x_T1059', 'D3-CH-MORE', 'N/A', '-', 'Txxxx'])('does not guess from %s', value => { expect(recognize([field(value, 'MITRE ATT&CK')])).toEqual([]); }); it('preserves deprecated/revoked catalog status and refuses ambiguous titles', () => { const entries = bundledReferenceCatalogs[0].entries; const historical = entries.find(entry => entry.state !== 'active')!; expect(recognize([field(historical.id)])[0].status).toBe(historical.state); const { sha256: _, ...catalog } = bundledReferenceCatalogs[0]; const ambiguous = referenceSnapshot({ ...catalog, entries: [{ ...entries[0], id: 'T9998', title: 'Ambiguous' }, { ...entries[0], id: 'T9999', title: 'Ambiguous' }] }); expect(createReferenceRecognizer([ambiguous])([field('Ambiguous', 'MITRE ATT&CK')])).toEqual([]); }); });