import pytest import pytest_asyncio from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession from sqlmodel import SQLModel from sqlalchemy.orm import sessionmaker from httpx import AsyncClient, ASGITransport from app.main import app from app.database import get_session @pytest_asyncio.fixture(scope="function") async def engine(): """Create a fresh in-memory SQLite engine for each test.""" engine = create_async_engine( "sqlite+aiosqlite:///:memory:", echo=False, ) # Create tables for each test to ensure a clean state async with engine.begin() as conn: await conn.run_sync(SQLModel.metadata.create_all) yield engine await engine.dispose() @pytest_asyncio.fixture async def session_factory(engine): """Create async session factory.""" return sessionmaker(engine, class_=AsyncSession, expire_on_commit=False) @pytest_asyncio.fixture async def db_session(session_factory): """Create a database session for a test.""" async with session_factory() as session: yield session # Rollback is still good practice, though engine is fresh each time @pytest.fixture def sample_session_data(): """Sample sleep session data for testing.""" return { "start_time": "2024-01-15T21:30:00Z", } @pytest_asyncio.fixture async def api_client(db_session): """Provides an AsyncClient for testing API endpoints with the test database session.""" async def override(): yield db_session app.dependency_overrides[get_session] = override async with AsyncClient( transport=ASGITransport(app=app), base_url="http://test" ) as client: yield client app.dependency_overrides.clear()