from collections.abc import Awaitable, Callable from datetime import datetime from typing import Any from unittest.mock import AsyncMock import pytest from aiogram import BaseMiddleware, Dispatcher, F from aiogram.enums import ChatType from aiogram.filters import Command from aiogram.fsm.scene import Scene, SceneRegistry, ScenesManager, on from aiogram.types import Chat, Message, TelegramObject, Update, User from tests.mocked_bot import MockedBot class EchoScene(Scene, state="test"): @on.message.enter() async def greetings(self, message: Message, test_context: str): await message.answer(f"Echo mode enabled. Context: {test_context}.") @on.message(F.text) async def echo(self, message: Message, test_context: str): await message.reply(f"Your input: {message.text} and Context: {test_context}.") class TestMiddleware(BaseMiddleware): async def __call__( self, handler: Callable[[TelegramObject, dict[str, Any]], Awaitable[Any]], event: TelegramObject, data: dict[str, Any], ) -> Any: data["test_context"] = "Custom context here" return await handler(event, data) @pytest.mark.asyncio async def test_middleware_data_passed_to_scene(bot: MockedBot): """Test that middleware data is correctly passed to the scene when using as_handler().""" # Create a dispatcher dp = Dispatcher() # Register the scene handler with the command filter dp.message.register(EchoScene.as_handler(), Command("test")) # Register the scene with the registry scene_registry = SceneRegistry(dp) scene_registry.add(EchoScene) # Register the middleware dp.message.outer_middleware.register(TestMiddleware()) # Create a proper message with the command chat = Chat(id=123, type=ChatType.PRIVATE) user = User(id=456, is_bot=False, first_name="Test User") message = Message(message_id=1, date=datetime.now(), from_user=user, chat=chat, text="/test") update = Update(message=message, update_id=1) # Mock the ScenesManager.enter method original_enter = ScenesManager.enter ScenesManager.enter = AsyncMock() try: # Process the update await dp.feed_update(bot, update) # Verify that ScenesManager.enter was called with the test_context from middleware ScenesManager.enter.assert_called_once() args, kwargs = ScenesManager.enter.call_args assert "test_context" in kwargs assert kwargs["test_context"] == "Custom context here" finally: # Restore the original method ScenesManager.enter = original_enter