""" Pytest fixtures for integration tests. Uses SQLite in-memory (aiosqlite) for speed. Each test function gets a fresh database and HTTP client. """ import pytest import pytest_asyncio from httpx import ASGITransport, AsyncClient from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine from app.database import Base, get_session from app.main import app TEST_DATABASE_URL = "sqlite+aiosqlite:///:memory:" @pytest_asyncio.fixture async def test_engine(): engine = create_async_engine(TEST_DATABASE_URL, echo=False) async with engine.begin() as conn: await conn.run_sync(Base.metadata.create_all) yield engine async with engine.begin() as conn: await conn.run_sync(Base.metadata.drop_all) await engine.dispose() @pytest_asyncio.fixture async def db_session(test_engine): """Direct database session for use in fixtures and assertions.""" session_factory = async_sessionmaker(test_engine, expire_on_commit=False) async with session_factory() as session: yield session @pytest_asyncio.fixture async def client(test_engine) -> AsyncClient: """HTTP client wired to a fresh in-memory database.""" session_factory = async_sessionmaker(test_engine, expire_on_commit=False) async def override_get_session(): async with session_factory() as session: yield session app.dependency_overrides[get_session] = override_get_session async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as ac: yield ac app.dependency_overrides.clear() # --------------------------------------------------------------------------- # Helper factories # --------------------------------------------------------------------------- async def create_user_and_login( client: AsyncClient, email: str = "user@example.com", password: str = "password123", full_name: str = "Test User", ) -> tuple[dict, str]: """Register a user and return (user_json, access_token).""" reg_resp = await client.post( "/api/v1/auth/register", json={"email": email, "password": password, "full_name": full_name}, ) assert reg_resp.status_code == 201, reg_resp.text login_resp = await client.post( "/api/v1/auth/login", data={"username": email, "password": password}, headers={"Content-Type": "application/x-www-form-urlencoded"}, ) assert login_resp.status_code == 200, login_resp.text return reg_resp.json(), login_resp.json()["access_token"]