# tests/core/conftest.py import shutil from datetime import datetime, timedelta from pathlib import Path from unittest.mock import MagicMock import pytest from myauth.core.password import PasswordManager from myauth.core.token import TokenManager from myauth.core.auth import AuthService from myauth.models.user import UserCreate, UserInDB from myauth.persistence.sqlite import SQLiteUserRepository, SQLiteTokenRepository @pytest.fixture def test_user_data_create(): """Provides valid data for creating a test user.""" return UserCreate( email="test.service@example.com", username="TestServiceUser", password="ValidPassword123!", roles=["member"], user_settings={"theme": "dark"} ) @pytest.fixture def test_user_hashed_password(): """Provides a dummy hashed password (only used internally by service)""" # Note: In service tests, we rely on the service to do the hashing/verification, # but this is kept for completeness if needed elsewhere. return "$2b$12$R.S/XfI2tQYt3Kk.iF1XwOQz0Qe.L0T0mD/O1H8E2V5D4Q6F7G8H9I0" @pytest.fixture def test_user_in_db() -> UserInDB: """Provides a basic UserInDB instance for testing.""" return UserInDB( id="1", email="test@example.com", username="testuser", hashed_password="some_hash", is_active=True, is_verified=True, roles=['member'], user_settings={}, created_at=datetime.now(), updated_at=datetime.now() ) @pytest.fixture() def sqlite_db_path(tmp_path_factory): """ Creates a temporary directory and an SQLite file path for the test session. The directory is deleted after the session. """ temp_dir = tmp_path_factory.mktemp("sqlite_auth_service_test") db_file: Path = temp_dir / "auth_service_test.db" yield str(db_file) # Cleanup phase try: if temp_dir.exists(): shutil.rmtree(temp_dir) except OSError as e: print(f"Error during cleanup of temporary DB directory: {e}") @pytest.fixture def user_repository(sqlite_db_path: str) -> SQLiteUserRepository: """Provides a real SQLiteUserRepository instance.""" return SQLiteUserRepository(db_path=sqlite_db_path) @pytest.fixture def token_repository(sqlite_db_path: str) -> SQLiteTokenRepository: """Provides a real SQLiteTokenRepository instance.""" return SQLiteTokenRepository(db_path=sqlite_db_path) @pytest.fixture def mock_password_manager() -> PasswordManager: """Provides a PasswordManager instance for injection (low rounds for speed).""" mock = MagicMock(spec=PasswordManager) mock.hash_password.return_value = "PREDICTABLE_HASHED_PASSWORD_FOR_TESTING" mock.verify_password.return_value = True return mock @pytest.fixture def mock_token_manager() -> TokenManager: """Provides a TokenManager instance for injection (fast expiration settings).""" mock = MagicMock(spec=TokenManager) mock.create_access_token.return_value = "MOCKED_ACCESS_TOKEN" mock.create_refresh_token.return_value = "MOCKED_REFRESH_TOKEN" mock.get_refresh_token_expiration.return_value = datetime.now() + timedelta(days=1) return mock # --- Service Fixture --- @pytest.fixture def auth_service(user_repository: SQLiteUserRepository, token_repository: SQLiteTokenRepository, mock_password_manager: PasswordManager, mock_token_manager: TokenManager ) -> AuthService: """ Provides an AuthService instance initialized with real repositories. """ # NOTE: To test hashing/verification, we must ensure password_hash_rounds is low. # NOTE: To simplify JWT testing, we mock the internal components (hashing/JWT) # as the AuthService shouldn't be responsible for these core algorithms, # only for orchestrating them. If your service integrates them directly, # we'll need to patch them below. return AuthService( user_repository=user_repository, token_repository=token_repository, password_manager=mock_password_manager, token_manager=mock_token_manager, )