import os import pytest from httpx import ASGITransport, AsyncClient from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine import app.models # noqa: F401 — ensures all models register with Base.metadata from app.core.database import Base, get_session from app.main import app TEST_DATABASE_URL = os.getenv( "TEST_DATABASE_URL", "postgresql+asyncpg://postgres:postgres@localhost:5433/nuzlocke_test", ) @pytest.fixture(scope="session") async def engine(): """Create the test engine and schema once for the entire session.""" eng = create_async_engine(TEST_DATABASE_URL, echo=False) async with eng.begin() as conn: await conn.run_sync(Base.metadata.create_all) yield eng async with eng.begin() as conn: await conn.run_sync(Base.metadata.drop_all) await eng.dispose() @pytest.fixture async def db_session(engine): """ Provide a database session for a single test. Overrides the FastAPI get_session dependency so endpoint handlers use the same session. Truncates all tables after the test to isolate state. """ session_factory = async_sessionmaker(engine, expire_on_commit=False) session = session_factory() async def override_get_session(): yield session app.dependency_overrides[get_session] = override_get_session yield session await session.close() app.dependency_overrides.clear() async with engine.begin() as conn: for table in reversed(Base.metadata.sorted_tables): await conn.execute(table.delete()) @pytest.fixture async def client(db_session): """Async HTTP client wired to the FastAPI app with the test database session.""" async with AsyncClient( transport=ASGITransport(app=app), base_url="http://test" ) as ac: yield ac