diff --git a/tests/integration/main_test.py b/tests/integration/main_test.py new file mode 100644 index 0000000..4ffcfb9 --- /dev/null +++ b/tests/integration/main_test.py @@ -0,0 +1,182 @@ +"""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"] diff --git a/tests/integration/test_main.py b/tests/integration/test_main.py deleted file mode 100644 index e04ee49..0000000 --- a/tests/integration/test_main.py +++ /dev/null @@ -1,72 +0,0 @@ -"""Integration tests for FastAPI application.""" - -import pytest -from fastapi.testclient import TestClient - - -@pytest.mark.integration -def test_read_root(app_test_client: TestClient) -> None: - """Test root endpoint returns expected message.""" - response = app_test_client.get("/") - assert response.status_code == 200 - assert response.json() == {"message": "Hello World"} - - -@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 JSON content type.""" - response = app_test_client.get("/") - 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"