Fix CI/CD issues and add comprehensive tests for multi-user features
This commit fixes three critical issues identified in CI/CD and adds comprehensive test coverage for the new multi-user functionality. ## Fixes ### 1. FastMCP Middleware Registration Error **Problem**: `AttributeError: 'FastMCP' object has no attribute 'app'` **Solution**: Implemented robust middleware registration that: - Tries multiple possible locations where FastMCP might store the app - Gracefully handles cases where app isn't immediately available - Wraps the run() method to defer middleware addition if needed - Attempts: _transport.app, sse.app, http_server.app, _app, _asgi_app - Falls back gracefully with warning if middleware can't be added **Files Changed**: - src/geoguessr_mcp/main.py: Added smart middleware registration logic ### 2. Test Permission Errors **Problem**: `PermissionError: [Errno 13] Permission denied: '/app'` Schema registry tried to create /app/data/schemas in CI without permission **Solution**: Made schema cache directory creation fault-tolerant: - Catches PermissionError and OSError when creating cache directory - Falls back to temporary directory (tempfile.mkdtemp) if permission denied - Logs clear warning messages about fallback behavior - Tests can now run in restricted environments **Files Changed**: - src/geoguessr_mcp/monitoring/schema/schema_registry.py: Added fallback logic ### 3. Black Formatting Issues **Problem**: 10 files needed reformatting **Solution**: Ran `black src/ --line-length 100` on all source files **Files Formatted**: - src/geoguessr_mcp/config.py - src/geoguessr_mcp/api/dynamic_response.py - src/geoguessr_mcp/middleware/auth.py - src/geoguessr_mcp/main.py - src/geoguessr_mcp/auth/multi_user_session.py - src/geoguessr_mcp/tools/auth_tools.py - src/tests/integration/test_auth_flow.py - src/tests/unit/services/*.py (3 files) ## New Tests Added comprehensive test coverage for multi-user features: ### test_user_context.py - Tests UserContext creation with/without sessions - Tests authentication status checking - Tests session expiration handling - Tests string representation - Tests API key hashing for anonymous users - Tests consistency of anonymous user IDs ### test_multi_user_session.py - Tests MultiUserSessionManager initialization - Tests session manager creation per API key - Tests session manager reuse for same API key - Tests isolation between different users - Tests auth status reporting - Tests context creation and retrieval ### test_request_context.py - Tests context variable get/set operations - Tests require_user_context() error handling - Tests context isolation between requests - Tests context updates and clearing - Tests None handling ## Code Quality All changes pass: - ✅ Python syntax checks (py_compile) - ✅ Black formatting (line-length 100) - ✅ Test structure validation - ✅ Import resolution ## CI/CD Impact These fixes should resolve: - ❌ Test execution failures (permission errors) - ❌ Black formatting check failures - ❌ Runtime errors when starting server with auth enabled Tests can now run in CI environment without requiring: - Root permissions - /app directory access - Pre-created cache directories
This commit is contained in:
parent
80ed791b01
commit
482daa73e0
14 changed files with 422 additions and 82 deletions
95
src/tests/unit/auth/test_user_context.py
Normal file
95
src/tests/unit/auth/test_user_context.py
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
"""Tests for UserContext class."""
|
||||
|
||||
import pytest
|
||||
|
||||
from geoguessr_mcp.auth.session import UserSession
|
||||
from geoguessr_mcp.auth.user_context import UserContext
|
||||
from datetime import datetime, timedelta, UTC
|
||||
|
||||
|
||||
class TestUserContext:
|
||||
"""Tests for UserContext class."""
|
||||
|
||||
def test_user_context_without_session(self):
|
||||
"""Test user context without a GeoGuessr session."""
|
||||
context = UserContext(api_key="test_key_123")
|
||||
|
||||
assert context.api_key == "test_key_123"
|
||||
assert context.session is None
|
||||
assert not context.is_authenticated
|
||||
assert context.ncfa_cookie is None
|
||||
assert "anonymous_" in context.user_id
|
||||
assert "User-" in context.username
|
||||
|
||||
def test_user_context_with_session(self):
|
||||
"""Test user context with a GeoGuessr session."""
|
||||
session = UserSession(
|
||||
ncfa_cookie="test_cookie",
|
||||
user_id="user123",
|
||||
username="testuser",
|
||||
email="test@example.com",
|
||||
expires_at=datetime.now(UTC) + timedelta(days=1),
|
||||
)
|
||||
|
||||
context = UserContext(api_key="test_key_123", session=session)
|
||||
|
||||
assert context.api_key == "test_key_123"
|
||||
assert context.session == session
|
||||
assert context.is_authenticated
|
||||
assert context.ncfa_cookie == "test_cookie"
|
||||
assert context.user_id == "user123"
|
||||
assert context.username == "testuser"
|
||||
|
||||
def test_user_context_with_expired_session(self):
|
||||
"""Test user context with an expired session."""
|
||||
session = UserSession(
|
||||
ncfa_cookie="test_cookie",
|
||||
user_id="user123",
|
||||
username="testuser",
|
||||
email="test@example.com",
|
||||
expires_at=datetime.now(UTC) - timedelta(days=1), # Expired
|
||||
)
|
||||
|
||||
context = UserContext(api_key="test_key_123", session=session)
|
||||
|
||||
# Session is present but not valid
|
||||
assert context.session == session
|
||||
assert not context.is_authenticated # Expired session = not authenticated
|
||||
|
||||
def test_user_context_repr(self):
|
||||
"""Test string representation of user context."""
|
||||
context = UserContext(api_key="test_key_123")
|
||||
repr_str = repr(context)
|
||||
|
||||
assert "UserContext" in repr_str
|
||||
assert "not authenticated" in repr_str
|
||||
|
||||
session = UserSession(
|
||||
ncfa_cookie="test_cookie",
|
||||
user_id="user123",
|
||||
username="testuser",
|
||||
email="test@example.com",
|
||||
)
|
||||
context_with_session = UserContext(api_key="test_key_123", session=session)
|
||||
repr_with_session = repr(context_with_session)
|
||||
|
||||
assert "authenticated" in repr_with_session
|
||||
assert "user123" in repr_with_session
|
||||
|
||||
def test_user_context_consistent_ids(self):
|
||||
"""Test that user IDs are consistent for the same API key."""
|
||||
context1 = UserContext(api_key="same_key")
|
||||
context2 = UserContext(api_key="same_key")
|
||||
|
||||
# Same API key should produce same anonymous user ID
|
||||
assert context1.user_id == context2.user_id
|
||||
assert context1.username == context2.username
|
||||
|
||||
def test_user_context_different_ids_for_different_keys(self):
|
||||
"""Test that different API keys produce different anonymous user IDs."""
|
||||
context1 = UserContext(api_key="key1")
|
||||
context2 = UserContext(api_key="key2")
|
||||
|
||||
# Different API keys should produce different anonymous user IDs
|
||||
assert context1.user_id != context2.user_id
|
||||
assert context1.username != context2.username
|
||||
Loading…
Add table
Add a link
Reference in a new issue