""" 用户登录 Use Case 测试 """ from datetime import datetime, timezone from unittest.mock import Mock import pytest from packages.application.auth import ( LoginRequest, LoginUseCase, LogoutRequest, LogoutUseCase, ) from packages.domain.auth import password_hasher from packages.domain.entities import User class TestLoginUseCase: """登录用例测试""" @pytest.fixture def mock_user_repo(self): repo = Mock() repo.find_by_email = Mock(return_value=None) repo.save = Mock() return repo @pytest.fixture def use_case(self, mock_user_repo): session_store = Mock() session_store.save_session.return_value = True return LoginUseCase(user_repository=mock_user_repo, session_store=session_store) @pytest.fixture def test_user(self): """创建测试用户""" password_hash = password_hasher.hash_password("SecurePass123") return User( id="user-123", email="test@example.com", username="testuser", display_name="Test User", password_hash=password_hash, email_verified=True, ) def test_login_success(self, use_case, mock_user_repo, test_user): """测试登录成功""" mock_user_repo.find_by_email.return_value = test_user request = LoginRequest( email="test@example.com", password="SecurePass123", device_info="Chrome/Windows", ip_address="192.168.1.1", ) response, error = use_case.execute(request) assert error is None assert response is not None assert response.user_id == "user-123" assert response.email == "test@example.com" assert response.username == "testuser" assert response.access_token != "" assert response.refresh_token != "" assert response.expires_in > 0 # 验证保存了 session use_case.session_store.save_session.assert_called_once() # 验证更新了最后登录信息 mock_user_repo.save.assert_called_once() def test_login_invalid_email(self, use_case, mock_user_repo): """测试邮箱不存在""" mock_user_repo.find_by_email.return_value = None request = LoginRequest( email="nonexistent@example.com", password="SecurePass123", ) response, error = use_case.execute(request) assert response is None assert error == "Invalid email or password" def test_login_wrong_password(self, use_case, mock_user_repo, test_user): """测试密码错误""" mock_user_repo.find_by_email.return_value = test_user request = LoginRequest( email="test@example.com", password="WrongPassword123", ) response, error = use_case.execute(request) assert response is None assert error == "Invalid email or password" def test_login_missing_email(self, use_case): """测试缺少邮箱""" request = LoginRequest( email="", password="SecurePass123", ) response, error = use_case.execute(request) assert response is None assert error == "Email is required" def test_login_missing_password(self, use_case, mock_user_repo, test_user): """测试缺少密码""" mock_user_repo.find_by_email.return_value = test_user request = LoginRequest( email="test@example.com", password="", ) response, error = use_case.execute(request) assert response is None assert error == "Password is required" class TestLogoutUseCase: """登出用例测试""" @pytest.fixture def use_case(self): session_store = Mock() return LogoutUseCase(session_store=session_store) def test_logout_current_device(self, use_case): """测试登出当前设备""" use_case.session_store.delete_session.return_value = True request = LogoutRequest( user_id="user-123", session_id="session-abc", logout_all_devices=False, ) success, error = use_case.execute(request) assert success is True assert error is None use_case.session_store.delete_session.assert_called_once_with("session-abc") def test_logout_all_devices(self, use_case): """测试登出所有设备""" use_case.session_store.delete_all_user_sessions.return_value = 3 request = LogoutRequest( user_id="user-123", logout_all_devices=True, ) success, error = use_case.execute(request) assert success is True assert error is None use_case.session_store.delete_all_user_sessions.assert_called_once_with("user-123") def test_logout_session_not_found(self, use_case): """测试 session 不存在""" use_case.session_store.delete_session.return_value = False request = LogoutRequest( user_id="user-123", session_id="nonexistent", logout_all_devices=False, ) success, error = use_case.execute(request) assert success is False assert error == "Session not found" def test_logout_missing_session_id(self, use_case): """测试缺少 session_id""" request = LogoutRequest( user_id="user-123", session_id=None, logout_all_devices=False, ) success, error = use_case.execute(request) assert success is False assert error == "Session ID is required"