"""Shared pytest fixtures and configuration. Environment variables for testing are configured in pytest.ini via pytest-env plugin. """ from collections.abc import AsyncGenerator import pytest import pytest_asyncio from fakeredis import aioredis as fakeredis from capa_de_integracion.config import Settings from capa_de_integracion.services.storage import FirestoreService, RedisService # Configure pytest-asyncio pytest_plugins = ("pytest_asyncio",) @pytest.fixture(scope="session") def emulator_settings() -> Settings: """Create settings configured for Firestore emulator.""" # Settings will be loaded from environment variables set at module level return Settings.model_validate({}) @pytest_asyncio.fixture async def firestore_service( emulator_settings: Settings, ) -> AsyncGenerator[FirestoreService, None]: """Create FirestoreService instance connected to emulator.""" service = FirestoreService(emulator_settings) yield service # Cleanup: Close the service await service.close() @pytest_asyncio.fixture async def clean_firestore(firestore_service: FirestoreService) -> AsyncGenerator[FirestoreService, None]: """Provide a clean Firestore service and cleanup after test.""" # Cleanup before test await _cleanup_collections(firestore_service) yield firestore_service # Cleanup after test await _cleanup_collections(firestore_service) async def _cleanup_collections(service: FirestoreService) -> None: """Delete all documents from test collections.""" # Clean conversations collection conversations_ref = service.db.collection(service.conversations_collection) async for doc in conversations_ref.stream(): # Delete subcollection entries first entries_ref = doc.reference.collection(service.entries_subcollection) async for entry_doc in entries_ref.stream(): await entry_doc.reference.delete() # Delete session document await doc.reference.delete() # Clean notifications collection notifications_ref = service.db.collection(service.notifications_collection) async for doc in notifications_ref.stream(): await doc.reference.delete() @pytest_asyncio.fixture async def redis_service( emulator_settings: Settings, ) -> AsyncGenerator[RedisService, None]: """Create RedisService instance with fakeredis for testing.""" service = RedisService(emulator_settings) # Use fakeredis instead of connecting to a real Redis instance service.redis = await fakeredis.FakeRedis(decode_responses=True) yield service # Cleanup: Close the service await service.close() @pytest_asyncio.fixture async def clean_redis(redis_service: RedisService) -> AsyncGenerator[RedisService, None]: """Provide a clean Redis service and cleanup after test.""" # Cleanup before test await _cleanup_redis(redis_service) yield redis_service # Cleanup after test await _cleanup_redis(redis_service) async def _cleanup_redis(service: RedisService) -> None: """Delete all keys from Redis.""" if service.redis: # Delete all keys matching our patterns patterns = [ "conversation:*", "notification:*", ] for pattern in patterns: cursor = 0 while True: cursor, keys = await service.redis.scan(cursor, match=pattern, count=100) if keys: await service.redis.delete(*keys) if cursor == 0: break def pytest_recording_configure(config, vcr): """Configure pytest-recording for Firestore emulator.""" # Don't filter requests to the emulator vcr.ignore_hosts = [] # Match on method and path for emulator requests vcr.match_on = ["method", "path", "body"]