""" End-to-end tests for error scenarios and edge cases. Tests various error conditions and ensures proper error handling throughout the system. """ import pytest from fastapi.testclient import TestClient @pytest.fixture def error_app(monkeypatch, tmp_path): """Create app for error scenario testing.""" db_path = tmp_path / "test.db" monkeypatch.setenv("GONDULF_SECRET_KEY", "a" * 32) monkeypatch.setenv("GONDULF_BASE_URL", "https://auth.example.com") monkeypatch.setenv("GONDULF_DATABASE_URL", f"sqlite:///{db_path}") monkeypatch.setenv("GONDULF_DEBUG", "true") from gondulf.main import app return app @pytest.fixture def error_client(error_app): """Create test client for error scenario tests.""" with TestClient(error_app) as client: yield client @pytest.mark.e2e class TestAuthorizationErrors: """E2E tests for authorization endpoint errors.""" def test_missing_all_parameters(self, error_client): """Test authorization request with no parameters.""" response = error_client.get("/authorize") assert response.status_code == 400 def test_http_client_id_rejected(self, error_client): """Test HTTP (non-HTTPS) client_id is rejected.""" response = error_client.get("/authorize", params={ "client_id": "http://insecure.example.com", "redirect_uri": "http://insecure.example.com/callback", "response_type": "code", "state": "test", }) assert response.status_code == 400 assert "https" in response.text.lower() def test_mismatched_redirect_uri_domain(self, error_client): """Test redirect_uri must match client_id domain.""" response = error_client.get("/authorize", params={ "client_id": "https://legitimate-app.example.com", "redirect_uri": "https://evil-site.example.com/steal", "response_type": "code", "state": "test", }) assert response.status_code == 400 def test_invalid_response_type_redirects(self, error_client): """Test invalid response_type redirects with error.""" response = error_client.get("/authorize", params={ "client_id": "https://app.example.com", "redirect_uri": "https://app.example.com/callback", "response_type": "implicit", # Not supported "state": "test123", }, follow_redirects=False) assert response.status_code == 302 location = response.headers["location"] assert "error=unsupported_response_type" in location assert "state=test123" in location @pytest.mark.e2e class TestTokenEndpointErrors: """E2E tests for token endpoint errors.""" def test_invalid_grant_type(self, error_client): """Test unsupported grant_type returns error.""" response = error_client.post("/token", data={ "grant_type": "client_credentials", "code": "some_code", "client_id": "https://app.example.com", "redirect_uri": "https://app.example.com/callback", }) assert response.status_code == 400 data = response.json() assert data["detail"]["error"] == "unsupported_grant_type" def test_missing_grant_type(self, error_client): """Test missing grant_type returns validation error.""" response = error_client.post("/token", data={ "code": "some_code", "client_id": "https://app.example.com", "redirect_uri": "https://app.example.com/callback", }) # FastAPI validation error assert response.status_code == 422 def test_nonexistent_code(self, error_client): """Test nonexistent authorization code returns error.""" response = error_client.post("/token", data={ "grant_type": "authorization_code", "code": "completely_made_up_code_12345", "client_id": "https://app.example.com", "redirect_uri": "https://app.example.com/callback", }) assert response.status_code == 400 data = response.json() assert data["detail"]["error"] == "invalid_grant" def test_get_method_not_allowed(self, error_client): """Test GET method not allowed on token endpoint.""" response = error_client.get("/token") assert response.status_code == 405 @pytest.mark.e2e class TestVerificationErrors: """E2E tests for verification endpoint errors.""" def test_invalid_me_url(self, error_client): """Test invalid me URL format.""" response = error_client.post( "/api/verify/start", data={"me": "not-a-url"} ) assert response.status_code == 200 data = response.json() assert data["success"] is False assert data["error"] == "invalid_me_url" def test_invalid_code_verification(self, error_client): """Test verification with invalid code.""" response = error_client.post( "/api/verify/code", data={"domain": "example.com", "code": "000000"} ) assert response.status_code == 200 data = response.json() assert data["success"] is False @pytest.mark.e2e class TestSecurityErrorHandling: """E2E tests for security-related error handling.""" def test_xss_in_state_escaped(self, error_client): """Test XSS attempt in state parameter is escaped.""" xss_payload = "" response = error_client.get("/authorize", params={ "client_id": "https://app.example.com", "redirect_uri": "https://app.example.com/callback", "response_type": "token", # Will error and redirect "state": xss_payload, }, follow_redirects=False) # Should redirect with error assert response.status_code == 302 location = response.headers["location"] # Script tags should be URL encoded, not raw assert "