"""Client tests for AuthMiddleware 'me'/'myself' resolution with Phase 1 & 2 fixes.
Tests verify:
1. Tools work with explicit user_google_email parameter (backward compatible)
2. Tools work with 'me'/'myself' keywords (middleware auto-injection)
3. Middleware properly resolves user email from OAuth files
"""
import pytest
from .base_test_config import TEST_EMAIL
from .test_helpers import TestResponseValidator, ToolTestRunner
@pytest.mark.service("gmail")
@pytest.mark.auth_required
class TestMiddlewareMeResolution:
"""Test 'me'/'myself' email resolution with improved AuthMiddleware."""
@pytest.mark.asyncio
async def test_explicit_email_still_works(self, client):
"""Verify backward compatibility - explicit email parameter works."""
# Test with explicit email (should always work)
result = await client.call_tool(
"search_gmail_messages",
{"user_google_email": TEST_EMAIL, "query": "test", "page_size": 5},
)
assert result is not None
content = result.content[0].text if result.content else str(result)
# Should get valid response or auth error (both are acceptable)
validator = TestResponseValidator()
is_valid_auth = validator.is_valid_auth_response(content)
is_success = validator.is_success_response(content)
assert (
is_valid_auth or is_success
), f"Should get valid auth response or success, got: {content[:200]}"
@pytest.mark.asyncio
async def test_me_keyword_resolution(self, client):
"""Test 'me' keyword resolution via middleware auto-injection."""
# Test with 'me' keyword - middleware should inject actual email
result = await client.call_tool(
"draft_gmail_message",
{
"user_google_email": "me", # Should be auto-resolved by middleware
"subject": "Test with 'me' keyword",
"body": "Testing middleware auto-injection",
},
)
assert result is not None
content = result.content[0].text if result.content else str(result)
# SUCCESS CRITERIA:
# 1. Response contains actual email (not literal 'me')
# 2. OR response indicates 'me' was resolved
# 3. Response should NOT have "invalid email 'me'" error
# Check if actual email is in the response (middleware worked!)
has_actual_email = TEST_EMAIL in content or "groupon.com" in content
has_resolved_indicator = "resolved" in content.lower()
has_invalid_me_error = (
"invalid email 'me'" in content.lower()
or "invalid user email" in content.lower()
and "'me'" in content.lower()
)
assert (
has_actual_email or has_resolved_indicator
), f"Middleware should inject actual email, got: {content[:300]}"
assert (
not has_invalid_me_error
), f"Should not have 'invalid email' error for 'me', got: {content[:300]}"
@pytest.mark.asyncio
async def test_myself_keyword_resolution(self, client):
"""Test 'myself' keyword resolution via middleware auto-injection."""
# Test with 'myself' keyword
result = await client.call_tool(
"draft_gmail_message",
{
"user_google_email": "myself", # Should be auto-resolved
"subject": "Test with 'myself' keyword",
"body": "Testing middleware auto-injection with 'myself'",
},
)
assert result is not None
content = result.content[0].text if result.content else str(result)
# SUCCESS CRITERIA:
# 1. Response contains actual email (not literal 'myself')
# 2. OR response indicates 'myself' was resolved
# 3. Response should NOT have "invalid email 'myself'" error
# Check if actual email is in the response (middleware worked!)
has_actual_email = TEST_EMAIL in content or "groupon.com" in content
has_resolved_indicator = "resolved" in content.lower()
has_invalid_myself_error = (
"invalid email 'myself'" in content.lower()
or "invalid user email" in content.lower()
and "'myself'" in content.lower()
)
assert (
has_actual_email or has_resolved_indicator
), f"Middleware should inject actual email, got: {content[:300]}"
assert (
not has_invalid_myself_error
), f"Should not have 'invalid email' error for 'myself', got: {content[:300]}"
@pytest.mark.asyncio
async def test_auth_pattern_consistency(self, client):
"""Test that both auth patterns work consistently."""
runner = ToolTestRunner(client, TEST_EMAIL)
# Test both patterns on a simple tool
results = await runner.test_auth_patterns("list_gmail_labels", {})
# Explicit email should always work (backward compatible)
assert results[
"backward_compatible"
], "Explicit email pattern must remain backward compatible"
# Log middleware injection results
middleware_result = results["middleware_injection"]
print("\nš Middleware injection test:")
print(f" Success: {middleware_result['success']}")
if not middleware_result["success"]:
print(f" Response: {middleware_result['content'][:200]}")
@pytest.mark.service("drive")
@pytest.mark.auth_required
class TestDriveWithMiddleware:
"""Test Drive operations work with improved middleware."""
@pytest.mark.asyncio
async def test_drive_search_explicit_email(self, client):
"""Test Drive search with explicit email (backward compatible)."""
result = await client.call_tool(
"search_drive_files",
{"user_google_email": TEST_EMAIL, "query": "type:pdf", "page_size": 5},
)
assert result is not None
content = result.content[0].text if result.content else str(result)
# Should work or give valid auth response
validator = TestResponseValidator()
is_valid = validator.is_valid_auth_response(
content
) or validator.is_success_response(content)
assert is_valid, f"Should get valid response, got: {content[:200]}"
@pytest.mark.asyncio
async def test_drive_check_auth_with_me(self, client):
"""Test Drive auth check with 'me' keyword."""
result = await client.call_tool(
"check_drive_auth", {"user_google_email": "me"} # Should be auto-resolved
)
assert result is not None
content = result.content[0].text if result.content else str(result)
# Should not complain about invalid email 'me'
assert (
"'me'" not in content.lower()
or "resolved" in content.lower()
or "authenticated" in content.lower()
), f"'me' should be resolved, got: {content[:200]}"
@pytest.mark.service("calendar")
class TestCalendarWithMiddleware:
"""Test Calendar operations work with improved middleware."""
@pytest.mark.asyncio
async def test_list_calendars_both_patterns(self, client):
"""Test listing calendars with both auth patterns."""
runner = ToolTestRunner(client, TEST_EMAIL)
results = await runner.test_auth_patterns("list_calendars", {})
# Both should work or give valid auth responses
assert results["backward_compatible"], "Explicit email should work"
# Middleware should work or gracefully handle missing auth
middleware_success = results["middleware_injection"]["success"]
middleware_content = results["middleware_injection"]["content"]
if not middleware_success:
# If middleware injection failed, it should be a valid auth error
validator = TestResponseValidator()
assert validator.is_valid_auth_response(
middleware_content
), f"Middleware failure should give valid auth error, got: {middleware_content[:200]}"
class TestMiddlewareServerIntegration:
"""Test middleware is properly integrated with server."""
@pytest.mark.asyncio
async def test_server_tools_still_available(self, client):
"""Verify tools are still available after middleware re-enablement."""
tools = await client.list_tools()
tool_names = [tool.name for tool in tools]
# Should have core tools
essential_tools = [
"start_google_auth",
"search_gmail_messages",
"upload_to_drive",
"list_calendars",
]
for tool_name in essential_tools:
assert (
tool_name in tool_names
), f"Essential tool {tool_name} should be available after middleware re-enablement"
@pytest.mark.asyncio
async def test_resources_still_accessible(self, client):
"""Verify resources work after middleware re-enablement."""
# Try to read a resource
result = await client.read_resource("user://current/email")
assert result is not None, "Should be able to read user resource"
if __name__ == "__main__":
pytest.main([__file__, "-v", "-s"])