from __future__ import annotations import json import httpx from pingcap_datapipelines.nexuscrm_client import NexusCRMClient def test_client_authenticates_describes_and_upserts_collection() -> None: requests: list[httpx.Request] = [] def handler(request: httpx.Request) -> httpx.Response: requests.append(request) if request.url.path == "/services/oauth2/token": return httpx.Response( 200, json={"access_token": "token", "instance_url": "https://instance.example"}, ) assert request.headers["Authorization"] == "Bearer token" if request.url.path.endswith("/describe"): return httpx.Response(200, json={"fields": []}) if request.url.path.endswith("/query"): assert "Account_ID__c IN" in request.url.params["q"] return httpx.Response( 200, json={ "done": True, "records": [{"Id": "account-uuid", "Account_ID__c": "A-001"}], }, ) if request.method == "GET": assert request.url.params["ids"] == "001-a,001-b" assert request.url.params["fields"] == "Id" return httpx.Response( 200, json=[{"Id": "001-a", "attributes": {"type": "Account"}}, None], ) assert json.loads(request.content) == { "allOrNone": False, "records": [{"Outbound_Key__c": "key-1"}], } return httpx.Response(200, json=[{"id": "a0G-1", "success": True, "created": True, "errors": []}]) client = NexusCRMClient( base_url="https://login.example", client_id="client", client_secret="secret", transport=httpx.MockTransport(handler), ) try: assert client.describe_object("Month_End_ARR__c") == {"fields": []} retrieved = client.retrieve_collection(["001-a", "001-b"]) resolved = client.resolve_account_ids(["A-001", "A-missing"]) results = client.upsert_collection( object_name="Month_End_ARR__c", external_id_field="Outbound_Key__c", records=[{"Outbound_Key__c": "key-1"}], ) finally: client.close() assert len([request for request in requests if request.url.path == "/services/oauth2/token"]) == 1 assert retrieved[0] == {"Id": "001-a", "attributes": {"type": "Account"}} assert retrieved[1] is None assert resolved == {"A-001": "account-uuid"} assert results[0].id == "a0G-1" assert results[0].success is True assert results[0].created is True def test_client_retries_transient_http_failures() -> None: attempts = 0 sleeps: list[float] = [] def handler(request: httpx.Request) -> httpx.Response: nonlocal attempts if request.url.path == "/services/oauth2/token": return httpx.Response(200, json={"access_token": "token"}) attempts += 1 if attempts == 1: return httpx.Response(503, headers={"Retry-After": "3"}, json={"message": "busy"}) return httpx.Response(200, json={"fields": []}) client = NexusCRMClient( base_url="https://crm.example", client_id="client", client_secret="secret", transport=httpx.MockTransport(handler), sleeper=sleeps.append, ) try: client.describe_object("Month_End_ARR__c") finally: client.close() assert attempts == 2 assert sleeps == [3.0] def test_active_account_lookup_preserves_ambiguity_for_revenue_admission() -> None: seen_soql: list[str] = [] def handler(request: httpx.Request) -> httpx.Response: if request.url.path == "/services/oauth2/token": return httpx.Response(200, json={"access_token": "token", "instance_url": "https://instance.example"}) if request.url.path.endswith("/query"): soql = request.url.params["q"] seen_soql.append(soql) return httpx.Response( 200, json={ "done": True, "records": [ {"Id": "account-1", "Account_ID__c": "A-001"}, {"Id": "account-2", "Account_ID__c": "A-001"}, ], }, ) raise AssertionError(request.url) client = NexusCRMClient( base_url="https://login.example", client_id="client", client_secret="secret", transport=httpx.MockTransport(handler), ) try: matches = client.resolve_active_account_matches(["A-001", "A-missing"]) finally: client.close() assert matches == {"A-001": ["account-1", "account-2"], "A-missing": []} assert seen_soql and "IsDeleted = false" in seen_soql[0]