From caa7eeab418c1a1de2eead7ed8c21ef4fcce4dec Mon Sep 17 00:00:00 2001 From: Alex Root Junior Date: Sun, 24 Nov 2019 00:17:21 +0200 Subject: [PATCH] Add tests for handler --- mypy.ini | 3 + tests/test_dispatcher/__init__.py | 0 tests/test_dispatcher/test_event/__init__.py | 0 .../test_event/test_handler.py | 176 ++++++++++++++++++ .../test_dispatcher/test_filters/__init__.py | 0 5 files changed, 179 insertions(+) create mode 100644 tests/test_dispatcher/__init__.py create mode 100644 tests/test_dispatcher/test_event/__init__.py create mode 100644 tests/test_dispatcher/test_event/test_handler.py create mode 100644 tests/test_dispatcher/test_filters/__init__.py diff --git a/mypy.ini b/mypy.ini index 976ba029..613933ec 100644 --- a/mypy.ini +++ b/mypy.ini @@ -1,2 +1,5 @@ [mypy] ignore_missing_imports = True +show_error_context = True +show_error_codes = True +pretty = True diff --git a/tests/test_dispatcher/__init__.py b/tests/test_dispatcher/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_dispatcher/test_event/__init__.py b/tests/test_dispatcher/test_event/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_dispatcher/test_event/test_handler.py b/tests/test_dispatcher/test_event/test_handler.py new file mode 100644 index 00000000..2607ab20 --- /dev/null +++ b/tests/test_dispatcher/test_event/test_handler.py @@ -0,0 +1,176 @@ +import functools +from typing import Any, Dict, Union + +import pytest + +from aiogram.dispatcher.event.handler import CallableMixin, FilterObject, HandlerObject +from aiogram.dispatcher.filters.base import BaseFilter + + +def callback1(foo: int, bar: int, baz: int): + return locals() + + +async def callback2(foo: int, bar: int, baz: int): + return locals() + + +async def callback3(foo: int, **kwargs): + return locals() + + +class Filter(BaseFilter): + async def __call__(self, foo: int, bar: int, baz: int) -> Union[bool, Dict[str, Any]]: + return locals() + + +class SyncCallable: + def __call__(self, foo, bar, baz): + return locals() + + +class TestCallableMixin: + @pytest.mark.parametrize("callback", [callback2, Filter()]) + def test_init_awaitable(self, callback): + obj = CallableMixin(callback) + assert obj.awaitable + assert obj.callback == callback + + @pytest.mark.parametrize("callback", [callback1, SyncCallable()]) + def test_init_not_awaitable(self, callback): + obj = CallableMixin(callback) + assert not obj.awaitable + assert obj.callback == callback + + @pytest.mark.parametrize( + "callback,args", + [ + pytest.param(callback1, {"foo", "bar", "baz"}), + pytest.param(callback2, {"foo", "bar", "baz"}), + pytest.param(callback3, {"foo"}), + pytest.param(Filter(), {"self", "foo", "bar", "baz"}), + pytest.param(SyncCallable(), {"self", "foo", "bar", "baz"}), + ], + ) + def test_init_args_spec(self, callback, args): + obj = CallableMixin(callback) + assert set(obj.spec.args) == args + + def test_init_decorated(self): + def decorator(func): + @functools.wraps(func) + def wrapper(*args, **kwargs): + return func(*args, **kwargs) + + return wrapper + + @decorator + def callback1(foo, bar, baz): + pass + + @decorator + @decorator + def callback2(foo, bar, baz): + pass + + obj1 = CallableMixin(callback1) + obj2 = CallableMixin(callback2) + + assert set(obj1.spec.args) == {"foo", "bar", "baz"} + assert obj1.callback == callback1 + assert set(obj2.spec.args) == {"foo", "bar", "baz"} + assert obj2.callback == callback2 + + @pytest.mark.parametrize( + "callback,kwargs,result", + [ + pytest.param( + callback1, {"foo": 42, "spam": True, "baz": "fuz"}, {"foo": 42, "baz": "fuz"} + ), + pytest.param( + callback2, + {"foo": 42, "spam": True, "baz": "fuz", "bar": "test"}, + {"foo": 42, "baz": "fuz", "bar": "test"}, + ), + pytest.param( + callback3, + {"foo": 42, "spam": True, "baz": "fuz", "bar": "test"}, + {"foo": 42, "spam": True, "baz": "fuz", "bar": "test"}, + ), + pytest.param( + Filter(), {"foo": 42, "spam": True, "baz": "fuz"}, {"foo": 42, "baz": "fuz"} + ), + pytest.param( + SyncCallable(), {"foo": 42, "spam": True, "baz": "fuz"}, {"foo": 42, "baz": "fuz"} + ), + ], + ) + def test_prepare_kwargs(self, callback, kwargs, result): + obj = CallableMixin(callback) + assert obj._prepare_kwargs(kwargs) == result + + @pytest.mark.asyncio + async def test_sync_call(self): + obj = CallableMixin(callback1) + + result = await obj.call(foo=42, bar="test", baz="fuz", spam=True) + assert result == {"foo": 42, "bar": "test", "baz": "fuz"} + + @pytest.mark.asyncio + async def test_async_call(self): + obj = CallableMixin(callback2) + + result = await obj.call(foo=42, bar="test", baz="fuz", spam=True) + assert result == {"foo": 42, "bar": "test", "baz": "fuz"} + + +async def simple_handler(*args, **kwargs): + return args, kwargs + + +class TestHandlerObject: + @pytest.mark.asyncio + async def test_check_with_bool_result(self): + handler = HandlerObject(simple_handler, [FilterObject(lambda value: True)] * 3) + result, data = await handler.check(42, foo=True) + assert result + assert data == {"foo": True} + + @pytest.mark.asyncio + async def test_check_with_dict_result(self): + handler = HandlerObject( + simple_handler, + [ + FilterObject( + functools.partial(lambda value, index: {f"test{index}": "ok"}, index=item) + ) + for item in range(3) + ], + ) + result, data = await handler.check(42, foo=True) + assert result + assert data == {"foo": True, "test0": "ok", "test1": "ok", "test2": "ok"} + + @pytest.mark.asyncio + async def test_check_with_combined_result(self): + handler = HandlerObject( + simple_handler, + [FilterObject(lambda value: True), FilterObject(lambda value: {"test": value})], + ) + result, data = await handler.check(42, foo=True) + assert result + assert data == {"foo": True, "test": 42} + + @pytest.mark.asyncio + async def test_check_rejected(self): + handler = HandlerObject(simple_handler, [FilterObject(lambda value: False)]) + result, data = await handler.check(42, foo=True) + assert not result + + @pytest.mark.asyncio + async def test_check_partial_rejected(self): + handler = HandlerObject( + simple_handler, [FilterObject(lambda value: True), FilterObject(lambda value: False)] + ) + result, data = await handler.check(42, foo=True) + assert not result diff --git a/tests/test_dispatcher/test_filters/__init__.py b/tests/test_dispatcher/test_filters/__init__.py new file mode 100644 index 00000000..e69de29b