"""Tests pour la génération de contre-argumentation CPAM.""" from unittest.mock import patch import pytest from src.config import ControleCPAM, Diagnostic, DossierMedical, RAGSource, Sejour from src.control.cpam_response import _build_cpam_prompt, _format_response, generate_cpam_response def _make_dossier() -> DossierMedical: """Crée un dossier médical de test.""" return DossierMedical( source_file="test.pdf", document_type="crh", sejour=Sejour(sexe="M", age=65, duree_sejour=5), diagnostic_principal=Diagnostic( texte="Cholécystite aiguë", cim10_suggestion="K81.0", ), diagnostics_associes=[ Diagnostic(texte="Iléus réflexe", cim10_suggestion="K56.0"), ], ) def _make_controle() -> ControleCPAM: """Crée un contrôle CPAM de test.""" return ControleCPAM( numero_ogc=17, titre="Désaccord sur les DAS", arg_ucr="L'UCR confirme l'avis des médecins contrôleurs au motif que le DAS K56.0 n'est pas justifié.", decision_ucr="UCR confirme avis médecins contrôleurs", dp_ucr=None, da_ucr="K56.0", ) class TestBuildPrompt: def test_prompt_contains_dossier_info(self): dossier = _make_dossier() controle = _make_controle() prompt = _build_cpam_prompt(dossier, controle, []) assert "Cholécystite aiguë" in prompt assert "K81.0" in prompt assert "Iléus réflexe" in prompt assert "65 ans" in prompt def test_prompt_contains_cpam_argument(self): dossier = _make_dossier() controle = _make_controle() prompt = _build_cpam_prompt(dossier, controle, []) assert controle.arg_ucr in prompt assert controle.decision_ucr in prompt def test_prompt_contains_codes_contestes(self): dossier = _make_dossier() controle = _make_controle() prompt = _build_cpam_prompt(dossier, controle, []) assert "DA proposés par UCR : K56.0" in prompt def test_prompt_contains_rag_sources(self): dossier = _make_dossier() controle = _make_controle() sources = [ {"document": "guide_methodo", "page": 64, "extrait": "Texte du guide..."}, {"document": "cim10", "code": "K56.0", "extrait": "Iléus paralytique..."}, ] prompt = _build_cpam_prompt(dossier, controle, sources) assert "Guide Méthodologique MCO 2026" in prompt assert "CIM-10 FR 2026" in prompt assert "page 64" in prompt class TestFormatResponse: def test_full_response(self): parsed = { "analyse_contestation": "La CPAM conteste le DAS K56.0", "points_accord": "Aucun", "contre_arguments": "Le guide méthodologique précise...", "references": "Guide métho p.64", "conclusion": "Le DAS est justifié", } text = _format_response(parsed) assert "ANALYSE DE LA CONTESTATION" in text assert "CONTRE-ARGUMENTS" in text assert "CONCLUSION" in text # "Aucun" ne doit pas générer la section points d'accord assert "POINTS D'ACCORD" not in text def test_partial_response(self): parsed = { "contre_arguments": "Arguments...", "conclusion": "Conclusion...", } text = _format_response(parsed) assert "CONTRE-ARGUMENTS" in text assert "CONCLUSION" in text def test_empty_response(self): text = _format_response({}) assert text == "" class TestGenerateResponse: @patch("src.control.cpam_response.call_ollama") @patch("src.control.cpam_response._search_rag_for_control") def test_generate_success(self, mock_rag, mock_ollama): mock_rag.return_value = [ {"document": "guide_methodo", "page": 64, "extrait": "Texte guide"}, ] mock_ollama.return_value = { "analyse_contestation": "Analyse...", "contre_arguments": "Contre-arguments...", "conclusion": "Conclusion...", } dossier = _make_dossier() controle = _make_controle() text, sources = generate_cpam_response(dossier, controle) assert "Contre-arguments..." in text assert len(sources) == 1 assert sources[0].document == "guide_methodo" mock_ollama.assert_called_once() @patch("src.control.cpam_response.call_ollama") @patch("src.control.cpam_response._search_rag_for_control") def test_generate_ollama_unavailable(self, mock_rag, mock_ollama): mock_rag.return_value = [] mock_ollama.return_value = None dossier = _make_dossier() controle = _make_controle() text, sources = generate_cpam_response(dossier, controle) assert text == "" assert sources == []