import unittest from types import SimpleNamespace from unittest.mock import AsyncMock, patch from bot.app.web.admin_api_impl import webapp_runtime class AdminWebappRuntimeTests(unittest.IsolatedAsyncioTestCase): async def test_refresh_resets_settings_cache_and_invalidates_user_payloads(self): settings = SimpleNamespace() request = SimpleNamespace( app={ "settings": settings, "webapp_settings_cache": {"ts": 123.0, "data": {"stale": True}}, "subscription_guides_config_cache": { "fingerprint": ("stale",), "status": {"enabled": True}, }, } ) with patch.object( webapp_runtime, "invalidate_all_webapp_user_payloads", AsyncMock(), ) as invalidate_mock: await webapp_runtime.refresh_webapp_runtime_after_settings_change( request, updates={"SUBSCRIPTION_GUIDES_ENABLED": True}, deletes=[], ) self.assertEqual(request.app["webapp_settings_cache"], {"ts": 0.0, "data": {}}) self.assertEqual( request.app["subscription_guides_config_cache"], {"fingerprint": None, "status": None}, ) invalidate_mock.assert_awaited_once_with(settings, include_devices=False) async def test_refresh_clears_logo_cache_for_appearance_settings(self): settings = SimpleNamespace() request = SimpleNamespace( app={ "settings": settings, "webapp_settings_cache": {"ts": 123.0, "data": {"stale": True}}, "webapp_logo_cache": ("url", b"body", "image/png"), } ) with ( patch.object( webapp_runtime, "invalidate_all_webapp_user_payloads", AsyncMock(), ), patch( "bot.app.web.admin_api_impl.themes.prune_unused_appearance_assets" ) as prune_mock, ): await webapp_runtime.refresh_webapp_runtime_after_settings_change( request, updates={"WEBAPP_LOGO_URL": "/webapp-uploaded-logo/logo.png"}, deletes=[], ) self.assertIsNone(request.app["webapp_logo_cache"]) prune_mock.assert_called_once_with(settings)