63 lines
3.6 KiB
TypeScript
63 lines
3.6 KiB
TypeScript
// @vitest-environment jsdom
|
|
import { renderToStaticMarkup } from 'react-dom/server';
|
|
import { describe, expect, it } from 'vitest';
|
|
import type { PolicySourceEvidence as Source } from '../../src/domain/finding';
|
|
import { PolicySourceEvidence } from '../../src/features/finding-reader/PolicySourceEvidence';
|
|
|
|
/** Synthetic Registry.pol contribution of one GPO backup. */
|
|
function source(backup: string, key: string, data: number, deviating = true): Source {
|
|
return {
|
|
id: backup, backupKey: backup, backupInstanceId: `gpo-backup-${backup}`, sequence: 1,
|
|
sourceReference: `{${backup}}/DomainSysvol/GPO/Machine/registry.pol#records=1`,
|
|
values: [{ kind: 'registry-policy', operation: 'set-value', key, valueName: 'SyntheticEnable', data: { kind: 'uint32', value: data }, typeCode: 4 }],
|
|
baselineRelation: deviating ? 'conflicting' : 'aligned',
|
|
...(deviating ? { deviationFields: [['data']] } : {})
|
|
};
|
|
}
|
|
|
|
function render(sources: Source[]) {
|
|
const container = document.createElement('div');
|
|
container.innerHTML = renderToStaticMarkup(<PolicySourceEvidence sources={sources} search=""/>);
|
|
return container;
|
|
}
|
|
|
|
describe('GPO source value overview', () => {
|
|
it('states identical instructions of several backups once and notes a letter-case-only key difference', () => {
|
|
const container = render([
|
|
source('synthetic-a', 'SOFTWARE\\Policies\\Synthetic', 0),
|
|
source('synthetic-b', 'Software\\Policies\\Synthetic', 0),
|
|
source('synthetic-c', 'Software\\Policies\\Synthetic', 0)
|
|
]);
|
|
const overview = container.querySelector('.policy-source-overview')!;
|
|
expect(overview.querySelector('.policy-source-overview__summary')?.textContent).toBe('All 3 sources retain the same instruction');
|
|
expect(overview.querySelector('.policy-source-overview__value')?.textContent).toBe('Operation: set-value · Data: 0 · Type code: 4 (REG_DWORD)');
|
|
// The overview stays neutral; the field-specific marker remains only in each source section.
|
|
expect(overview.querySelector('.policy-source-deviation-value')).toBeNull();
|
|
expect(container.querySelectorAll('.policy-source-deviation-value')).toHaveLength(3);
|
|
expect(overview.querySelector('.policy-source-overview__sources')).toBeNull();
|
|
expect(overview.querySelector('.policy-source-overview__note')?.textContent).toContain('different letter case');
|
|
// Every complete source section remains immediately visible.
|
|
expect(container.querySelectorAll('.policy-source-group')).toHaveLength(3);
|
|
expect(container.querySelectorAll('.policy-source-group details')).toHaveLength(0);
|
|
});
|
|
|
|
it('groups differing instructions and names the contributing backups', () => {
|
|
const container = render([
|
|
source('synthetic-a', 'Software\\Policies\\Synthetic', 0),
|
|
source('synthetic-b', 'Software\\Policies\\Synthetic', 1, false),
|
|
source('synthetic-c', 'Software\\Policies\\Synthetic', 0)
|
|
]);
|
|
const overview = container.querySelector('.policy-source-overview')!;
|
|
expect(overview.querySelector('.policy-source-overview__summary')?.textContent).toBe('2 different instructions across 3 sources');
|
|
expect([...overview.querySelectorAll('.policy-source-overview__sources')].map(item => item.textContent)).toEqual([
|
|
'2 of 3: GPO backup gpo-backup-synthetic-a, GPO backup gpo-backup-synthetic-c',
|
|
'1 of 3: GPO backup gpo-backup-synthetic-b'
|
|
]);
|
|
expect(overview.querySelector('.policy-source-overview__note')).toBeNull();
|
|
});
|
|
|
|
it('adds no overview for a single backup source', () => {
|
|
expect(render([source('synthetic-a', 'Software\\Policies\\Synthetic', 0)]).querySelector('.policy-source-overview')).toBeNull();
|
|
});
|
|
});
|