Assessor_2.0/tests/reporting/report-engine-invariance.te...

45 lines
2.8 KiB
TypeScript

import { describe, expect, it, vi } from 'vitest';
import { reportContext } from './context-report-fixture';
import { makeSheet } from '../../src/importers/sheet-factory';
import { loadCanonicalProjectWorkspace } from '../../src/features/project-import/load-canonical-project-workspace';
import { LocalAssessorRepository } from '../../src/persistence/local-assessor-repository';
import { reportReadPortFrom } from '../../src/reporting/report-read-port';
import { createReportRun } from '../../src/reporting/report-run';
// Only the workspace loader is synthetic, so the run reaches the projection; every read of stored
// data goes to the real repository through the engine's read-only port.
vi.mock('../../src/features/project-import/load-canonical-project-workspace', () => ({
loadCanonicalProjectWorkspace: vi.fn()
}));
// Permanent on/off invariance of the Report Engine (AGENTS.md, "Core Engine and engines"): the Core
// works unchanged with the engine switched off, and switching it on - running a report - leaves
// every stored ASSESSOR value and the repository revision exactly as they were. The Context Engine
// carries the same check in tests/assessment-context/context-boundary.test.ts.
describe('Report Engine on/off invariance', () => {
it('leaves every stored ASSESSOR value and the repository revision unchanged', async () => {
const sheet = makeSheet('Dummy', [['Title', 'Source: Scan'], ['Synthetic check', 'PingCastle']],
'', 'dummy.csv', { isProjectSheet: true });
vi.mocked(loadCanonicalProjectWorkspace).mockResolvedValue({
models: [], assessmentIds: ['dummy-assessment'],
dataset: { fileName: 'Dummy', sheets: [sheet], scanTool: 'PingCastle' } as never
});
const repository = new LocalAssessorRepository();
const timestamp = '2026-10-01T08:00:00.000Z';
await repository.saveProject({ id: 'dummy-project', name: 'Dummy Customer', createdAt: timestamp, updatedAt: timestamp, attributes: {} });
await repository.saveAssessment({ id: 'dummy-assessment', projectId: 'dummy-project', name: 'Dummy', createdAt: timestamp, updatedAt: timestamp });
const off = { revision: repository.revision, data: JSON.stringify(await repository.exportProject('dummy-project')) };
const run = await createReportRun(reportReadPortFrom(repository, async () => repository.revision),
{ projectId: 'dummy-project', assessmentIds: ['dummy-assessment'], generatedAt: timestamp },
{ readContext: async () => reportContext(repository.revision) });
// The engine really ran: both report files were rendered from the stored state.
expect(run.files.management.length).toBeGreaterThan(0);
expect(run.files.technical.length).toBeGreaterThan(0);
expect(run.revision).toBe(off.revision);
expect(repository.revision).toBe(off.revision);
expect(JSON.stringify(await repository.exportProject('dummy-project'))).toBe(off.data);
});
});