"""Shared test fixtures for kmtnflower backend tests.""" import os import pytest from unittest.mock import patch # Set test environment vars BEFORE any app imports # This is module-level so it runs when pytest loads this conftest os.environ.setdefault("KMTN_DATABASE_URL", "sqlite+aiosqlite:///file::memory:?cache=shared") os.environ.setdefault("KMTN_ENV", "test") os.environ.setdefault("KMTN_JWT_SECRET_KEY", "test-secret-key-do-not-use") os.environ.setdefault("KMTN_ADMIN_USERNAME", "testadmin") os.environ.setdefault("KMTN_ADMIN_PASSWORD", "testpass123") os.environ.setdefault("KMTN_LOGS_DIR", "/tmp/kmtn_test_logs") os.environ.setdefault("KMTN_GEOLITE2_DB_PATH", "/nonexistent/GeoLite2-City.mmdb") os.environ.setdefault("KMTN_THEME_JSON_PATH", "/tmp/kmtn_test_theme.json") # Use shared-cache in-memory SQLite so all connections within the process # see the same in-memory database (critical for tests that call the # login endpoint which opens its own DB connections). TEST_DB_URL = "sqlite+aiosqlite:///file::memory:?cache=shared" @pytest.fixture(autouse=True) def override_settings(): """Set test-only environment variables before any import of app modules.""" env = { "KMTN_DATABASE_URL": TEST_DB_URL, "KMTN_ENV": "test", "KMTN_JWT_SECRET_KEY": "test-secret-key-do-not-use", "KMTN_ADMIN_USERNAME": "testadmin", "KMTN_ADMIN_PASSWORD": "testpass123", "KMTN_LOGS_DIR": "/tmp/kmtn_test_logs", "KMTN_GEOLITE2_DB_PATH": "/nonexistent/GeoLite2-City.mmdb", "KMTN_THEME_JSON_PATH": "/tmp/kmtn_test_theme.json", } with patch.dict("os.environ", env, clear=False): yield env @pytest.fixture(autouse=True) async def reconfigure_database(): """Reconfigure the SQLAlchemy engine to use shared in-memory SQLite. Uses file::memory:?cache=shared so all connections within the process see the same in-memory database (critical for tests that call the login endpoint which opens its own DB connections). Drops all tables at the START of each test to ensure isolation. """ from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker from app import database from app.models import Base as ModelsBase # Create a new SQLite async engine with shared cache test_engine = create_async_engine(TEST_DB_URL, echo=False) test_session = async_sessionmaker( test_engine, class_=database.AsyncSession, expire_on_commit=False ) # Replace the module-level engine and session factory database.engine = test_engine database.async_session = test_session # Drop all tables to ensure test isolation (shared-cache persists across tests) # Then recreate them so fixture-dependent tests have a schema to work with. async with test_engine.begin() as conn: await conn.run_sync(ModelsBase.metadata.drop_all) await conn.run_sync(ModelsBase.metadata.create_all) yield test_engine # Dispose of the test engine after each test await test_engine.dispose()