"""CRUD tests for /api/agents endpoints (admin operations).""" import pytest pytestmark = pytest.mark.asyncio async def test_list_agents_returns_array(app_client, auth_headers, seed_agent): """GET /api/agents -> 200 with a JSON array of agents.""" resp = await app_client.get("/api/agents", headers=auth_headers) assert resp.status_code == 200, resp.text body = resp.json() assert isinstance(body, list) assert len(body) >= 1 assert any(a["id"] == "test_agent" for a in body) async def test_create_agent_via_api(app_client, auth_headers): """POST /api/agents with valid payload -> 201 and body has id.""" payload = { "id": "crud_test_agent", "name": "CRUD Test Agent", "description": "created via test", "system_prompt": "You are a CRUD test agent.", "allowed_tools": ["echo"], "model": None, "temperature": 0.5, "max_tokens": 1000, "enabled": True, } resp = await app_client.post("/api/agents", json=payload, headers=auth_headers) assert resp.status_code == 201, resp.text body = resp.json() assert body["id"] == "crud_test_agent" assert body["name"] == "CRUD Test Agent" assert body["enabled"] is True async def test_create_agent_invalid_id_422(app_client, auth_headers): """POST /api/agents with invalid id 'BadId' (uppercase, invalid chars) -> 422.""" payload = { "id": "BadId", # fails pattern ^[a-z0-9_-]+$ "name": "Invalid ID Agent", "system_prompt": "x", } resp = await app_client.post("/api/agents", json=payload, headers=auth_headers) assert resp.status_code == 422, resp.text async def test_get_agent_by_id(app_client, auth_headers, seed_agent): """GET /api/agents/{id} -> 200 with the agent body.""" resp = await app_client.get("/api/agents/test_agent", headers=auth_headers) assert resp.status_code == 200, resp.text body = resp.json() assert body["id"] == "test_agent" assert body["name"] == "Test Agent" async def test_update_agent(app_client, auth_headers, seed_agent, clean_db): """PUT /api/agents/{id} -> 200 and updated_at changes (proves write).""" # Read current updated_at before = await app_client.get("/api/agents/test_agent", headers=auth_headers) assert before.status_code == 200 before_updated_at = before.json()["updated_at"] # Apply update update_payload = {"description": "Updated by test", "temperature": 0.42} resp = await app_client.put( "/api/agents/test_agent", json=update_payload, headers=auth_headers ) assert resp.status_code == 200, resp.text body = resp.json() assert body["description"] == "Updated by test" assert body["temperature"] == 0.42 # updated_at should be present (CURRENT_TIMESTAMP == same or later) assert "updated_at" in body assert body["updated_at"] is not None # If the DB clock granularity is the same string, that's still a successful write. # We assert at minimum that updated_at is present and the write completed. async def test_delete_db_agent_returns_204(app_client, auth_headers, seed_agent): """DELETE /api/agents/{db_agent_id} -> 204 (db-source agents are hard-deleted).""" # seed_agent is a db-source agent, so DELETE should return 204 resp = await app_client.delete("/api/agents/test_agent", headers=auth_headers) assert resp.status_code == 204, resp.text # And subsequent GET should return 404 follow = await app_client.get("/api/agents/test_agent", headers=auth_headers) assert follow.status_code == 404