From 0236ef23d86e99e9123709b8a5a41c72303183fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Y=C3=BBki=20VACHOT?= Date: Sat, 29 Nov 2025 04:54:37 +0100 Subject: [PATCH] Fix integration tests via mockup --- src/tests/conftest.py | 95 ++++++++++++++++++++---- src/tests/integration/test_api_client.py | 48 +++--------- src/tests/integration/test_auth_flow.py | 4 +- 3 files changed, 95 insertions(+), 52 deletions(-) diff --git a/src/tests/conftest.py b/src/tests/conftest.py index 00e0442..8c49252 100644 --- a/src/tests/conftest.py +++ b/src/tests/conftest.py @@ -1,19 +1,44 @@ """Shared test fixtures.""" - +import os from unittest.mock import AsyncMock, MagicMock, patch import pytest +from geoguessr_mcp.api import GeoGuessrClient from geoguessr_mcp.api.dynamic_response import DynamicResponse -from geoguessr_mcp.auth import SessionManager +from geoguessr_mcp.auth import SessionManager, UserSession +from geoguessr_mcp.config import settings from geoguessr_mcp.models import RoundGuess, Game from geoguessr_mcp.services import AnalysisService, GameService, ProfileService @pytest.fixture(autouse=True) -def mock_env(monkeypatch): +def mock_env(request, monkeypatch): """Set up environment variables for testing.""" - monkeypatch.setenv("GEOGUESSR_NCFA_COOKIE", "test_cookie_value") + # Skip this fixture if the test has the 'real_env' marker + if 'real_env' in request.keywords: + yield + return + + # Clear the default cookie in settings to avoid interference + monkeypatch.setattr(settings, "DEFAULT_NCFA_COOKIE", None) + + # Clear schema registry to avoid interference from registered schemas + from geoguessr_mcp.monitoring.schema.schema_registry import schema_registry + # Store original schemas + original_schemas = schema_registry.schemas.copy() + # Clear all schemas for testing + schema_registry.schemas.clear() + + # Ensure required settings are set + if not hasattr(settings, "GEOGUESSR_API_URL") or not settings.GEOGUESSR_API_URL: + monkeypatch.setattr(settings, "GEOGUESSR_API_URL", "https://api.geoguessr.com") + if not hasattr(settings, "GEOGUESSR_DOMAIN_NAME") or not settings.GEOGUESSR_DOMAIN_NAME: + monkeypatch.setattr(settings, "GEOGUESSR_DOMAIN_NAME", ".geoguessr.com") + + # Restore schemas after test + yield + schema_registry._schemas = original_schemas @pytest.fixture @@ -24,6 +49,35 @@ def mock_client(): return client +@pytest.fixture +def real_client(): + """Create a real client with environment authentication.""" + real_cookie = os.getenv("GEOGUESSR_NCFA_COOKIE") + session_manager = SessionManager(default_cookie=real_cookie) + return GeoGuessrClient(session_manager) + + +@pytest.fixture +def client(mock_session_manager): + """Create a GeoGuessrClient with mocked session manager.""" + return GeoGuessrClient(mock_session_manager) + + +@pytest.fixture +def mock_session_manager(): + """Create a mock session manager.""" + manager = MagicMock(spec=SessionManager) + manager.get_session = AsyncMock( + return_value=UserSession( + ncfa_cookie="test_cookie", + user_id="test-user", + username="TestUser", + email="test@example.com", + ) + ) + return manager + + @pytest.fixture def mock_session(): """Create a mock async HTTP session.""" @@ -35,11 +89,19 @@ def mock_session(): @pytest.fixture def session_manager(): - return SessionManager() + """Create a SessionManager without default cookie.""" + return SessionManager(default_cookie=None) + + +@pytest.fixture +def session_manager_with_default(): + """Create a SessionManager with a default cookie.""" + return SessionManager(default_cookie="test_cookie_value") @pytest.fixture def mock_httpx_client(): + """Create a mock httpx client for testing.""" with patch("httpx.AsyncClient") as mock_client_class: mock_client = AsyncMock() mock_client.__aenter__.return_value = mock_client @@ -89,16 +151,21 @@ def profile_service(mock_client): @pytest.fixture def mock_dynamic_response(): - """Create a mock DynamicResponse factory.""" + """Create a DynamicResponse factory for testing.""" - def create_response(data, success=True, status_code=200): - response = MagicMock(spec=DynamicResponse) - response.data = data - response.is_success = success - response.status_code = status_code - response.available_fields = list(data.keys()) if isinstance(data, dict) else [] - response.summarize.return_value = {"data_summary": data} - return response + def create_response(data, success=True, status_code=200, endpoint="/mock/endpoint"): + """Create a real DynamicResponse instance for testing. + :param data: + :param status_code: + :param endpoint: + :type success: object + """ + return DynamicResponse( + data=data, + endpoint=endpoint, + status_code=status_code, + response_time_ms=100.0, + ) return create_response diff --git a/src/tests/integration/test_api_client.py b/src/tests/integration/test_api_client.py index 8bf38f8..5b98ffd 100644 --- a/src/tests/integration/test_api_client.py +++ b/src/tests/integration/test_api_client.py @@ -11,7 +11,6 @@ import httpx import pytest from geoguessr_mcp.api import DynamicResponse, GeoGuessrClient, EndpointInfo, Endpoints -from geoguessr_mcp.auth.session import SessionManager, UserSession from geoguessr_mcp.config import settings @@ -52,7 +51,7 @@ class TestDynamicResponse: """Test available_fields with dict data.""" response = DynamicResponse( data={"id": "123", "name": "Test", "score": 5000}, - endpoint="/v3/test", + endpoint="/mock/endpoint", status_code=200, response_time_ms=100.0, ) @@ -62,7 +61,7 @@ class TestDynamicResponse: """Test available_fields with non-dict data.""" response = DynamicResponse( data=["item1", "item2"], - endpoint="/v3/test", + endpoint="/mock/endpoint", status_code=200, response_time_ms=100.0, ) @@ -72,7 +71,7 @@ class TestDynamicResponse: """Test getting a simple field.""" response = DynamicResponse( data={"id": "123", "name": "Test"}, - endpoint="/v3/test", + endpoint="/mock/endpoint", status_code=200, response_time_ms=100.0, ) @@ -90,7 +89,7 @@ class TestDynamicResponse: } } }, - endpoint="/v3/test", + endpoint="/mock/endpoint", status_code=200, response_time_ms=100.0, ) @@ -101,7 +100,7 @@ class TestDynamicResponse: """Test getting missing field returns default.""" response = DynamicResponse( data={"id": "123"}, - endpoint="/v3/test", + endpoint="/mock/endpoint", status_code=200, response_time_ms=100.0, ) @@ -137,13 +136,13 @@ class TestDynamicResponse: ], "total": 4, }, - endpoint="/v3/test", + endpoint="/mock/endpoint", status_code=200, response_time_ms=100.0, ) summary = response.summarize(max_depth=1) - assert summary["endpoint"] == "/v3/test" + assert summary["endpoint"] == "/mock/endpoint" assert summary["status"] == "success" assert "data_summary" in summary @@ -152,7 +151,7 @@ class TestDynamicResponse: long_text = "x" * 200 response = DynamicResponse( data={"description": long_text}, - endpoint="/v3/test", + endpoint="/mock/endpoint", status_code=200, response_time_ms=100.0, ) @@ -165,25 +164,6 @@ class TestDynamicResponse: class TestGeoGuessrClient: """Tests for GeoGuessrClient.""" - @pytest.fixture - def mock_session_manager(self): - """Create a mock session manager.""" - manager = MagicMock(spec=SessionManager) - manager.get_session = AsyncMock( - return_value=UserSession( - ncfa_cookie="test_cookie", - user_id="test-user", - username="TestUser", - email="test@example.com", - ) - ) - return manager - - @pytest.fixture - def client(self, mock_session_manager): - """Create a GeoGuessrClient with mocked session manager.""" - return GeoGuessrClient(mock_session_manager) - @pytest.mark.asyncio async def test_get_authenticated_client(self, client, mock_session_manager): """Test getting authenticated HTTP client.""" @@ -268,7 +248,7 @@ class TestGeoGuessrClient: mock_auth.return_value = mock_http_client - endpoint = EndpointInfo(path="/v3/test", method="POST") + endpoint = EndpointInfo(path="/mock/endpoint", method="POST") response = await client.post(endpoint, json_data={"data": "test"}) assert response.is_success @@ -309,6 +289,7 @@ class TestGeoGuessrClient: @pytest.mark.integration +@pytest.mark.real_env class TestGeoGuessrClientIntegration: """ Integration tests that would make real API calls. @@ -318,12 +299,6 @@ class TestGeoGuessrClientIntegration: authentication cookie. """ - @pytest.fixture - def real_client(self): - """Create a real client with environment authentication.""" - session_manager = SessionManager() - return GeoGuessrClient(session_manager) - @pytest.mark.asyncio async def test_real_profile_endpoint(self, real_client): """Test real API call to profile endpoint.""" @@ -335,11 +310,12 @@ class TestGeoGuessrClientIntegration: response = await real_client.get(Endpoints.PROFILES.GET_PROFILE) assert response.is_success - assert "id" in response.available_fields or "nick" in response.available_fields + assert "user" in response.available_fields or "email" in response.available_fields @pytest.mark.asyncio async def test_real_stats_endpoint(self, real_client): """Test real API call to stats' endpoint.""" + # This test requires GEOGUESSR_NCFA_COOKIE to be set import os if not os.environ.get("GEOGUESSR_NCFA_COOKIE"): pytest.skip("GEOGUESSR_NCFA_COOKIE not set") diff --git a/src/tests/integration/test_auth_flow.py b/src/tests/integration/test_auth_flow.py index 0cb3d95..7bc0867 100644 --- a/src/tests/integration/test_auth_flow.py +++ b/src/tests/integration/test_auth_flow.py @@ -375,5 +375,5 @@ class TestRealAuthFlow: result = await session_manager.validate_cookie(cookie) assert result is not None - assert "id" in result - assert "nick" in result + assert "user" in result + assert "email" in result