import { describe, expect, it } from 'vitest'; import { buildPolicyAnalysisOverview, type BuildPolicyAnalysisOverviewInput } from '../../src/domain/policy-analysis-overview'; const timestamp = '2026-08-04T16:00:00.000Z'; function input(options: { aggregation?: boolean; baseline?: 'complete' | 'partial' | 'missing'; evaluation?: boolean } = {}): BuildPolicyAnalysisOverviewInput { const aggregation = { version: 1, run: { id: 'aggregation-1', environmentProfileId: 'profile-1', sourceAnalysisRunIds: ['identity-run-1'], status: 'complete', diagnosticCodes: [], snapshotId: 'snapshot-1' }, snapshot: { instanceIds: ['backup-1'] }, states: [], reviewHints: [] }; const evaluation = { version: 1, run: { id: 'evaluation-1', aggregationRunId: 'aggregation-1', environmentProfileId: 'profile-1', baselineAnalysisIds: ['baseline-analysis-1'], status: 'partial', diagnosticCodes: [], completedAt: timestamp, matchCount: 0, deviationCount: 0, notApplicableCount: 0, reviewCount: 1 }, results: [{ id: 'evaluation-result-1', identity: { id: 'identity-1' }, findingEligibility: 'ineligible', classification: 'review_required', baselineState: 'catalog-gap', diagnosticCodes: ['policy-evaluation-catalog-gap'], observationIds: [], backupInstanceIds: [] }], evidence: [] }; return { projectId: 'project-1', generatedAt: timestamp, identityAnalyses: [{ run: { id: 'identity-run-1', artifactId: 'artifact-1', sourceProcessingRunId: 'processing-1', status: 'complete', observationCount: 0, resolvedCount: 0, diagnosticCodes: [], completedAt: timestamp }, resolutions: [] }], profiles: [{ id: 'profile-1', name: 'Windows Server 2025', revision: 1, contexts: [{ id: 'context-1', productFamily: 'Windows Server', productVersion: '2025', role: 'Member Server', scope: 'computer' }] }], aggregations: options.aggregation ? [aggregation] : [], evaluations: options.evaluation ? [evaluation] : [], findingRuns: [], processingRuns: [{ id: 'processing-1', artifactId: 'artifact-1', completedAt: timestamp }], baselineRecords: options.baseline === 'missing' || !options.baseline ? [] : [{ id: 'baseline-1', status: 'eligible', metadata: { productContexts: [{ productFamily: 'Windows Server', productVersion: '2025', roles: ['Any'], scopes: ['mixed'] }] } }], baselineAnalyses: options.baseline === 'missing' || !options.baseline ? [] : [{ analysis: { id: 'baseline-analysis-1', baselineId: 'baseline-1', analyzedAt: timestamp, status: options.baseline } }] } as unknown as BuildPolicyAnalysisOverviewInput; } describe('policy analysis action readiness', () => { it('offers deterministic reprocessing and aggregation for active source and profile revisions', () => { const overview = buildPolicyAnalysisOverview(input()); expect(overview.actions.reprocess).toEqual([expect.objectContaining({ status: 'ready', artifactId: 'artifact-1', expectedLatestProcessingRunId: 'processing-1' })]); expect(overview.actions.aggregate).toEqual([expect.objectContaining({ status: 'ready', environmentProfileId: 'profile-1', sourceAnalysisRunIds: ['identity-run-1'] })]); }); it('selects one matching complete baseline analysis and offers evaluation', () => { const overview = buildPolicyAnalysisOverview(input({ aggregation: true, baseline: 'complete' })); expect(overview.actions.aggregate[0]).toMatchObject({ status: 'completed', existingRunId: 'aggregation-1' }); expect(overview.actions.evaluate).toEqual([expect.objectContaining({ status: 'ready', aggregationRunId: 'aggregation-1', baselineAnalysisIds: ['baseline-analysis-1'] })]); }); it('excludes superseded profile and identity-analysis revisions from new actions', () => { const data = input(); const oldProfile = data.profiles[0]; data.profiles.push({ ...oldProfile, id: 'profile-2', name: 'Windows Server 2025 revised', revision: 2, supersedesProfileId: oldProfile.id }); const oldAnalysis = data.identityAnalyses[0]; data.identityAnalyses.push({ ...oldAnalysis, run: { ...oldAnalysis.run, id: 'identity-run-2', sourceProcessingRunId: 'processing-2', supersedesAnalysisRunId: oldAnalysis.run.id } }); data.processingRuns!.push({ id: 'processing-2', artifactId: 'artifact-1', completedAt: '2026-08-04T16:01:00.000Z' } as never); const overview = buildPolicyAnalysisOverview(data); expect(overview.actions.aggregate).toHaveLength(1); expect(overview.actions.aggregate[0]).toMatchObject({ environmentProfileId: 'profile-2', sourceAnalysisRunIds: ['identity-run-2'] }); expect(overview.actions.reprocess[0].expectedLatestProcessingRunId).toBe('processing-2'); }); it('marks partial baseline evidence review-only and blocks missing catalog evidence', () => { const partial = buildPolicyAnalysisOverview(input({ aggregation: true, baseline: 'partial' })); expect(partial.actions.evaluate[0]).toMatchObject({ status: 'review-only', reasonCodes: ['policy-action-baseline-analysis-partial'] }); const missing = buildPolicyAnalysisOverview(input({ aggregation: true, baseline: 'missing' })); expect(missing.actions.evaluate[0]).toMatchObject({ status: 'blocked' }); expect(missing.actions.evaluate[0].reasonCodes).toContain('policy-action-baseline-no-match'); }); it('keeps a partial evaluation review-only at the Finding Factory boundary', () => { const overview = buildPolicyAnalysisOverview(input({ aggregation: true, baseline: 'complete', evaluation: true })); expect(overview.actions.evaluate[0]).toMatchObject({ status: 'completed', existingRunId: 'evaluation-1' }); expect(overview.actions.createFindings).toEqual([expect.objectContaining({ status: 'review-only', evaluationRunId: 'evaluation-1', eligibleResultCount: 0, reasonCodes: ['policy-action-evaluation-partial'] })]); }); });