Implement new middlewares

This commit is contained in:
Alex Root Junior 2020-05-26 00:23:35 +03:00
parent c262cc0ce6
commit 7f26ec9935
29 changed files with 532 additions and 1252 deletions

View file

@ -0,0 +1,59 @@
import functools
from typing import Any
import pytest
from aiogram.dispatcher.event.event import EventObserver
from aiogram.dispatcher.event.handler import HandlerObject
try:
from asynctest import CoroutineMock, patch
except ImportError:
from unittest.mock import AsyncMock as CoroutineMock, patch # type: ignore
async def my_handler(value: str, index: int = 0) -> Any:
return value
class TestEventObserver:
@pytest.mark.parametrize("via_decorator", [True, False])
@pytest.mark.parametrize("count,handler", ([5, my_handler], [3, my_handler], [2, my_handler]))
def test_register_filters(self, via_decorator, count, handler):
observer = EventObserver()
for index in range(count):
wrapped_handler = functools.partial(handler, index=index)
if via_decorator:
register_result = observer()(wrapped_handler)
assert register_result == wrapped_handler
else:
register_result = observer.register(wrapped_handler)
assert register_result is None
registered_handler = observer.handlers[index]
assert len(observer.handlers) == index + 1
assert isinstance(registered_handler, HandlerObject)
assert registered_handler.callback == wrapped_handler
assert not registered_handler.filters
@pytest.mark.asyncio
async def test_trigger(self):
observer = EventObserver()
observer.register(my_handler)
observer.register(lambda e: True)
observer.register(my_handler)
assert observer.handlers[0].awaitable
assert not observer.handlers[1].awaitable
assert observer.handlers[2].awaitable
with patch(
"aiogram.dispatcher.event.handler.CallableMixin.call", new_callable=CoroutineMock,
) as mocked_my_handler:
results = await observer.trigger("test")
assert results is None
mocked_my_handler.assert_awaited_with("test")
assert mocked_my_handler.call_count == 3

View file

@ -5,11 +5,14 @@ from typing import Any, Awaitable, Callable, Dict, NoReturn, Union
import pytest
from aiogram.api.types import Chat, Message, User
from aiogram.dispatcher.event.bases import SkipHandler
from aiogram.dispatcher.event.handler import HandlerObject
from aiogram.dispatcher.event.observer import EventObserver, SkipHandler, TelegramEventObserver
from aiogram.dispatcher.event.telegram import TelegramEventObserver
from aiogram.dispatcher.filters.base import BaseFilter
from aiogram.dispatcher.router import Router
# TODO: Test middlewares in routers tree
async def my_handler(event: Any, index: int = 0) -> Any:
return event
@ -38,54 +41,6 @@ class MyFilter3(MyFilter1):
pass
class TestEventObserver:
@pytest.mark.parametrize("count,handler", ([5, my_handler], [3, my_handler], [2, my_handler]))
def test_register_filters(self, count, handler):
observer = EventObserver()
for index in range(count):
wrapped_handler = functools.partial(handler, index=index)
observer.register(wrapped_handler)
registered_handler = observer.handlers[index]
assert len(observer.handlers) == index + 1
assert isinstance(registered_handler, HandlerObject)
assert registered_handler.callback == wrapped_handler
assert not registered_handler.filters
@pytest.mark.parametrize("count,handler", ([5, my_handler], [3, my_handler], [2, my_handler]))
def test_register_filters_via_decorator(self, count, handler):
observer = EventObserver()
for index in range(count):
wrapped_handler = functools.partial(handler, index=index)
observer()(wrapped_handler)
registered_handler = observer.handlers[index]
assert len(observer.handlers) == index + 1
assert isinstance(registered_handler, HandlerObject)
assert registered_handler.callback == wrapped_handler
assert not registered_handler.filters
@pytest.mark.asyncio
async def test_trigger_accepted_bool(self):
observer = EventObserver()
observer.register(my_handler)
results = [result async for result in observer.trigger(42)]
assert results == [42]
@pytest.mark.asyncio
async def test_trigger_with_skip(self):
observer = EventObserver()
observer.register(skip_my_handler)
observer.register(my_handler)
observer.register(my_handler)
results = [result async for result in observer.trigger(42)]
assert results == [42, 42]
class TestTelegramEventObserver:
def test_bind_filter(self):
event_observer = TelegramEventObserver(Router(), "test")
@ -198,8 +153,8 @@ class TestTelegramEventObserver:
from_user=User(id=42, is_bot=False, first_name="Test"),
)
results = [result async for result in observer.trigger(message)]
assert results == [message]
results = await observer.trigger(message)
assert results is message
@pytest.mark.parametrize(
"count,handler,filters",
@ -223,15 +178,58 @@ class TestTelegramEventObserver:
assert registered_handler.callback == wrapped_handler
assert len(registered_handler.filters) == len(filters)
#
@pytest.mark.asyncio
async def test_trigger_right_context_in_handlers(self):
router = Router(use_builtin_filters=False)
observer = router.message
observer.register(
pipe_handler, lambda event: {"a": 1}, lambda event: False
) # {"a": 1} should not be in result
observer.register(pipe_handler, lambda event: {"b": 2})
results = [result async for result in observer.trigger(42)]
assert results == [((42,), {"b": 2})]
async def mix_unnecessary_data(event):
return {"a": 1}
async def mix_data(event):
return {"b": 2}
async def handler(event, **kwargs):
return False
observer.register(
pipe_handler, mix_unnecessary_data, handler
) # {"a": 1} should not be in result
observer.register(pipe_handler, mix_data)
results = await observer.trigger(42)
assert results == ((42,), {"b": 2})
@pytest.mark.parametrize("middleware_type", ("middleware", "outer_middleware"))
def test_register_middleware(self, middleware_type):
event_observer = TelegramEventObserver(Router(), "test")
middlewares = getattr(event_observer, f"{middleware_type}s")
decorator = getattr(event_observer, middleware_type)
@decorator
async def my_middleware1(handler, event, data):
pass
assert my_middleware1 is not None
assert my_middleware1.__name__ == "my_middleware1"
assert my_middleware1 in middlewares
@decorator()
async def my_middleware2(handler, event, data):
pass
assert my_middleware2 is not None
assert my_middleware2.__name__ == "my_middleware2"
assert my_middleware2 in middlewares
async def my_middleware3(handler, event, data):
pass
decorator(my_middleware3)
assert my_middleware3 is not None
assert my_middleware3.__name__ == "my_middleware3"
assert my_middleware3 in middlewares
assert middlewares == [my_middleware1, my_middleware2, my_middleware3]