import { createElement } from 'react'; import { renderToStaticMarkup } from 'react-dom/server'; import { describe, expect, it } from 'vitest'; import { formatAppLockerXml } from '../../src/profiles/group-policy/xml-presentation'; import { formatPolicyComparisonValue } from '../../src/profiles/group-policy/presentation'; import { baselineRemediation } from '../../src/profiles/group-policy/guidance'; import { FindingReader } from '../../src/features/finding-reader/FindingReader'; import type { PolicyEvaluationResult } from '../../src/domain/policy-evaluation'; import type { FindingRecord } from '../../src/domain/finding'; const publisher = ''; describe('AppLocker value display', () => { it('presents rule attributes and version bounds without XML syntax', () => { const formatted = formatAppLockerXml(publisher)!; for (const text of ['Publisher rule', 'Rule ID: synthetic-rule', 'Name: Synthetic application', 'Action: Deny', 'User/group SID: S-1-1-0', 'Publisher: O=SYNTHETIC', 'Product: DEMO', 'Binary: DEMO.EXE', 'Minimum: 1.0.0.0', 'Maximum: *']) expect(formatted).toContain(text); expect(formatted).not.toContain('<'); expect(formatPolicyComparisonValue(JSON.stringify({ kind: 'text', value: publisher }))).toBe(formatted); expect(formatPolicyComparisonValue(JSON.stringify([{ kind: 'registry-policy', data: { kind: 'string', value: publisher } }]))).toContain(' Publisher rule'); }); it('keeps path exceptions distinct from conditions and preserves collection mode', () => { const formatted = formatAppLockerXml('')!; expect(formatted).toContain('Enforcement mode: AuditOnly'); expect(formatted).toContain('Conditions\n Path condition\n Path: %WINDIR%\\*'); expect(formatted).toContain('Exceptions\n Path condition\n Path: %WINDIR%\\Temp\\*'); }); it('preserves hash attributes and unknown extensions instead of silently dropping them', () => { const formatted = formatAppLockerXml('Detail')!; expect(formatted).toContain('Type: SHA256'); expect(formatted).toContain('Data: ABC123'); expect(formatted).toContain('Source name: demo.exe'); expect(formatted).toContain('Future Setting: true'); expect(formatted).toContain('Detail'); }); it('falls back unchanged for malformed, unrelated, namespaced and entity-bearing XML', () => { for (const xml of ['', '', '', ']>', '']) { expect(formatAppLockerXml(xml)).toBeUndefined(); expect(formatPolicyComparisonValue(xml)).toBe(xml); } }); it('bounds size, depth, attributes and node count', () => { for (const xml of [ ``, `${''.repeat(33)}${''.repeat(33)}`, ` `a${i}="x"`).join(' ')}/>` , `${''.repeat(2001)}`, ]) expect(formatAppLockerXml(xml)).toBeUndefined(); }); it('uses the same readable baseline rule in remediation without changing evaluation', () => { const result = { baselineState: 'explicit-recommendation', diagnosticCodes: [], comparator: { baseline: { kind: 'text', value: publisher }, comparator: { kind: 'equality' } }, identity: { scope: 'computer', target: { hive: 'HKLM', key: 'Software\\Synthetic', valueName: 'Value' } } } as unknown as PolicyEvaluationResult; const original = JSON.stringify(result); expect(baselineRemediation(result)).toContain(`Expected: ${formatAppLockerXml(publisher)}`); expect(JSON.stringify(result)).toBe(original); }); it('renders values as inert readable text, without code panels or active markup', () => { const record = { id: 'synthetic', title: 'Synthetic policy', index: 0, filled: [], meta: [], fields: [ { index: 0, label: 'Configured value', value: '' }, { index: 1, label: 'Baseline value', value: publisher }, ] } as FindingRecord; const html = renderToStaticMarkup(createElement(FindingReader, { record, title: record.title, linkedSheets: [], resultReferences: [], search: '', position: 0, recordCount: 1, toolId: 'group-policy', onPrevious() {}, onNext() {}, onReview() {} })); expect(html).toContain('Publisher rule'); expect(html).toContain('Action: Deny'); expect(html).toContain('<img'); expect(html).not.toMatch(/<(?:img|pre|code)\b/); expect(html).toContain('class="policy-guidance-text"'); }); });