"""Integration tests for FastAPI application.""" import pytest from fastapi.testclient import TestClient @pytest.mark.integration def test_home_page_serves_html(app_test_client: TestClient) -> None: """Test root endpoint returns HTML page.""" response = app_test_client.get("/") assert response.status_code == 200 assert "text/html" in response.headers["content-type"] @pytest.mark.integration def test_api_root_requires_auth(app_test_client: TestClient) -> None: """Test API root endpoint requires authentication.""" response = app_test_client.get("/api/") assert response.status_code == 401 assert response.json() == {"detail": "Not authenticated"} @pytest.mark.integration def test_api_root_with_auth(app_test_client: TestClient) -> None: """Test authenticated API root endpoint returns expected message.""" # First login to get token login_response = app_test_client.post( "/api/login", json={"username": "admin", "password": "password"} ) assert login_response.status_code == 200 token = login_response.json()["access_token"] # Then access API root with token response = app_test_client.get( "/api/", headers={"Authorization": f"Bearer {token}"} ) assert response.status_code == 200 assert response.json() == {"message": "Hello World", "authenticated": True} @pytest.mark.integration def test_health_check(app_test_client: TestClient) -> None: """Test health check endpoint returns healthy status.""" response = app_test_client.get("/health") assert response.status_code == 200 assert response.json() == {"status": "healthy"} @pytest.mark.integration def test_readiness_check(app_test_client: TestClient) -> None: """Test readiness check endpoint returns ready status.""" response = app_test_client.get("/ready") assert response.status_code == 200 assert response.json() == {"status": "ready"} @pytest.mark.integration def test_openapi_docs_accessible(app_test_client: TestClient) -> None: """Test OpenAPI documentation is accessible.""" response = app_test_client.get("/docs") assert response.status_code == 200 @pytest.mark.integration def test_openapi_json_accessible(app_test_client: TestClient) -> None: """Test OpenAPI JSON schema is accessible.""" response = app_test_client.get("/openapi.json") assert response.status_code == 200 assert "openapi" in response.json() assert "info" in response.json() @pytest.mark.integration def test_nonexistent_endpoint_returns_404(app_test_client: TestClient) -> None: """Test requesting a non-existent endpoint returns 404.""" response = app_test_client.get("/nonexistent") assert response.status_code == 404 @pytest.mark.integration def test_root_endpoint_content_type(app_test_client: TestClient) -> None: """Test root endpoint returns HTML content type.""" response = app_test_client.get("/") assert "text/html" in response.headers["content-type"] @pytest.mark.integration def test_api_root_endpoint_content_type(app_test_client: TestClient) -> None: """Test API root endpoint returns JSON content type.""" # Login first to get token login_response = app_test_client.post( "/api/login", json={"username": "admin", "password": "password"} ) token = login_response.json()["access_token"] response = app_test_client.get( "/api/", headers={"Authorization": f"Bearer {token}"} ) assert response.headers["content-type"] == "application/json" @pytest.mark.integration def test_health_endpoint_content_type(app_test_client: TestClient) -> None: """Test health endpoint returns JSON content type.""" response = app_test_client.get("/health") assert response.headers["content-type"] == "application/json" @pytest.mark.integration def test_ready_endpoint_content_type(app_test_client: TestClient) -> None: """Test readiness endpoint returns JSON content type.""" response = app_test_client.get("/ready") assert response.headers["content-type"] == "application/json" @pytest.mark.integration def test_login_success(app_test_client: TestClient) -> None: """Test successful login returns access token.""" response = app_test_client.post( "/api/login", json={"username": "admin", "password": "password"} ) assert response.status_code == 200 data = response.json() assert "access_token" in data assert data["token_type"] == "bearer" @pytest.mark.integration def test_login_invalid_credentials(app_test_client: TestClient) -> None: """Test login with invalid credentials returns 401.""" response = app_test_client.post( "/api/login", json={"username": "admin", "password": "wrongpassword"} ) assert response.status_code == 401 assert response.json() == {"detail": "Invalid username or password"} @pytest.mark.integration def test_login_missing_fields(app_test_client: TestClient) -> None: """Test login with missing fields returns validation error.""" response = app_test_client.post( "/api/login", json={"username": "admin"} ) assert response.status_code == 422 @pytest.mark.integration def test_logout(app_test_client: TestClient) -> None: """Test logout endpoint.""" # Login first login_response = app_test_client.post( "/api/login", json={"username": "admin", "password": "password"} ) token = login_response.json()["access_token"] # Logout response = app_test_client.post( "/api/logout", headers={"Authorization": f"Bearer {token}"} ) assert response.status_code == 200 assert response.json() == {"message": "Logged out successfully"} @pytest.mark.integration def test_info_endpoint(app_test_client: TestClient) -> None: """Test info endpoint returns installed features.""" response = app_test_client.get("/info") assert response.status_code == 200 data = response.json() assert "features" in data assert isinstance(data["features"], dict) assert "redis" in data["features"] assert "postgresql" in data["features"]