import json import httpx import pytest from ai_platform.infrastructure.openai_compatible_scoring import OpenAICompatibleScoringGateway from ai_platform.lead_scoring.application.ai_provider import AIProviderFailure def _completion(content: str) -> httpx.Response: return httpx.Response(200, json={"choices": [{"message": {"content": content}}]}) @pytest.mark.asyncio async def test_compatible_adapter_accepts_json_fence_without_request_vkey(): requests: list[httpx.Request] = [] def handler(request: httpx.Request) -> httpx.Response: requests.append(request) assert "authorization" not in request.headers assert json.loads(request.content)["model"] == "gemini-3.5-flash-lite" return _completion('```json\n{"items":[]}\n```') http = httpx.AsyncClient(transport=httpx.MockTransport(handler)) provider = OpenAICompatibleScoringGateway("http://127.0.0.1:8317", None, http) try: evidence = await provider.extract_evidence( model="gemini-3.5-flash-lite", snapshot={}, vkey="", timeout=7 ) finally: await http.aclose() assert evidence == [] assert len(requests) == 1 @pytest.mark.parametrize( ("response", "error_code"), [ ( _completion('{"score":80,"score":1,"confidence":0.8,"reasoning":"a"}'), "openai_invalid_response", ), (_completion('{"score":"80","confidence":0.8,"reasoning":"a"}'), "openai_invalid_score"), (httpx.Response(429, text="sensitive upstream error"), "openai_http_error"), ], ) @pytest.mark.asyncio async def test_compatible_adapter_rejects_unsafe_outputs(response: httpx.Response, error_code: str): http = httpx.AsyncClient(transport=httpx.MockTransport(lambda _: response)) provider = OpenAICompatibleScoringGateway("https://proxy.example", "test-key", http) try: with pytest.raises(AIProviderFailure) as error: await provider.score( model="ignored", system_prompt="system", user_prompt="user", vkey="", timeout=7 ) finally: await http.aclose() assert error.value.error_code == error_code assert "sensitive upstream error" not in str(error.value)