# backend/tests/conftest.py from typing import AsyncGenerator, Generator import pytest from app.core.auth import get_admin_user, get_optional_user from app.database import Base, get_db # Import your app and models from app.main import app from fastapi import Request from httpx import ASGITransport, AsyncClient from sqlalchemy import create_engine from sqlalchemy.orm import Session, sessionmaker from sqlalchemy.pool import StaticPool # --- DATABASE SETUP --- # Use in-memory SQLite. # StaticPool is CRITICAL for in-memory SQLite with async tests to share connection. SQLALCHEMY_DATABASE_URL = "sqlite:///" engine = create_engine( SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}, poolclass=StaticPool, ) TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) @pytest.fixture(scope="session") def prepare_db(): Base.metadata.create_all(bind=engine) yield Base.metadata.drop_all(bind=engine) @pytest.fixture(scope="function") def db(prepare_db) -> Generator[Session, None, None]: connection = engine.connect() transaction = connection.begin() session = TestingSessionLocal(bind=connection) yield session session.close() transaction.rollback() connection.close() @pytest.fixture(scope="function") async def client(db: Session) -> AsyncGenerator[AsyncClient, None]: def override_get_db(): try: yield db finally: pass # Strict Auth: Always requires a token (simulated by header presence) def override_get_admin_user(request: Request): if "Authorization" not in request.headers: # Let FastAPI raise the 401 naturally if header is missing raise pytest.skip("Auth header missing in strict auth test") return "test_admin" # Optional Auth: Returns Admin IF header exists, else None def override_get_optional_user(request: Request): if "Authorization" in request.headers: return "test_admin" return None app.dependency_overrides[get_db] = override_get_db app.dependency_overrides[get_admin_user] = override_get_admin_user app.dependency_overrides[get_optional_user] = override_get_optional_user async with AsyncClient( transport=ASGITransport(app=app), base_url="http://test" ) as c: yield c app.dependency_overrides.clear() # --- HELPER FIXTURES --- @pytest.fixture def auth_headers(client): return {"Authorization": "Bearer test_token"} @pytest.fixture def valid_tournament_payload(): return { "name": "Test Tournament", "code": "1234", "type": "Double", "timestamp": "2024-01-01T10:00:00", "duration": 15, "teams": ["Team A", "Team B", "Team C", "Team D"], "courts": ["Court 1", "Court 2"], }