Callback answer feature (#1091)

* Added callback answer feature

* Fixed typehints and tests

* Make context manager in tests compatible with Python 3.8
This commit is contained in:
Alex Root Junior 2023-01-08 16:49:34 +02:00 committed by GitHub
parent 2e59adefe6
commit 04ccb390d5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 574 additions and 30 deletions

View file

@ -0,0 +1,217 @@
from unittest.mock import AsyncMock, MagicMock, patch
import pytest
from aiogram.exceptions import CallbackAnswerException
from aiogram.methods import AnswerCallbackQuery
from aiogram.types import CallbackQuery, User
from aiogram.utils.callback_answer import CallbackAnswer, CallbackAnswerMiddleware
class TestCallbackAnswer:
@pytest.mark.parametrize(
"name,value",
[
["answered", True],
["answered", False],
["disabled", True],
["disabled", False],
["text", "test"],
["text", None],
["show_alert", True],
["show_alert", False],
["show_alert", None],
["url", "https://example.com"],
["url", None],
["cache_time", None],
["cache_time", 10],
],
)
def test_getters(self, name, value):
kwargs = {
"answered": False,
name: value,
}
instance = CallbackAnswer(**kwargs)
result = getattr(instance, name)
assert result == value
@pytest.mark.parametrize(
"name,value",
[
["disabled", True],
["disabled", False],
["text", None],
["text", ""],
["text", "test"],
["show_alert", None],
["show_alert", True],
["show_alert", False],
["url", None],
["url", "https://example.com"],
["cache_time", None],
["cache_time", 0],
["cache_time", 10],
],
)
def test_setter_allowed(self, name, value):
instance = CallbackAnswer(answered=False)
setattr(instance, name, value)
assert getattr(instance, name) == value
@pytest.mark.parametrize(
"name",
[
"disabled",
"text",
"show_alert",
"url",
"cache_time",
],
)
def test_setter_blocked(self, name):
instance = CallbackAnswer(answered=True)
with pytest.raises(CallbackAnswerException):
setattr(instance, name, "test")
def test_disable(self):
instance = CallbackAnswer(answered=False)
assert not instance.disabled
instance.disable()
assert instance.disabled
def test_str(self):
instance = CallbackAnswer(answered=False, text="test")
assert str(instance) == "CallbackAnswer(answered=False, disabled=False, text='test')"
class TestCallbackAnswerMiddleware:
@pytest.mark.parametrize(
"init_kwargs,flag_properties,expected",
[
[
{},
True,
{
"answered": False,
"disabled": False,
"text": None,
"show_alert": None,
"url": None,
"cache_time": None,
},
],
[
{
"pre": True,
"text": "test",
"show_alert": True,
"url": "https://example.com",
"cache_time": 5,
},
True,
{
"answered": True,
"disabled": False,
"text": "test",
"show_alert": True,
"url": "https://example.com",
"cache_time": 5,
},
],
[
{
"pre": False,
"text": "test",
"show_alert": True,
"url": "https://example.com",
"cache_time": 5,
},
{
"pre": True,
"disabled": True,
"text": "another test",
"show_alert": False,
"url": "https://example.com/game.html",
"cache_time": 10,
},
{
"answered": True,
"disabled": True,
"text": "another test",
"show_alert": False,
"url": "https://example.com/game.html",
"cache_time": 10,
},
],
],
)
def test_construct_answer(self, init_kwargs, flag_properties, expected):
middleware = CallbackAnswerMiddleware(**init_kwargs)
callback_answer = middleware.construct_callback_answer(properties=flag_properties)
for key, value in expected.items():
assert getattr(callback_answer, key) == value
def test_answer(self):
middleware = CallbackAnswerMiddleware()
event = CallbackQuery(
id="1",
from_user=User(id=42, first_name="Test", is_bot=False),
chat_instance="test",
)
callback_answer = CallbackAnswer(
answered=False,
disabled=False,
text="another test",
show_alert=False,
url="https://example.com/game.html",
cache_time=10,
)
method = middleware.answer(event=event, callback_answer=callback_answer)
assert isinstance(method, AnswerCallbackQuery)
assert method.text == callback_answer.text
assert method.show_alert == callback_answer.show_alert
assert method.url == callback_answer.url
assert method.cache_time == callback_answer.cache_time
@pytest.mark.parametrize(
"properties,expected_stack",
[
[{"answered": False}, ["handler", "answer"]],
[{"answered": True}, ["answer", "handler"]],
[{"disabled": True}, ["handler"]],
],
)
async def test_call(self, properties, expected_stack):
stack = []
event = CallbackQuery(
id="1",
from_user=User(id=42, first_name="Test", is_bot=False),
chat_instance="test",
)
async def handler(*args, **kwargs):
stack.append("handler")
async def answer(*args, **kwargs):
stack.append("answer")
middleware = CallbackAnswerMiddleware()
with patch(
"aiogram.utils.callback_answer.CallbackAnswerMiddleware.construct_callback_answer",
new_callable=MagicMock,
side_effect=lambda **kwargs: CallbackAnswer(**{"answered": False, **properties}),
), patch(
"aiogram.utils.callback_answer.CallbackAnswerMiddleware.answer",
new=answer,
):
await middleware(handler, event, {})
assert stack == expected_stack
async def test_invalid_event_type(self):
middleware = CallbackAnswerMiddleware()
handler = AsyncMock()
await middleware(handler, None, {})
handler.assert_awaited()