diff --git a/maxapi/bot.py b/maxapi/bot.py index a434982..0828d7c 100644 --- a/maxapi/bot.py +++ b/maxapi/bot.py @@ -410,7 +410,7 @@ async def send_message( async def send_action( self, chat_id: int | None = None, - action: SenderAction = SenderAction.TYPING_ON, + action: SenderAction | str = SenderAction.TYPING_ON, ) -> SendedAction: """ Отправляет действие в чат (например, "печатает"). @@ -419,12 +419,11 @@ async def send_action( Args: chat_id (Optional[int]): ID чата. - action (SenderAction): Тип действия. + action (SenderAction | str): Тип действия. Returns: SendedAction: Результат отправки действия. """ - return await SendAction( bot=self, chat_id=chat_id, action=action ).fetch() diff --git a/maxapi/methods/send_action.py b/maxapi/methods/send_action.py index 54ed424..af8c748 100644 --- a/maxapi/methods/send_action.py +++ b/maxapi/methods/send_action.py @@ -21,7 +21,7 @@ class SendAction(BaseConnection): bot (Bot): Экземпляр бота для выполнения запроса. chat_id (Optional[int]): Идентификатор чата. Если None, действие не отправляется. - action (Optional[SenderAction]): Тип действия. По умолчанию + action (SenderAction | str): Тип действия. По умолчанию SenderAction.TYPING_ON. """ @@ -29,9 +29,25 @@ def __init__( self, bot: "Bot", chat_id: int | None = None, - action: SenderAction = SenderAction.TYPING_ON, + action: SenderAction | str = SenderAction.TYPING_ON, ): super().__init__() + + if not isinstance(action, SenderAction): + if not isinstance(action, str): + raise TypeError( + f"action должен быть SenderAction или str, " + f"получено: {type(action).__name__}" + ) + + try: + action = SenderAction(action) + except ValueError as e: + allowed = ", ".join(item.value for item in SenderAction) + raise ValueError( + f"Неверный action: {action!r}. Ожидается: {allowed}" + ) from e + self.bot = bot self.chat_id = chat_id self.action = action diff --git a/tests/test_bot.py b/tests/test_bot.py index 661f8a6..b388792 100644 --- a/tests/test_bot.py +++ b/tests/test_bot.py @@ -185,6 +185,78 @@ async def test_send_action_call(self, bot): assert mock_fetch.called + @pytest.mark.asyncio + async def test_send_invalid_action_as_string(self, bot): + """Тест вызова send_action с неверными данными.""" + # Core Stuff + from maxapi.methods.send_action import SendAction + + available_actions = ", ".join(action.value for action in SenderAction) + + with patch.object( + SendAction, "fetch", new_callable=AsyncMock + ) as mock_fetch: + mock_fetch.return_value = Mock() + + with pytest.raises(ValueError) as exc_info: # noqa: PT011 + await bot.send_action(chat_id=12345, action="fake_action") + + exc_message = str(exc_info.value) + + assert "Неверный" in exc_message + assert available_actions in exc_message + + @pytest.mark.asyncio + async def test_send_valid_action_as_string(self, bot): + """Тест вызова send_action с верными данными.""" + # Core Stuff + from maxapi.methods.send_action import SendAction + + with patch.object( + SendAction, "fetch", new_callable=AsyncMock + ) as mock_fetch: + mock_fetch.return_value = Mock() + + await bot.send_action(chat_id=12345, action="typing_on") + + assert mock_fetch.called + + @pytest.mark.asyncio + async def test_send_action_without_action_param(self, bot): + """Тест вызова send_action без передачи action.""" + # Core Stuff + from maxapi.methods.send_action import SendAction + + with patch.object( + SendAction, "fetch", new_callable=AsyncMock + ) as mock_fetch: + mock_fetch.return_value = Mock() + + await bot.send_action(chat_id=12345) + + assert mock_fetch.called + + @pytest.mark.asyncio + async def test_send_action_with_wrong_action_type(self, bot): + """Тест вызова send_action с передачей неверного типа (не SenderAction, не str).""" # noqa: E501 + # Core Stuff + from maxapi.methods.send_action import SendAction + + with patch.object( + SendAction, "fetch", new_callable=AsyncMock + ) as mock_fetch: + mock_fetch.return_value = Mock() + + wrong_action = 123 + wrong_action_type = type(wrong_action).__name__ + + with pytest.raises(TypeError) as exc_info: + await bot.send_action(chat_id=12345, action=wrong_action) + + exc_message = str(exc_info.value) + + assert wrong_action_type in exc_message + @pytest.mark.asyncio async def test_get_me_structure(self, bot): """Тест структуры вызова get_me."""