polyglot-alpha / tests /test_operators_api.py
licaomeng
deploy: main@8970ffb → HF Spaces (2026-05-27T05:19Z)
88d2f2a
"""Integration tests for the /api/operators routes."""
from __future__ import annotations
from unittest.mock import patch
import pytest
from fastapi.testclient import TestClient
from polyglot_alpha.api.main import create_app
@pytest.fixture()
def client(isolated_db) -> TestClient:
"""Create a TestClient with an isolated SQLite DB."""
app = create_app()
return TestClient(app)
def _stub_chain_register(*_args, **_kwargs):
return {"stake_tx": "0xabc123stake", "register_tx": "0xdef456register"}
def test_register_operator_creates_row_and_returns_seed_repuration(
client: TestClient,
) -> None:
with patch(
"polyglot_alpha.api.routes.operators._try_register_on_chain",
side_effect=_stub_chain_register,
):
resp = client.post(
"/api/operators/register",
json={
"operator_address": "0xtestop001",
"display_name": "Test Operator",
"signature": "0xdeadbeef",
},
)
assert resp.status_code == 200, resp.text
body = resp.json()
assert body["status"] == "registered"
assert body["stake_tx"] == "0xabc123stake"
assert body["reputation_tx"] == "0xdef456register"
assert body["initial_reputation"] == 0.7
assert body["auction_stream_url"] == "/sse/auctions"
assert body["operator_address"] == "0xtestop001"
def test_register_operator_idempotent_for_new_address(client: TestClient) -> None:
"""Re-registering an address with 0 bids/wins is allowed (only commits one row)."""
with patch(
"polyglot_alpha.api.routes.operators._try_register_on_chain",
side_effect=_stub_chain_register,
):
client.post(
"/api/operators/register",
json={
"operator_address": "0xtestop002",
"display_name": "Test 2",
"signature": "0xab",
},
)
# Second call with no bids -> not yet 409.
resp = client.post(
"/api/operators/register",
json={
"operator_address": "0xtestop002",
"display_name": "Test 2",
"signature": "0xab",
},
)
assert resp.status_code == 200
def test_list_operators_returns_seeders_and_externals(client: TestClient) -> None:
with patch(
"polyglot_alpha.api.routes.operators._try_register_on_chain",
side_effect=_stub_chain_register,
):
client.post(
"/api/operators/register",
json={
"operator_address": "0xtestop003",
"display_name": "External",
"signature": "0xab",
},
)
resp = client.get("/api/operators")
assert resp.status_code == 200
operators = resp.json()
assert isinstance(operators, list)
# The external operator we just registered must appear with kind=external.
matches = [o for o in operators if o["address"] == "0xtestop003"]
assert len(matches) == 1
assert matches[0]["kind"] == "external"
def test_get_operator_returns_arc_explorer_url(client: TestClient) -> None:
with patch(
"polyglot_alpha.api.routes.operators._try_register_on_chain",
side_effect=_stub_chain_register,
):
client.post(
"/api/operators/register",
json={
"operator_address": "0xtestop004",
"display_name": "Lookup Target",
"signature": "0xab",
},
)
resp = client.get("/api/operators/0xtestop004")
assert resp.status_code == 200
body = resp.json()
assert "arc_explorer_url" in body
assert "testnet.arc.network" in body["arc_explorer_url"]
assert body["kind"] == "external"
assert body["reputation"] == 0.7
def test_get_unknown_operator_returns_404(client: TestClient) -> None:
resp = client.get("/api/operators/0xdoesnotexist1234567890abcdef12345678")
assert resp.status_code == 404
def test_register_operator_mock_mode_returns_sim_tx_and_no_chain_call(
client: TestClient,
) -> None:
"""Mock mode must skip the chain helper and return ``0xsim_`` tx hashes."""
with patch(
"polyglot_alpha.api.routes.operators._try_register_on_chain"
) as chain_mock:
resp = client.post(
"/api/operators/register",
json={
"operator_address": "0xtestop900",
"display_name": "Mock Operator",
"model_label": "claude-opus-4-7",
"languages": ["zh", "ja"],
"stake_amount_usdc": 100.0,
"mode": "mock",
},
)
assert resp.status_code == 200, resp.text
body = resp.json()
assert body["is_simulated"] is True
assert body["success"] is True
assert body["stake_tx"].startswith("0xsim_")
assert body["reputation_tx"].startswith("0xsim_")
assert body["registration_id"].startswith("reg_")
chain_mock.assert_not_called()
def test_register_operator_rejects_unknown_language(client: TestClient) -> None:
resp = client.post(
"/api/operators/register",
json={
"operator_address": "0xtestop901",
"display_name": "Bad Langs",
"languages": ["zh", "klingon"],
"mode": "mock",
},
)
assert resp.status_code == 422
assert "unsupported_language_codes" in resp.text
def test_pending_fees_returns_cumulative_for_operator(
client: TestClient, isolated_db
) -> None:
"""``/operators/{addr}/pending-fees`` mirrors AgentReputation.cumulative_fees."""
from datetime import datetime, timezone
from polyglot_alpha.persistence.db import session_scope
from polyglot_alpha.persistence.models import AgentReputation
addr = "0xtestop910"
with session_scope() as s:
s.add(
AgentReputation(
agent_address=addr,
avg_quality=0.8,
cumulative_fees=42.5,
last_updated=datetime.now(timezone.utc),
)
)
resp = client.get(f"/api/operators/{addr}/pending-fees")
assert resp.status_code == 200, resp.text
body = resp.json()
assert body["operator_address"] == addr
assert body["pending_usdc"] == 42.5
assert body["event_count"] == 0
def test_claim_fees_mock_mode_zeros_balance_and_returns_sim_tx(
client: TestClient, isolated_db
) -> None:
from datetime import datetime, timezone
from polyglot_alpha.persistence.db import session_scope
from polyglot_alpha.persistence.models import AgentReputation
addr = "0xtestop911"
with session_scope() as s:
s.add(
AgentReputation(
agent_address=addr,
avg_quality=0.8,
cumulative_fees=17.25,
last_updated=datetime.now(timezone.utc),
)
)
resp = client.post(
f"/api/operators/{addr}/claim-fees",
json={"mode": "mock"},
)
assert resp.status_code == 200, resp.text
body = resp.json()
assert body["success"] is True
assert body["is_simulated"] is True
assert body["amount_claimed_usdc"] == 17.25
assert body["tx_hash"].startswith("0xsim_")
# Subsequent claim should be a no-op.
follow = client.post(
f"/api/operators/{addr}/claim-fees",
json={"mode": "mock"},
)
assert follow.status_code == 200
assert follow.json()["success"] is False
assert follow.json()["amount_claimed_usdc"] == 0.0
def test_claim_fees_returns_404_for_unknown_operator(client: TestClient) -> None:
resp = client.post(
"/api/operators/0xnotanoperator9999999999999999999999999/claim-fees",
json={"mode": "mock"},
)
assert resp.status_code == 404
def test_relay_bid_endpoint_is_phase_2_stub(client: TestClient) -> None:
resp = client.post(
"/api/auctions/evt-42/bid",
json={
"operator_address": "0xtestop005",
"bid_amount_usdc": 1.25,
"candidate_hash": "0x" + "ab" * 32,
"signature": "0xsig",
},
)
assert resp.status_code == 200
body = resp.json()
assert body["status"] == "phase_2_stub"
assert body["tx_hash"] is None