affix-huggingface / tests /test_transport.py
AffixIO's picture
Publish affix-huggingface 0.3.0
551b309 verified
Raw
History Blame Contribute Delete
3.25 kB
"""Transport contracts for the AffixIO production API client."""
# Credit: @paparichens
from __future__ import annotations
import httpx
import pytest
from affix_huggingface.errors import AffixAPIError
from affix_huggingface.transport import AffixTransport
def test_prove_sends_auth_idempotency_and_encoded_circuit() -> None:
captured: list[httpx.Request] = []
def handler(request: httpx.Request) -> httpx.Response:
captured.append(request)
return httpx.Response(
200,
json={"proof": "proof_hex"},
headers={"X-Request-Id": "req_1"},
)
http = httpx.Client(transport=httpx.MockTransport(handler))
transport = AffixTransport("aio_test", client=http)
data, request_id = transport.prove(
circuit_id="yes/no",
fields={"condition_greater1": True},
idempotency_key="idem_1",
)
assert data["proof"] == "proof_hex"
assert request_id == "req_1"
assert captured[0].url.raw_path == b"/v1/circuits/yes%2Fno/prove"
assert captured[0].headers["Authorization"] == "Bearer aio_test"
assert captured[0].headers["X-API-Key"] == "aio_test"
assert captured[0].headers["Idempotency-Key"] == "idem_1"
def test_gate_returns_structured_denial_from_403() -> None:
def handler(_: httpx.Request) -> httpx.Response:
return httpx.Response(
403,
json={
"allow": False,
"reason_code": "REGION_MISMATCH",
"receipt_id": "rcpt_denied",
},
)
http = httpx.Client(transport=httpx.MockTransport(handler))
transport = AffixTransport("aio_test", client=http)
data, _ = transport.gate(
proof="proof_hex",
circuit_id="yesno",
policy_id="gate.agent",
mode="consume",
gate_id="a" * 64,
idempotency_key="idem_gate",
)
assert data["allow"] is False
assert data["reason_code"] == "REGION_MISMATCH"
def test_retryable_response_is_retried(monkeypatch: pytest.MonkeyPatch) -> None:
attempts = 0
def handler(_: httpx.Request) -> httpx.Response:
nonlocal attempts
attempts += 1
if attempts == 1:
return httpx.Response(503, json={"error": "unavailable"})
return httpx.Response(200, json={"ok": True})
monkeypatch.setattr(AffixTransport, "_sleep", staticmethod(lambda *_: None))
http = httpx.Client(transport=httpx.MockTransport(handler))
transport = AffixTransport("aio_test", client=http, max_retries=1)
data, _ = transport.health()
assert data == {"ok": True}
assert attempts == 2
def test_non_retryable_error_preserves_api_fields() -> None:
def handler(_: httpx.Request) -> httpx.Response:
return httpx.Response(
401,
json={"error": "unauthorised", "message": "API key rejected"},
headers={"X-Request-Id": "req_auth"},
)
http = httpx.Client(transport=httpx.MockTransport(handler))
transport = AffixTransport("bad_key", client=http)
with pytest.raises(AffixAPIError) as exc:
transport.health()
assert exc.value.status_code == 401
assert exc.value.code == "unauthorised"
assert exc.value.request_id == "req_auth"