email-copilot-env / tests /test_api_contract.py
rogerdemello's picture
Allow OpenEnv reset POST without body
c265728
Raw History Blame Contribute Delete
4.02 kB
from fastapi.testclient import TestClient
from env.api import app
from env.environment import ExecutiveEmailEnv
from env.models import Action
client = TestClient(app)
def test_tasks_endpoint_and_persona_surface() -> None:
response = client.get("/tasks")
assert response.status_code == 200
payload = response.json()
assert len(payload["tasks"]) == 3
observation_schema = payload["observation_schema"]
assert "persona" in observation_schema["properties"]
assert "remaining_interruptions" in observation_schema["properties"]
def test_runtime_reset_step_state_endpoints() -> None:
reset_response = client.post(
"/reset",
json={
"task_id": "easy_classification",
"seed": 42,
"persona": "balanced",
},
)
assert reset_response.status_code == 200
observation = reset_response.json()
assert "emails" in observation
assert observation["persona"] == "balanced"
first_email_id = observation["emails"][0]["id"]
step_response = client.post(
"/step",
json={
"action_type": "classify",
"email_id": first_email_id,
"label": "normal",
},
)
assert step_response.status_code == 200
step_payload = step_response.json()
assert "observation" in step_payload
assert "reward" in step_payload
assert "done" in step_payload
state_response = client.post("/state", json={})
assert state_response.status_code == 200
state_payload = state_response.json()
assert state_payload["task_id"] == "easy_classification"
def test_runtime_reset_accepts_empty_body() -> None:
response = client.post("/reset")
assert response.status_code == 200
payload = response.json()
assert "emails" in payload
assert payload["persona"] == "balanced"
def test_interruptions_arrive_mid_episode() -> None:
env = ExecutiveEmailEnv(task_id="hard_full_management", seed=42, persona="balanced")
observation = env.reset(task_id="hard_full_management", seed=42, persona="balanced")
initial_count = len(observation.emails)
order = [email.id for email in observation.emails]
seen_interruptions = []
for _ in range(8):
result = env.step(Action(action_type="prioritize", priority_order=order))
seen_interruptions.extend(result.info.get("interruptions", []))
assert len(env.state().emails) > initial_count
assert "i1" in seen_interruptions
def test_baseline_endpoint_accepts_persona() -> None:
response = client.post(
"/baseline",
json={
"task_id": "hard_full_management",
"seed": 42,
"persona": "strict_ceo",
"max_steps": 40,
},
)
assert response.status_code == 200
payload = response.json()
assert payload["persona"] == "strict_ceo"
assert 0.0 <= payload["score"] <= 1.0
def test_baseline_endpoint_supports_stress_mode() -> None:
response = client.post(
"/baseline",
json={
"task_id": "hard_full_management",
"seed": 42,
"persona": "balanced",
"mode": "stress",
"stress_rate": 0.5,
"max_steps": 50,
},
)
assert response.status_code == 200
payload = response.json()
assert payload["mode"] == "stress"
assert payload["stress_rate"] == 0.5
def test_leaderboard_endpoint_available() -> None:
response = client.post(
"/leaderboard",
json={
"tasks": ["easy_classification"],
"personas": ["balanced"],
"seeds": [42],
"max_steps": 60,
"mode": "baseline",
"stress_rate": 0.0,
},
)
assert response.status_code == 200
payload = response.json()
assert payload["mode"] == "baseline"
assert len(payload["rows"]) == 1