"""Tests for the gateway client.""" from __future__ import annotations import json from datetime import datetime, timezone import pytest import respx from httpx import Response from conduit_client import AsyncConduitClient, ConduitClient from conduit_client.models.common import CreateKeyRequest from conduit_client.models.gateway import AuditLogQuery @respx.mock def test_health(api_key: str) -> None: respx.get("https://api.example.com/health").mock(return_value=Response(200, text="ok")) with ConduitClient(api_key, base_url="https://api.example.com") as client: result = client.gateway.health() assert result == "ok" @respx.mock def test_me(api_key: str) -> None: respx.get("https://api.example.com/auth/me").mock( return_value=Response( 200, json={ "subject": "user:123", "actor_type": "user", "auth_method": "api_key", "scopes": ["gateway:read"], "grantable_scopes": ["gateway:read", "sms:send"], }, ) ) with ConduitClient(api_key, base_url="https://api.example.com") as client: result = client.gateway.me() assert result.subject == "user:123" assert result.scopes == ["gateway:read"] @respx.mock def test_services(api_key: str) -> None: respx.get("https://api.example.com/services").mock( return_value=Response( 200, json=[ {"id": "sms", "name": "SMS", "prefixes": ["/sms"], "enabled": True}, ], ) ) with ConduitClient(api_key, base_url="https://api.example.com") as client: result = client.gateway.services() assert len(result) == 1 assert result[0].id == "sms" @respx.mock def test_list_keys(api_key: str) -> None: created = datetime.now(timezone.utc).isoformat() respx.get("https://api.example.com/keys").mock( return_value=Response( 200, json=[ { "key_prefix": "abc123", "display_name": "test", "scopes": ["gateway:read"], "created_at": created, }, ], ) ) with ConduitClient(api_key, base_url="https://api.example.com") as client: result = client.gateway.list_keys() assert result[0].key_prefix == "abc123" @respx.mock def test_create_key(api_key: str) -> None: created = datetime.now(timezone.utc).isoformat() route = respx.post("https://api.example.com/keys").mock( return_value=Response( 200, json={ "key": "mega_sk_live_abc_secret", "key_prefix": "abc", "display_name": "new key", "scopes": ["sms:read"], "created_at": created, }, ) ) with ConduitClient(api_key, base_url="https://api.example.com") as client: result = client.gateway.create_key(CreateKeyRequest(display_name="new key", scopes=["sms:read"])) assert result.key == "mega_sk_live_abc_secret" assert json.loads(route.calls[0].request.content) == { "display_name": "new key", "scopes": ["sms:read"], } @respx.mock def test_revoke_key(api_key: str) -> None: respx.delete("https://api.example.com/keys/abc").mock(return_value=Response(204)) with ConduitClient(api_key, base_url="https://api.example.com") as client: result = client.gateway.revoke_key("abc") assert result is None @respx.mock def test_admin_audit(api_key: str) -> None: route = respx.get("https://api.example.com/admin/audit").mock( return_value=Response(200, json=[]) ) with ConduitClient(api_key, base_url="https://api.example.com") as client: result = client.gateway.admin_audit( AuditLogQuery(actor_subject="user:123", limit=50) ) assert result == [] assert route.calls[0].request.url.params["actor_subject"] == "user:123" assert route.calls[0].request.url.params["limit"] == "50" @pytest.mark.asyncio @respx.mock async def test_async_me(api_key: str) -> None: respx.get("https://api.example.com/auth/me").mock( return_value=Response( 200, json={ "subject": "user:123", "actor_type": "user", "auth_method": "api_key", "scopes": ["gateway:read"], "grantable_scopes": ["gateway:read", "sms:send"], }, ) ) async with AsyncConduitClient(api_key, base_url="https://api.example.com") as client: result = await client.gateway.me() assert result.subject == "user:123"