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"');
});
});