""" End-to-end tests for the API. These tests require the API server to be running and are skipped by default. Run with: pytest tests/test_e2e.py -v --run-e2e Start the server first: ./wakeup.sh """ import pytest from tests.conftest import assert_contains_any # All tests in this module require --run-e2e pytestmark = [pytest.mark.e2e, pytest.mark.slow] class TestHealthEndpoint: """E2E tests for health endpoint.""" @pytest.mark.anyio async def test_health_check(self, live_client): """Test that health endpoint responds.""" response = await live_client.get("/health") assert response.status_code == 200 data = response.json() assert data.get("status") == "healthy" class TestAgentEndpoints: """E2E tests for agent endpoints.""" @pytest.mark.anyio async def test_list_agents(self, live_client): """Test listing agents via live API.""" response = await live_client.get("/agents/") assert response.status_code == 200 data = response.json() assert "agents" in data assert len(data["agents"]) >= 1 # Verify explore agent exists names = [a["name"] for a in data["agents"]] assert "explore" in names @pytest.mark.anyio async def test_get_agent_info(self, live_client): """Test getting agent info via live API.""" response = await live_client.get("/agents/explore") assert response.status_code == 200 data = response.json() assert data["name"] == "explore" assert "description" in data @pytest.mark.anyio async def test_run_agent(self, live_client, sample_project): """Test running agent via live API.""" response = await live_client.post( "/agents/run", json={ "agent_type": "explore", "prompt": "List all files in this directory", "working_dir": str(sample_project), }, timeout=60.0, # LLM calls can be slow ) assert response.status_code == 200 data = response.json() assert data.get("success") is True assert "response" in data assert len(data["response"]) > 0 class TestStreamingEndpoint: """E2E tests for streaming endpoint.""" @pytest.mark.anyio async def test_stream_agent(self, live_client, sample_project): """Test streaming agent responses via live API.""" async with live_client.stream( "POST", "/agents/stream", json={ "agent_type": "explore", "prompt": "List all Python files", "working_dir": str(sample_project), }, timeout=60.0, ) as response: assert response.status_code == 200 assert response.headers.get("content-type") == "text/event-stream; charset=utf-8" # Collect chunks chunks = [] async for line in response.aiter_lines(): if line.startswith("data: "): chunks.append(line) # Should receive some data assert len(chunks) >= 1 @pytest.mark.anyio async def test_stream_invalid_agent(self, live_client): """Test streaming with invalid agent type.""" response = await live_client.post( "/agents/stream", json={ "agent_type": "nonexistent", "prompt": "test", "working_dir": ".", }, ) assert response.status_code == 400 class TestErrorHandling: """E2E tests for error handling.""" @pytest.mark.anyio async def test_invalid_agent_type(self, live_client): """Test error response for invalid agent.""" response = await live_client.post( "/agents/run", json={ "agent_type": "nonexistent", "prompt": "test", "working_dir": ".", }, ) assert response.status_code == 400 data = response.json() assert "detail" in data @pytest.mark.anyio async def test_missing_required_fields(self, live_client): """Test validation error for missing fields.""" response = await live_client.post( "/agents/run", json={ "agent_type": "explore", # Missing prompt }, ) assert response.status_code == 422 @pytest.mark.anyio async def test_agent_not_found(self, live_client): """Test 404 for unknown agent info.""" response = await live_client.get("/agents/unknown_agent") assert response.status_code == 404 class TestRealWorldScenarios: """E2E tests for real-world usage scenarios.""" @pytest.mark.anyio async def test_explore_codebase(self, live_client, sample_project): """Test exploring a real codebase.""" response = await live_client.post( "/agents/run", json={ "agent_type": "explore", "prompt": "What functions are defined in the src directory?", "working_dir": str(sample_project), }, timeout=60.0, ) assert response.status_code == 200 data = response.json() assert data.get("success") is True # Should mention some functions assert_contains_any( data.get("response", ""), ["greet", "add", "divide", "factorial", "function"] ) @pytest.mark.anyio async def test_find_bugs(self, live_client, sample_project_with_bug): """Test finding bugs in code.""" response = await live_client.post( "/agents/run", json={ "agent_type": "explore", "prompt": "Review buggy.py and identify any potential bugs or issues.", "working_dir": str(sample_project_with_bug), }, timeout=60.0, ) assert response.status_code == 200 data = response.json() assert data.get("success") is True # Should identify issues assert_contains_any( data.get("response", ""), ["zero", "division", "bug", "error", "issue", "check"] ) @pytest.mark.anyio async def test_read_and_summarize(self, live_client, sample_project): """Test reading and summarizing a file.""" response = await live_client.post( "/agents/run", json={ "agent_type": "explore", "prompt": "Read README.md and give me a one-sentence summary.", "working_dir": str(sample_project), }, timeout=60.0, ) assert response.status_code == 200 data = response.json() assert data.get("success") is True assert len(data.get("response", "")) > 10