from __future__ import annotations from unittest.mock import AsyncMock, MagicMock, patch import aiohttp import pytest from fastapi import FastAPI from starlette.requests import Request from app.config import Settings from app.dependencies import ( ApplicationContext, get_app_context, get_db, get_history_archive_repo, get_http_session, get_scheduler, get_session_cache, get_settings, get_settings_repo, ) from app.main import create_app from app.models.server import ServerStatus def _make_test_request(app: FastAPI) -> Request: scope = { "type": "http", "method": "GET", "path": "/", "headers": [], "query_string": b"", "client": ("test", 0), "server": ("test", 0), "scheme": "http", "app": app, } return Request(scope) @pytest.mark.asyncio async def test_app_context_dependency_exposes_shared_resources(test_settings: Settings) -> None: app = create_app(settings=test_settings) session = aiohttp.ClientSession() scheduler = MagicMock() app.state.http_session = session app.state.scheduler = scheduler app.state.server_status = ServerStatus(online=False) app.state.pending_recovery = None app.state.last_activation = None request = _make_test_request(app) app_context = await get_app_context(request) assert isinstance(app_context, ApplicationContext) assert app_context.settings is test_settings assert app_context.http_session is session assert app_context.scheduler is scheduler assert app_context.session_cache is app.state.session_cache assert app_context.runtime_state is app.state.runtime_state assert await get_settings(app_context) is test_settings assert await get_http_session(app_context) is session assert await get_scheduler(app_context) is scheduler assert await get_session_cache(app_context) is app.state.session_cache await session.close() @pytest.mark.asyncio async def test_settings_and_history_archive_repo_dependencies_return_modules() -> None: settings_repo = await get_settings_repo() history_archive_repo = await get_history_archive_repo() assert hasattr(settings_repo, "get_setting") assert hasattr(settings_repo, "set_setting") assert hasattr(settings_repo, "delete_setting") assert hasattr(settings_repo, "get_all_settings") assert hasattr(history_archive_repo, "archive_ban_event") assert hasattr(history_archive_repo, "get_max_timeofban") assert hasattr(history_archive_repo, "get_archived_history") @pytest.mark.asyncio async def test_get_db_uses_effective_runtime_database_path(test_settings: Settings) -> None: """Database connections should use effective runtime settings when overridden.""" runtime_settings = test_settings.model_copy(update={"database_path": "/tmp/runtime.db"}) mock_connection = MagicMock() mock_connection.close = AsyncMock() with patch("app.db.open_db", new=AsyncMock(return_value=mock_connection)) as mock_open_db: gen = get_db(settings=runtime_settings) try: connection = await gen.__anext__() assert connection is mock_connection finally: await gen.aclose() mock_open_db.assert_awaited_once_with("/tmp/runtime.db")