import { describe, expect, it, vi } from 'vitest'; import { comparisonReadPortFrom, type ComparisonReadMethods } from '../../src/comparison/comparison-read-port'; // The engine port shares reads within one repository revision and never serves a read of an older revision. function repository() { return { getProject: vi.fn(async () => null), listAssessments: vi.fn(async () => []), loadAssessmentModel: vi.fn(async (id: string) => ({ id })), queryUnifiedResults: vi.fn(async () => ({ results: [] })), listPolicyEvaluations: vi.fn(async () => []), listGpoBackupInstances: vi.fn(async () => []) }; } describe('Comparison Engine read port', () => { it('loads each read once per revision, also for parallel requests of both timeslots', async () => { const source = repository(); const port = comparisonReadPortFrom(source as unknown as ComparisonReadMethods, async () => 1); await Promise.all([port.listPolicyEvaluations('p'), port.listPolicyEvaluations('p')]); const [a, b] = await Promise.all([port.loadAssessmentModel('a'), port.loadAssessmentModel('a')]); await port.loadAssessmentModel('b'); expect(source.listPolicyEvaluations).toHaveBeenCalledTimes(1); expect(source.loadAssessmentModel).toHaveBeenCalledTimes(2); expect(a).toBe(b); }); it('reloads after a committed change and does not keep a failed read', async () => { const source = repository(); let revision = 1; const port = comparisonReadPortFrom(source as unknown as ComparisonReadMethods, async () => revision); await port.loadAssessmentModel('a'); revision = 2; await port.loadAssessmentModel('a'); expect(source.loadAssessmentModel).toHaveBeenCalledTimes(2); source.listGpoBackupInstances.mockRejectedValueOnce(new Error('unavailable')); await expect(port.listGpoBackupInstances('p')).rejects.toThrow('unavailable'); await port.listGpoBackupInstances('p'); expect(source.listGpoBackupInstances).toHaveBeenCalledTimes(2); }); });