import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import os from 'os'; import path from 'path'; /** * Full pipeline test using mock providers + JSONL chunks. * Ensures we can run a question-first batch without real LLMs or ES. */ describe('full pipeline (mock providers)', () => { beforeEach(() => { vi.resetModules(); process.env.PIPELINE_CHUNK_SOURCE = 'jsonl'; process.env.GENERATOR_PROVIDER = 'mock'; process.env.VERIFIER_PROVIDER = 'mock'; process.env.REWARD_PROVIDER = 'mock'; process.env.QUESTION_PROVIDER = 'mock'; process.env.PIPELINE_CACHE_DIR = path.join( os.tmpdir(), `cache-${Date.now()}`, ); }); afterEach(() => { delete process.env.PIPELINE_CHUNK_SOURCE; delete process.env.GENERATOR_PROVIDER; delete process.env.VERIFIER_PROVIDER; delete process.env.REWARD_PROVIDER; delete process.env.QUESTION_PROVIDER; delete process.env.PIPELINE_CACHE_DIR; vi.restoreAllMocks(); vi.unmock('../src/retrieval/jsonl_chunks.mjs'); }); it('processes mock chunks end-to-end and writes accepted samples', async () => { // Mock chunk loader to avoid filesystem dependency vi.doMock('../src/retrieval/jsonl_chunks.mjs', () => ({ loadRagChunks: vi.fn(async () => [ { id: 'chunk-1', content: 'Mock content A' }, { id: 'chunk-2', content: 'Mock content B' }, ]), })); // Ensure no accidental ES calls vi.doMock('../src/retrieval/retrieval.mjs', () => ({ fetchChunksFromIndex: vi.fn(), })); // Mock verifier to return JSON with SCORE vi.doMock('../src/providers/provider.mjs', () => ({ loadProviderFor: (stage) => { if (stage === 'verifier') { return { generate: async () => JSON.stringify({ REASONING: ['supported'], SCORE: 0.9, }), }; } if (stage === 'reward') return { generate: async () => '0.9 good' }; if (stage === 'question') return { generate: async () => JSON.stringify({ questions: ['Q1?', 'Q2?', 'Q3?'] }), }; return { generate: async () => 'tanswer' }; }, })); const { runPipelineBatch } = await import('../src/pipeline/batch.mjs'); const outPath = path.join(os.tmpdir(), `mock-pipeline-${Date.now()}.jsonl`); const result = await runPipelineBatch({ seedMode: 'question-first', limit: 3, // question cap outPath, verbose: false, logger: { log() {}, error() {} }, }); expect(result.mode).toBe('question-first'); expect(result.processed).toBe(3); expect(result.accepted).toBe(3); expect(result.statusCounts.accepted).toBe(3); }); });