agent-swarm-workbench / tests_python /test_integration.py
Kiy-K's picture
Restore full Space app with bucket model support
31c8075 verified
Raw
History Blame Contribute Delete
5.94 kB
"""Integration tests: real HTTP layer with real sandbox, stores, and validation."""
import asyncio
import httpx
import pytest
from arena.api import app, service
from arena.codebase_archive import LocalCodebaseArchiveStore
from arena.run_models import RunRequest
from arena.run_store import InMemoryRunStore
from arena.swarm_runtime import SwarmRuntime
from arena.validator_graph import DeterministicValidatorExecutor, ValidatorGraph
from conftest import make_local_session
def request(method: str, path: str, **kwargs) -> httpx.Response:
async def _request() -> httpx.Response:
transport = httpx.ASGITransport(app=app)
async with httpx.AsyncClient(transport=transport, base_url="http://testserver") as client:
return await client.request(method, path, **kwargs)
return asyncio.run(_request())
@pytest.fixture(autouse=True)
def _reset_service() -> None:
from arena.event_bus import EventBus
store = LocalCodebaseArchiveStore()
event_bus = EventBus()
service._run_store = InMemoryRunStore()
service._archive_store = store
service._swarm_runtime = SwarmRuntime(
session_factory=make_local_session,
archive_store=store,
event_bus=event_bus,
)
service._validator_graph = ValidatorGraph(
executor=DeterministicValidatorExecutor(),
rubric_enabled=False,
)
from arena.run_flow import RunFlow
service._run_flow = RunFlow(
run_store=service._run_store,
swarm_runtime=service._swarm_runtime,
validator_graph=service._validator_graph,
archive_store=service._archive_store,
event_bus=event_bus,
)
def test_health_endpoint_returns_ok() -> None:
response = request("GET", "/health")
assert response.status_code == 200
assert response.json() == {"status": "ok"}
def test_skills_endpoint_returns_list() -> None:
response = request("GET", "/skills")
assert response.status_code == 200
skills = response.json()
assert isinstance(skills, list)
def test_create_run_and_get_status() -> None:
response = request(
"POST",
"/runs",
json={"prompt": "Build a CLI", "user_tests": ["echo ok"]},
)
assert response.status_code == 200
data = response.json()
assert "token" not in data
run_id = data["id"]
status_resp = request("GET", f"/runs/{run_id}")
assert status_resp.status_code == 200
run = status_resp.json()
assert run["id"] == run_id
assert run["prompt"] == "Build a CLI"
assert run["status"] == "completed"
assert len(run["tasks"]) >= 1
assert run["codebase_archive"] is not None
assert run["validation_report"] is not None
def test_rejoin_run() -> None:
response = request(
"POST",
"/runs",
json={"prompt": "Build a CLI", "user_tests": []},
)
run_id = response.json()["id"]
access = service._run_store.create_run(RunRequest(prompt="Private rejoin"))
rejoin_resp = request("POST", "/runs/rejoin", json={"token": access.token})
assert rejoin_resp.status_code == 200
assert "token" not in rejoin_resp.json()
assert rejoin_resp.json()["id"] == access.run.id
assert rejoin_resp.json()["id"] != run_id
def test_validate_run() -> None:
response = request(
"POST",
"/runs",
json={"prompt": "Build a CLI", "user_tests": ["echo ok"]},
)
run_id = response.json()["id"]
validate_resp = request("POST", f"/runs/{run_id}/validate")
assert validate_resp.status_code == 200
report = validate_resp.json()
assert report["passed"] is True
assert report["run_id"] == run_id
final = request("GET", f"/runs/{run_id}")
assert final.json()["status"] == "completed"
assert final.json()["validation_report"] is not None
def test_download_codebase_zip() -> None:
response = request(
"POST",
"/runs",
json={"prompt": "Build a CLI", "user_tests": []},
)
run_id = response.json()["id"]
zip_resp = request("GET", f"/runs/{run_id}/codebase.zip")
assert zip_resp.status_code == 200
assert zip_resp.headers["content-type"] == "application/zip"
assert len(zip_resp.content) > 0
assert zip_resp.content[:2] == b"PK"
def test_start_run_nonblocking() -> None:
import time
response = request(
"POST",
"/runs/start",
json={"prompt": "Build a CLI", "user_tests": ["echo ok"]},
)
assert response.status_code == 200
run_id = response.json()["id"]
assert response.json()["status"] in ("queued", "planning", "working", "validating", "completed")
time.sleep(0.2)
final = request("GET", f"/runs/{run_id}")
assert final.json()["status"] in ("working", "validating", "completed")
def test_cancel_run() -> None:
response = request(
"POST",
"/runs",
json={"prompt": "Build a CLI", "user_tests": []},
)
run_id = response.json()["id"]
cancel_resp = request("POST", f"/runs/{run_id}/cancel")
assert cancel_resp.status_code == 200
assert cancel_resp.json()["status"] == "completed"
def test_add_run_message() -> None:
response = request(
"POST",
"/runs",
json={"prompt": "Build a CLI", "user_tests": []},
)
run_id = response.json()["id"]
message_resp = request(
"POST",
f"/runs/{run_id}/messages",
json={"content": "Please keep this active"},
)
assert message_resp.status_code == 200
assert "token" not in message_resp.json()
assert message_resp.json()["events"][-1]["message"] == "User: Please keep this active"
def test_run_not_found_returns_404() -> None:
response = request("GET", "/runs/nonexistent")
assert response.status_code == 404
def test_rejoin_bad_token_returns_404() -> None:
response = request("POST", "/runs/rejoin", json={"token": "not-a-real-token"})
assert response.status_code == 404