87 lines
2.9 KiB
Python
87 lines
2.9 KiB
Python
from __future__ import annotations
|
|
|
|
import asyncio
|
|
from typing import List
|
|
|
|
import httpx
|
|
from fastapi import FastAPI
|
|
from fastapi.testclient import TestClient
|
|
|
|
from services.api import app as api_app
|
|
from services.analytics import app as analytics_app
|
|
from services.game import app as game_app
|
|
|
|
|
|
def _install_asgi_clients() -> List[httpx.AsyncClient]:
|
|
created: List[httpx.AsyncClient] = []
|
|
|
|
def make_client(app: FastAPI, base_url: str) -> httpx.AsyncClient:
|
|
client = httpx.AsyncClient(transport=httpx.ASGITransport(app=app), base_url=base_url)
|
|
created.append(client)
|
|
return client
|
|
|
|
api_app.clients["game"] = make_client(game_app.app, "http://game")
|
|
api_app.clients["analytics"] = make_client(analytics_app.app, "http://analytics")
|
|
|
|
dummy_ai = FastAPI()
|
|
|
|
@dummy_ai.get("/models")
|
|
def _models():
|
|
return {"models": []}
|
|
|
|
@dummy_ai.post("/act")
|
|
def _act():
|
|
return {"action": {"type": "end_turn", "payload": {}}, "debug": {}}
|
|
|
|
api_app.clients["ai"] = make_client(dummy_ai, "http://ai")
|
|
return created
|
|
|
|
|
|
def _close_clients(clients: List[httpx.AsyncClient]) -> None:
|
|
for client in clients:
|
|
try:
|
|
loop = asyncio.get_event_loop()
|
|
except RuntimeError:
|
|
asyncio.run(client.aclose())
|
|
else:
|
|
loop.run_until_complete(client.aclose())
|
|
|
|
|
|
def test_full_user_flow() -> None:
|
|
with TestClient(api_app.app) as client:
|
|
created = _install_asgi_clients()
|
|
try:
|
|
# Register + login
|
|
response = client.post("/api/auth/register", json={"username": "user_flow", "password": "secret"})
|
|
assert response.status_code == 200
|
|
token = response.json()["token"]
|
|
headers = {"Authorization": f"Bearer {token}"}
|
|
|
|
# Create lobby and seat host
|
|
response = client.post("/api/games", json={"name": "Flow", "max_players": 3}, headers=headers)
|
|
assert response.status_code == 200
|
|
game_id = response.json()["id"]
|
|
|
|
response = client.post(f"/api/games/{game_id}/join", headers=headers)
|
|
assert response.status_code == 200
|
|
payload = response.json()
|
|
assert payload["players"][0]["name"] == "user_flow"
|
|
|
|
# Seat AI opponent and start the game
|
|
for _ in range(2):
|
|
response = client.post(
|
|
f"/api/games/{game_id}/add-ai",
|
|
json={"ai_type": "random"},
|
|
headers=headers,
|
|
)
|
|
assert response.status_code == 200
|
|
|
|
response = client.post(f"/api/games/{game_id}/start", headers=headers)
|
|
assert response.status_code == 200
|
|
state = response.json()
|
|
assert state["status"] == "running"
|
|
assert state["game"]["phase"] == "setup_round_one"
|
|
assert len(state["legal_actions"]) > 0
|
|
finally:
|
|
_close_clients(created)
|