from __future__ import annotations import httpx import pytest from app.crm import CrmClient, CrmOutcome def make_client(handler) -> CrmClient: client = CrmClient.__new__(CrmClient) client._base_url = "https://portal.example/rest/1/token/" client._host = "portal.example" client._client = httpx.AsyncClient( transport=httpx.MockTransport(handler), follow_redirects=False ) return client @pytest.mark.asyncio async def test_crm_success_and_no_redirect() -> None: client = make_client( lambda request: httpx.Response(200, json={"result": {"ID": "42"}}, request=request) ) result = await client.call("crm.contact.get", {"id": "42"}, mutating=False) assert result.outcome == CrmOutcome.SUCCEEDED assert result.result["ID"] == "42" await client.close() redirecting = make_client( lambda request: httpx.Response( 302, headers={"Location": "https://evil.example/"}, request=request ) ) result = await redirecting.call("crm.contact.get", {"id": "42"}, mutating=False) assert result.outcome == CrmOutcome.PERMANENT assert result.error_code == "crm_redirect_rejected" await redirecting.close() @pytest.mark.asyncio async def test_mutating_timeout_is_uncertain() -> None: def timeout(request): raise httpx.ReadTimeout("timed out", request=request) client = make_client(timeout) result = await client.call("crm.contact.add", {"fields": {}}, mutating=True) assert result.outcome == CrmOutcome.UNCERTAIN await client.close()