from collections.abc import AsyncIterator from pathlib import Path import pytest from sqlalchemy.ext.asyncio import AsyncEngine from app.access.service import AccessService from app.config import AccessSettings, RuntimeSettings, Settings, TelegramSettings from app.db.migrate import upgrade from app.db.session import SessionMaker, make_engine, make_sessionmaker from app.texts import Texts, load_texts ROOT = Path(__file__).resolve().parent.parent ADMIN = 1001 OUTSIDER = 2002 @pytest.fixture def texts() -> Texts: return load_texts(ROOT / "config") @pytest.fixture def settings(tmp_path: Path) -> Settings: return Settings( telegram=TelegramSettings(bot_token="42:TEST-TOKEN"), access=AccessSettings(admin_ids=frozenset({ADMIN})), runtime=RuntimeSettings(config_dir=ROOT / "config", heartbeat_file=tmp_path / "hb"), ) @pytest.fixture async def engine() -> AsyncIterator[AsyncEngine]: """Fresh in-memory SQLite with all migrations applied — the same path the bot takes at startup.""" eng = make_engine("sqlite+aiosqlite://") await upgrade(eng) yield eng await eng.dispose() @pytest.fixture def sessions(engine: AsyncEngine) -> SessionMaker: return make_sessionmaker(engine) @pytest.fixture async def access(sessions: SessionMaker, settings: Settings) -> AccessService: service = AccessService(sessions, settings.access) await service.bootstrap_admins() return service