# tests/core/conftest.py import shutil from datetime import datetime, timedelta from pathlib import Path from unittest.mock import MagicMock import pytest from my_auth.core.password import PasswordManager from my_auth.core.token import TokenManager from src.my_auth.core.auth import AuthService from src.my_auth.models.user import UserCreate, UserInDB from src.my_auth.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, )