import os import pytest_asyncio from httpx import ASGITransport, AsyncClient from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine # Provide required settings for the test environment before any app imports resolve them os.environ.setdefault("JWT_SECRET_KEY", "test-secret-key-for-testing-only") os.environ.setdefault("OWNER_USERNAME", "testowner") os.environ.setdefault("OWNER_PASSWORD", "testpassword") from app.auth.jwt_provider import JWTAuthProvider from app.config import get_settings from app.database import Base from app.dependencies import get_auth, get_db, get_storage from app.main import app # Bust the LRU cache so get_settings() picks up the env vars set above get_settings.cache_clear() _TEST_JWT_SECRET = os.environ["JWT_SECRET_KEY"] _TEST_OWNER_USERNAME = os.environ["OWNER_USERNAME"] _TEST_OWNER_PASSWORD = os.environ["OWNER_PASSWORD"] @pytest_asyncio.fixture(scope="session", loop_scope="session") async def engine(): settings = get_settings() # Use a separate test database URL if TEST_DATABASE_URL is set import os db_url = os.getenv("TEST_DATABASE_URL", settings.database_url) eng = create_async_engine(db_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_asyncio.fixture async def db_session(engine): session_factory = async_sessionmaker(engine, expire_on_commit=False) async with session_factory() as session: yield session await session.rollback() @pytest_asyncio.fixture async def client(db_session): from app.auth.noop import NoOpAuthProvider from app.storage.s3_backend import S3StorageBackend storage = S3StorageBackend() auth = NoOpAuthProvider() async def override_db(): yield db_session def override_storage(): return storage def override_auth(): return auth app.dependency_overrides[get_db] = override_db app.dependency_overrides[get_storage] = override_storage app.dependency_overrides[get_auth] = override_auth async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as c: yield c app.dependency_overrides.clear() @pytest_asyncio.fixture async def jwt_auth_provider() -> JWTAuthProvider: return JWTAuthProvider( secret_key=_TEST_JWT_SECRET, expiry_seconds=3600, owner_username=_TEST_OWNER_USERNAME, owner_password=_TEST_OWNER_PASSWORD, ) @pytest_asyncio.fixture async def authed_client(db_session, jwt_auth_provider): from app.storage.s3_backend import S3StorageBackend storage = S3StorageBackend() auth = jwt_auth_provider async def override_db(): yield db_session def override_storage(): return storage def override_auth(): return auth app.dependency_overrides[get_db] = override_db app.dependency_overrides[get_storage] = override_storage app.dependency_overrides[get_auth] = override_auth valid_token = auth.create_token() async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as c: yield c, valid_token app.dependency_overrides.clear()