import json import httpx import pytest from django.test import override_settings from coulomb_social.apps.identity.user_engine import ( HttpUserEngineClient, IdentityClaims, StubUserEngineClient, get_user_engine_client, ) def test_stub_is_deterministic(): c = StubUserEngineClient() claims = IdentityClaims(issuer="https://iss", subject="sub-1", name="A") a = c.link_or_create(claims, tenant_id="tenant:coulomb", application_id="coulomb-social") b = c.link_or_create(claims, tenant_id="tenant:coulomb", application_id="coulomb-social") assert a.user_id == b.user_id assert a.source == "stub" def test_http_client_calls_me(httpx_mock=None): """Manual transport mock without pytest-httpx plugin.""" claims = IdentityClaims( issuer="https://kc.coulomb.social", subject="sub-http", name="Http User", email="h@example.com", tenant="tenant:coulomb", principal_type="human", roles=("user",), authorized_party="coulomb-social", ) def handler(request: httpx.Request) -> httpx.Response: assert request.url.path == "/api/v1/me" assert request.headers["X-User-Engine-Proxy-Secret"] == "secret-value-at-least-24-chars" raw = json.loads(request.headers["X-Verified-Oidc-Claims"]) assert raw["iss"] == claims.issuer assert raw["sub"] == claims.subject assert raw["tenant"] == "tenant:coulomb" assert "user-engine-portal" in raw["aud"] assert "coulomb-social" in raw["aud"] return httpx.Response( 200, json={ "user": { "user_id": "usr_test_123", "display_name": "Http User", "primary_email": "h@example.com", }, "actor": {"tenant": "tenant:coulomb", "subject": claims.subject}, "account": {}, "identities": [], }, ) transport = httpx.MockTransport(handler) client = HttpUserEngineClient("https://users.example.test", "secret-value-at-least-24-chars") # inject transport by patching Client used inside method import coulomb_social.apps.identity.user_engine as ue real_client = httpx.Client def client_factory(*args, **kwargs): kwargs["transport"] = transport return real_client(*args, **kwargs) original = ue.httpx.Client ue.httpx.Client = client_factory # type: ignore[misc] try: link = client.link_or_create( claims, tenant_id="tenant:coulomb", application_id="coulomb-social" ) finally: ue.httpx.Client = original # type: ignore[misc] assert link.user_id == "usr_test_123" assert link.source == "http" assert link.display_name == "Http User" @override_settings(USER_ENGINE_BASE_URL="", USER_ENGINE_PROXY_SECRET="") def test_get_client_stub_when_unconfigured(): assert isinstance(get_user_engine_client(), StubUserEngineClient) @override_settings( USER_ENGINE_BASE_URL="https://users.example.test", USER_ENGINE_PROXY_SECRET="secret-value-at-least-24-chars", ) def test_get_client_http_when_configured(): assert isinstance(get_user_engine_client(), HttpUserEngineClient)