"""Le service n'est jamais public : sans le jeton de service, 401 partout (la santé exceptée — sonde d'infra qui ne révèle rien).""" from fastapi.testclient import TestClient from siop_ai.app import app def test_sante_publique_interne(): reponse = _client_sans_db().get("/healthz") assert reponse.status_code == 200 assert reponse.json()["service"] == "siop2-ai" def test_endpoints_internes_refuses_sans_jeton(): client = _client_sans_db() assert client.post("/internal/reindex").status_code == 401 assert client.post("/internal/search", json={"question": "couple de serrage ?"}).status_code == 401 assert client.post("/internal/transcrire", files={"fichier": ("a.m4a", b"x")}).status_code == 401 def test_transcription_off_par_defaut_503(): """Dictée pas activée (AI_TRANSCRIPTION=off, défaut) : refus propre, jamais un 500 — même contrat que le service IA éteint côté NestJS.""" reponse = _client_sans_db().post( "/internal/transcrire", files={"fichier": ("note.m4a", b"faux-audio")}, headers={"X-Service-Token": "dev-only-ai-token"}, ) assert reponse.status_code == 503 def test_transcription_deterministe_retourne_un_texte(): from siop_ai.transcription import TranscripteurDeterministe client = _client_sans_db() app.state.transcripteur = TranscripteurDeterministe() reponse = client.post( "/internal/transcrire", files={"fichier": ("note.m4a", b"faux-audio")}, headers={"X-Service-Token": "dev-only-ai-token"}, ) assert reponse.status_code == 200 assert "10 octets" in reponse.json()["texte"] assert ".m4a" in reponse.json()["texte"] def test_question_trop_courte_rejetee_avant_tout(): reponse = _client_sans_db().post( "/internal/search", json={"question": "ab"}, headers={"X-Service-Token": "dev-only-ai-token"}, ) assert reponse.status_code == 422 def _client_sans_db() -> TestClient: """TestClient HORS gestionnaire de contexte : le lifespan (pool DB, modèle d'embeddings) ne tourne pas — on pose l'état minimal. Les tests d'intégration DB se font en local (recette), pas en CI (convention R5.1).""" from siop_ai.config import charger_reglages from siop_ai.transcription import construire_transcripteur reglages = charger_reglages() app.state.reglages = reglages app.state.transcripteur = construire_transcripteur( reglages.ai_transcription, reglages.ai_transcription_model ) return TestClient(app, raise_server_exceptions=False)