Assessor_2.0/tests/compliance/compliance-project-export-h...

57 lines
3.1 KiB
TypeScript

import { mkdtemp, rm, writeFile } from 'node:fs/promises';
import type { Server } from 'node:http';
import type { AddressInfo } from 'node:net';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { afterEach, beforeEach, expect, it } from 'vitest';
import { createAssessorHttpServer } from '../../server/assessor-http-server';
import { LocalComplianceStore } from '../../src/compliance/local-compliance-store';
import type { RegulatoryMappingBatchRun } from '../../src/compliance/regulatory-mapping';
import { LocalAssessorRepository } from '../../src/persistence/local-assessor-repository';
// The project export keeps the engine's data: the Core export and the Compliance Engine's own
// project data are combined at the HTTP route, not inside the Core repository.
const stamp = '2026-10-05T08:00:00.000Z';
let directory: string;
let server: Server | undefined;
beforeEach(async () => {
directory = await mkdtemp(join(tmpdir(), 'assessor-compliance-export-'));
await writeFile(join(directory, 'index.html'), '<main>synthetic app</main>');
});
afterEach(async () => {
await new Promise(resolve => server ? server.close(resolve) : resolve(undefined));
server = undefined;
await rm(directory, { recursive: true, force: true });
});
async function exportVia(complianceExport?: LocalComplianceStore) {
const repository = new LocalAssessorRepository();
await repository.saveProject({ id: 'dummy-project', name: 'Dummy Customer', createdAt: stamp, updatedAt: stamp, attributes: {} });
server = createAssessorHttpServer({ repository, staticRoot: directory, ...(complianceExport ? { complianceExport } : {}) });
await new Promise<void>(resolve => server!.listen(0, '127.0.0.1', resolve));
const { port } = server.address() as AddressInfo;
return (await fetch(`http://127.0.0.1:${port}/api/v1/projects/dummy-project/export`)).json();
}
it('adds the Compliance Engine project data to the Core project export', async () => {
const store = new LocalComplianceStore();
const batch = await store.createRegulatoryMappingBatchRun({
version: 1, id: 'dummy-batch', projectId: 'dummy-project', scopeKey: 'scope', filterHash: 'a'.repeat(64),
idempotencyKey: 'dummy-batch-1', assessmentIds: ['dummy-assessment'], scanRunIds: [], filters: {}, status: 'queued',
counts: { filteredResultCount: 0, excludedNonScannerCount: 0, eligibleFindingCount: 0, unsupportedFindingCount: 0,
distinctRuleCount: 0, reusedSucceededRuleCount: 0, reusedActiveRuleCount: 0, scheduledRuleCount: 0,
succeededRuleCount: 0, failedRuleCount: 0 },
createdAt: stamp, updatedAt: stamp
} satisfies RegulatoryMappingBatchRun);
const exported = await exportVia(store);
expect(exported).toMatchObject({ project: { id: 'dummy-project' }, regulatoryMappingBatchRuns: [batch],
regulatoryMappingRuns: [], regulatoryMappingDecisions: [] });
});
it('keeps the Core project export complete without the Compliance Engine', async () => {
const exported = await exportVia();
expect(exported).toMatchObject({ project: { id: 'dummy-project' } });
expect(exported).not.toHaveProperty('regulatoryMappingBatchRuns');
});