import pytest import asyncio import sys import os from datetime import datetime, timedelta from unittest.mock import AsyncMock, MagicMock # Add the src directory to Python path sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', 'src')) from auth.auth_manager import AuthManager from models.token import AuthenticationToken from auth.token_manager import TokenManager @pytest.fixture def mock_api_client(): """Mock API client for testing""" client = AsyncMock() client.set_token = AsyncMock() return client @pytest.fixture def mock_token_manager(): """Mock token manager for testing""" manager = MagicMock() manager.save_token = MagicMock() manager.load_token = MagicMock() manager.clear_token = MagicMock() manager.token_exists = MagicMock(return_value=False) return manager @pytest.fixture def auth_manager(mock_api_client, mock_token_manager): """Create an AuthManager instance with mocked dependencies""" return AuthManager(mock_api_client, mock_token_manager) @pytest.mark.asyncio async def test_authenticate_success(auth_manager, mock_api_client, mock_token_manager): """Test successful authentication""" # Setup mock response mock_api_client.authenticate_user = AsyncMock(return_value={ "success": True, "session_id": "session123", "access_token": "token123", "token_type": "Bearer", "expires_in": 3600, "user": {"id": "user123", "email": "test@example.com"} }) # Call authenticate result = await auth_manager.authenticate("test@example.com", "password", "123456") # Assertions assert result is not None assert result.user_id == "user123" assert result.session_id == "session123" mock_token_manager.save_token.assert_called_once() mock_api_client.set_token.assert_called_once() @pytest.mark.asyncio async def test_authenticate_with_mfa(auth_manager, mock_api_client, mock_token_manager): """Test authentication with MFA code""" # Setup mock response mock_api_client.authenticate_user = AsyncMock(return_value={ "success": True, "session_id": "session123", "access_token": "token123", "token_type": "Bearer", "expires_in": 3600, "mfa_required": True, "user": {"id": "user123", "email": "test@example.com"} }) # Call authenticate with MFA result = await auth_manager.authenticate("test@example.com", "password", "123456") # Assertions assert result is not None assert result.mfa_enabled is True mock_api_client.authenticate_user.assert_called_once_with("test@example.com", "password", "123456") @pytest.mark.asyncio async def test_authenticate_failure(auth_manager, mock_api_client): """Test authentication failure""" # Setup mock response for failure mock_api_client.authenticate_user = AsyncMock(return_value={ "success": False, "error": "Invalid credentials" }) # Expect exception to be raised with pytest.raises(Exception, match="Authentication failed: Invalid credentials"): await auth_manager.authenticate("test@example.com", "wrong_password") @pytest.mark.asyncio async def test_logout_success(auth_manager, mock_api_client, mock_token_manager): """Test successful logout""" # Setup mock_api_client.client.headers = {"Authorization": "Bearer token123"} # Call logout result = await auth_manager.logout() # Assertions assert result is True mock_token_manager.clear_token.assert_called_once() assert "Authorization" not in mock_api_client.client.headers def test_is_token_expired_false(auth_manager): """Test token expiration check for non-expired token""" # Create a token that expires in the future from datetime import datetime, timedelta future_expiry = datetime.now() + timedelta(hours=1) token = AuthenticationToken( token_id="token123", user_id="user123", access_token="token123", created_at=datetime.now() - timedelta(minutes=10), # Created 10 minutes ago expires_in=3600 # Expires in 1 hour ) # Should not be expired assert auth_manager.is_token_expired(token) is False def test_is_token_expired_true(auth_manager): """Test token expiration check for expired token""" # Create a token that should have expired token = AuthenticationToken( token_id="token123", user_id="user123", access_token="token123", created_at=datetime.now() - timedelta(hours=2), # Created 2 hours ago expires_in=3600 # Was supposed to expire after 1 hour ) # Should be expired assert auth_manager.is_token_expired(token) is True