Assessor_2.0/tests/persistence/regulatory-mapping-batch.te...

51 lines
2.6 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import type { RegulatoryMappingBatchRun } from '../../src/domain/regulatory-mapping';
import { LocalAssessorRepository } from '../../src/persistence/local-assessor-repository';
const stamp = '2026-09-16T08:00:00.000Z';
function batch(overrides: Partial<RegulatoryMappingBatchRun> = {}): RegulatoryMappingBatchRun {
return {
version: 1,
id: 'batch-1',
projectId: 'project-1',
scopeKey: 'scope-1',
filterHash: 'a'.repeat(64),
idempotencyKey: 'batch-request-1',
assessmentIds: ['assessment-1'],
scanRunIds: [],
filters: { deviation: true },
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,
...overrides
};
}
describe('local regulatory mapping batch persistence', () => {
it('preserves idempotency and active-scope uniqueness, exports batches and deletes them with the project', async () => {
const repository = new LocalAssessorRepository();
await repository.saveProject({ id: 'project-1', name: 'Synthetic', createdAt: stamp, updatedAt: stamp, attributes: {} });
await repository.saveAssessment({ id: 'assessment-1', projectId: 'project-1', name: 'Synthetic', createdAt: stamp, updatedAt: stamp });
const first = await repository.createRegulatoryMappingBatchRun(batch());
await expect(repository.createRegulatoryMappingBatchRun(batch({ id: 'batch-idempotent' }))).resolves.toEqual(first);
await expect(repository.createRegulatoryMappingBatchRun(batch({ id: 'batch-active', idempotencyKey: 'batch-request-2' }))).resolves.toEqual(first);
expect((await repository.exportProject('project-1')).regulatoryMappingBatchRuns).toEqual([first]);
const running = await repository.updateRegulatoryMappingBatchRun({ ...first, status: 'running', startedAt: stamp });
await repository.updateRegulatoryMappingBatchRun({ ...running, status: 'completed', completedAt: stamp });
const retry = await repository.createRegulatoryMappingBatchRun(batch({ id: 'batch-2', idempotencyKey: 'batch-request-2' }));
expect((await repository.listRegulatoryMappingBatchRuns('project-1', 'scope-1')).map(item => item.id)).toEqual(['batch-2', 'batch-1']);
expect(retry.id).toBe('batch-2');
await repository.deleteProject('project-1', { projectId: 'project-1', cascade: true });
await expect(repository.listRegulatoryMappingBatchRuns('project-1')).resolves.toEqual([]);
});
});