import { describe, expect, it } from 'vitest';
import { parseGpoBackupMetadataXml } from '../../server/gpo/gpo-metadata-parser';
import type { VerifiedZipFile } from '../../server/gpo/zip-inventory';
const guid = '11111111-1111-4111-8111-111111111111';
function parse(xml: string) {
return parseGpoBackupMetadataXml({ bytes: Buffer.from(xml), entry: {
relativePath: 'synthetic/Backup.xml', sha256: 'a'.repeat(64)
} } as unknown as VerifiedZipFile);
}
describe('GPMC metadata field paths', () => {
it('reads names only from bounded template fields when explicitly requested', () => {
const file = { bytes: Buffer.from('MSFT Windows Server 2016 - Domain ControllerWrong'),
entry: { relativePath: 'Synthetic/GPReport.xml', sha256: 'a'.repeat(64) } } as unknown as VerifiedZipFile;
expect(parseGpoBackupMetadataXml(file).templateNames).toBeUndefined();
expect(parseGpoBackupMetadataXml(file, undefined, true).templateNames).toEqual(['MSFT Windows Server 2016 - Domain Controller']);
const withIdentity = { ...file, bytes: Buffer.from(`Arbitrary display name{${guid}}`) };
expect(parseGpoBackupMetadataXml(withIdentity, undefined, true).gpoId).toBe(guid);
expect(parseGpoBackupMetadataXml(file, undefined, true).gpoId).toBeUndefined();
});
it('reads the GPMC core identity without interpreting unrelated IDs as a GPO', () => {
const result = parse(`
22222222-2222-4222-8222-222222222222unrelated.example
{${guid}}synthetic.example
`);
expect(result).toMatchObject({ gpoId: guid, domainKey: 'dns:synthetic.example', status: 'partial' });
expect(result.backupId).toBeUndefined();
expect(result.backupCreatedAt).toBeUndefined();
});
it('reads a nested GPReport Identifier and preserves missing backup-specific evidence', () => {
const result = parse(`{${guid}}
synthetic.example`);
expect(result.gpoId).toBe(guid);
expect(result.domainKey).toBe('dns:synthetic.example');
expect(result.diagnosticCodes).not.toContain('gpo-metadata-field-shape-invalid');
expect(result.diagnosticCodes).toContain('gpo-metadata-backup-id-missing');
});
it('keeps depth limits and rejects external entities', () => {
expect(() => parse(''.repeat(129) + ''.repeat(129))).toThrow();
expect(() => parse(']>&e;')).toThrow();
});
});