import { describe, expect, it, vi } from 'vitest'; import type { UnifiedResultProjection } from '../../src/domain/unified-result'; import { buildUnifiedResultJsonl, queryAllUnifiedResults, RESULT_DB_JSONL_FORMAT, RESULT_DB_JSONL_SCHEMA_VERSION, unifiedResultJsonlFileName } from '../../src/exports/unified-result-jsonl'; function result(id: string): UnifiedResultProjection { return { resultProjectionId: id, sourceKind: 'scanner-finding', sourceResultId: `source-${id}`, projectId: 'project-1', assessmentId: 'assessment-1', collectionRunId: 'scan-1', scanRunId: 'scan-1', title: `Synthetic result ${id}`, severityOriginal: 'high', severityNormalized: 'high', outcomeOriginal: 'fail', outcomeNormalized: 'fail', technicalExecutionState: 'completed', resultType: 'compliance_check', isIoe: false, isDeviation: true, lifecycleState: 'unknown', mappingConfidence: 1, reviewStatus: 'unreviewed', importedAt: '2026-09-03T10:00:00.000Z', createdAt: '2026-09-03T10:00:00.000Z', categories: [] }; } describe('filtered Result DB JSONL export', () => { it('writes an explicit manifest followed by one complete JSON object per filtered result', () => { const text = buildUnifiedResultJsonl({ projectId: 'project-1', scanRunIds: ['scan-1'], deviation: true, severity: ['critical', 'high'], search: 'synthetic', offset: 50, limit: 50 }, [result('result-1'), result('result-2')], '2026-09-03T12:34:56.789Z'); const lines = text.trimEnd().split('\n').map(line => JSON.parse(line)); expect(lines[0]).toEqual({ recordType: 'manifest', format: RESULT_DB_JSONL_FORMAT, schemaVersion: RESULT_DB_JSONL_SCHEMA_VERSION, generatedAt: '2026-09-03T12:34:56.789Z', resultCount: 2, scope: { projectId: 'project-1', scanRunIds: ['scan-1'] }, filters: { deviation: true, severity: ['critical', 'high'], search: 'synthetic' } }); expect(lines.slice(1)).toEqual([ { recordType: 'result', position: 1, result: result('result-1') }, { recordType: 'result', position: 2, result: result('result-2') } ]); expect(text.endsWith('\n')).toBe(true); expect(unifiedResultJsonlFileName('2026-09-03T12:34:56.789Z')) .toBe('assessor-result-db-filtered-2026-09-03T12-34-56Z.jsonl'); }); it('loads every filtered page with the same scope and rejects a changing result set', async () => { const all = [result('result-1'), result('result-2'), result('result-3')]; const reader = vi.fn(async query => ({ total: all.length, items: all.slice(query.offset ?? 0, (query.offset ?? 0) + (query.limit ?? all.length)) })); await expect(queryAllUnifiedResults(reader, { projectId: 'project-1', scanRunIds: ['scan-1'], deviation: true, offset: 99, limit: 1 }, 2)).resolves.toEqual(all); expect(reader).toHaveBeenNthCalledWith(1, { projectId: 'project-1', scanRunIds: ['scan-1'], deviation: true, offset: 0, limit: 2 }); expect(reader).toHaveBeenNthCalledWith(2, { projectId: 'project-1', scanRunIds: ['scan-1'], deviation: true, offset: 2, limit: 2 }); let call = 0; await expect(queryAllUnifiedResults(async query => { call += 1; return { total: call === 1 ? 2 : 3, items: [result(`result-${query.offset ?? 0}`)] }; }, { deviation: true }, 1)).rejects.toThrow('changed during export'); }); });