# tests/test_synthesizer.py """Tests for Synthesizer — mocked LLM, citation assembly.""" from __future__ import annotations from unittest.mock import MagicMock from app.services.retriever import RetrievedChunk from app.services.synthesizer import Synthesizer, SynthesisResult def _chunk(doc_id: str = "book-a", page: int = 5, text: str = "Fireball rules") -> RetrievedChunk: return RetrievedChunk( chunk_id="c1", doc_id=doc_id, page_number=page, text=text, bm25_score=1.0, vector_score=None, ) def test_synthesizer_returns_answer_and_citations(): mock_llm = MagicMock() mock_llm.complete.return_value = "Fireball deals 8d6 damage [p.5]." synth = Synthesizer(mock_llm) result = synth.synthesize( message="How does Fireball work?", history=[], chunks=[_chunk()], ) assert isinstance(result, SynthesisResult) assert "Fireball" in result.answer assert len(result.citations) == 1 assert result.citations[0].page_number == 5 assert result.citations[0].doc_id == "book-a" def test_synthesizer_builds_context_from_chunks(): mock_llm = MagicMock() mock_llm.complete.return_value = "Answer." synth = Synthesizer(mock_llm) synth.synthesize("Q?", [], [_chunk(text="Detailed rule text here.")]) assert "Detailed rule text here." in mock_llm.complete.call_args.args[0] def test_synthesizer_uses_system_prompt(): mock_llm = MagicMock() mock_llm.complete.return_value = "Answer." synth = Synthesizer(mock_llm) synth.synthesize("Q?", [], [_chunk()]) call_kwargs = mock_llm.complete.call_args assert call_kwargs.kwargs.get("system") or call_kwargs[1].get("system")