mirror of
https://github.com/aiogram/aiogram.git
synced 2025-12-06 07:50:32 +00:00
More class based handlers
This commit is contained in:
parent
b144332287
commit
895b727ddf
24 changed files with 506 additions and 30 deletions
|
|
@ -1,4 +1,21 @@
|
|||
from .base import BaseHandler, BaseHandlerMixin
|
||||
from .callback_query import CallbackQueryHandler
|
||||
from .chosen_inline_result import ChosenInlineResultHandler
|
||||
from .inline_query import InlineQueryHandler
|
||||
from .message import MessageHandler, MessageHandlerCommandMixin
|
||||
from .poll import PollHandler
|
||||
from .pre_checkout_query import PreCheckoutQueryHandler
|
||||
from .shipping_query import ShippingQueryHandler
|
||||
|
||||
__all__ = ("BaseHandler", "BaseHandlerMixin", "MessageHandler", "MessageHandlerCommandMixin")
|
||||
__all__ = (
|
||||
"BaseHandler",
|
||||
"BaseHandlerMixin",
|
||||
"CallbackQueryHandler",
|
||||
"ChosenInlineResultHandler",
|
||||
"InlineQueryHandler",
|
||||
"MessageHandler",
|
||||
"MessageHandlerCommandMixin",
|
||||
"PollHandler",
|
||||
"PreCheckoutQueryHandler",
|
||||
"ShippingQueryHandler",
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,23 +1,25 @@
|
|||
from abc import ABC, abstractmethod
|
||||
from typing import Any, Dict
|
||||
from typing import TYPE_CHECKING, Any, Dict, Generic, TypeVar
|
||||
|
||||
from aiogram import Bot
|
||||
from aiogram.api.types import TelegramObject
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
class BaseHandlerMixin:
|
||||
class BaseHandlerMixin(Generic[T]):
|
||||
if TYPE_CHECKING: # pragma: no cover
|
||||
event: T
|
||||
data: Dict[str, Any]
|
||||
|
||||
|
||||
class BaseHandler(BaseHandlerMixin[T], ABC):
|
||||
"""
|
||||
Typed mixin. Do nothing.
|
||||
Base class for all class-based handlers
|
||||
"""
|
||||
|
||||
event: TelegramObject
|
||||
data: Dict[str, Any]
|
||||
|
||||
|
||||
class _HandlerBotMixin(BaseHandlerMixin):
|
||||
"""
|
||||
Mixin adds bot attribute
|
||||
"""
|
||||
def __init__(self, event: T, **kwargs: Any) -> None:
|
||||
self.event: T = event
|
||||
self.data: Dict[str, Any] = kwargs
|
||||
|
||||
@property
|
||||
def bot(self) -> Bot:
|
||||
|
|
@ -25,16 +27,6 @@ class _HandlerBotMixin(BaseHandlerMixin):
|
|||
return self.data["bot"]
|
||||
return Bot.get_current()
|
||||
|
||||
|
||||
class BaseHandler(_HandlerBotMixin, ABC):
|
||||
"""
|
||||
Base class for all class-based handlers
|
||||
"""
|
||||
|
||||
def __init__(self, event: TelegramObject, **kwargs: Any) -> None:
|
||||
self.event = event
|
||||
self.data = kwargs
|
||||
|
||||
@abstractmethod
|
||||
async def handle(self) -> Any: # pragma: no cover
|
||||
pass
|
||||
|
|
|
|||
23
aiogram/dispatcher/handler/callback_query.py
Normal file
23
aiogram/dispatcher/handler/callback_query.py
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
from abc import ABC
|
||||
from typing import Optional
|
||||
|
||||
from aiogram.api.types import CallbackQuery, Message, User
|
||||
from aiogram.dispatcher.handler import BaseHandler
|
||||
|
||||
|
||||
class CallbackQueryHandler(BaseHandler[CallbackQuery], ABC):
|
||||
"""
|
||||
Base class for callback query handlers
|
||||
"""
|
||||
|
||||
@property
|
||||
def from_user(self) -> User:
|
||||
return self.event.from_user
|
||||
|
||||
@property
|
||||
def message(self) -> Optional[Message]:
|
||||
return self.event.message
|
||||
|
||||
@property
|
||||
def callback_data(self) -> Optional[str]:
|
||||
return self.event.data
|
||||
18
aiogram/dispatcher/handler/chosen_inline_result.py
Normal file
18
aiogram/dispatcher/handler/chosen_inline_result.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
from abc import ABC
|
||||
|
||||
from aiogram.api.types import ChosenInlineResult, User
|
||||
from aiogram.dispatcher.handler import BaseHandler
|
||||
|
||||
|
||||
class ChosenInlineResultHandler(BaseHandler[ChosenInlineResult], ABC):
|
||||
"""
|
||||
Base class for chosen inline result handlers
|
||||
"""
|
||||
|
||||
@property
|
||||
def from_user(self) -> User:
|
||||
return self.event.from_user
|
||||
|
||||
@property
|
||||
def query(self) -> str:
|
||||
return self.event.query
|
||||
18
aiogram/dispatcher/handler/inline_query.py
Normal file
18
aiogram/dispatcher/handler/inline_query.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
from abc import ABC
|
||||
|
||||
from aiogram.api.types import InlineQuery, User
|
||||
from aiogram.dispatcher.handler import BaseHandler
|
||||
|
||||
|
||||
class InlineQueryHandler(BaseHandler[InlineQuery], ABC):
|
||||
"""
|
||||
Base class for inline query handlers
|
||||
"""
|
||||
|
||||
@property
|
||||
def from_user(self) -> User:
|
||||
return self.event.from_user
|
||||
|
||||
@property
|
||||
def query(self) -> str:
|
||||
return self.event.query
|
||||
|
|
@ -6,8 +6,10 @@ from aiogram.dispatcher.filters import CommandObject
|
|||
from aiogram.dispatcher.handler.base import BaseHandler, BaseHandlerMixin
|
||||
|
||||
|
||||
class MessageHandler(BaseHandler, ABC):
|
||||
event: Message
|
||||
class MessageHandler(BaseHandler[Message], ABC):
|
||||
"""
|
||||
Base class for message handlers
|
||||
"""
|
||||
|
||||
@property
|
||||
def from_user(self) -> Optional[User]:
|
||||
|
|
@ -18,7 +20,7 @@ class MessageHandler(BaseHandler, ABC):
|
|||
return self.event.chat
|
||||
|
||||
|
||||
class MessageHandlerCommandMixin(BaseHandlerMixin):
|
||||
class MessageHandlerCommandMixin(BaseHandlerMixin[Message]):
|
||||
@property
|
||||
def command(self) -> Optional[CommandObject]:
|
||||
if "command" in self.data:
|
||||
|
|
|
|||
19
aiogram/dispatcher/handler/poll.py
Normal file
19
aiogram/dispatcher/handler/poll.py
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
from abc import ABC
|
||||
from typing import List
|
||||
|
||||
from aiogram.api.types import Poll, PollOption
|
||||
from aiogram.dispatcher.handler import BaseHandler
|
||||
|
||||
|
||||
class PollHandler(BaseHandler[Poll], ABC):
|
||||
"""
|
||||
Base class for poll handlers
|
||||
"""
|
||||
|
||||
@property
|
||||
def question(self) -> str:
|
||||
return self.event.question
|
||||
|
||||
@property
|
||||
def options(self) -> List[PollOption]:
|
||||
return self.event.options
|
||||
14
aiogram/dispatcher/handler/pre_checkout_query.py
Normal file
14
aiogram/dispatcher/handler/pre_checkout_query.py
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
from abc import ABC
|
||||
|
||||
from aiogram.api.types import PreCheckoutQuery, User
|
||||
from aiogram.dispatcher.handler import BaseHandler
|
||||
|
||||
|
||||
class PreCheckoutQueryHandler(BaseHandler[PreCheckoutQuery], ABC):
|
||||
"""
|
||||
Base class for pre-checkout handlers
|
||||
"""
|
||||
|
||||
@property
|
||||
def from_user(self) -> User:
|
||||
return self.event.from_user
|
||||
14
aiogram/dispatcher/handler/shipping_query.py
Normal file
14
aiogram/dispatcher/handler/shipping_query.py
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
from abc import ABC
|
||||
|
||||
from aiogram.api.types import ShippingQuery, User
|
||||
from aiogram.dispatcher.handler import BaseHandler
|
||||
|
||||
|
||||
class ShippingQueryHandler(BaseHandler[ShippingQuery], ABC):
|
||||
"""
|
||||
Base class for shipping query handlers
|
||||
"""
|
||||
|
||||
@property
|
||||
def from_user(self) -> User:
|
||||
return self.event.from_user
|
||||
|
|
@ -7,11 +7,16 @@ There are some base class based handlers what you need to use in your own handle
|
|||
|
||||
- [BaseHandler](#basehandler)
|
||||
- [MessageHandler](message.md)
|
||||
|
||||
- [CallbackQueryHandler](callback_query.md)
|
||||
- [ChosenInlineResultHandler](chosen_inline_result.md)
|
||||
- [InlineQueryHandler](inline_query.md)
|
||||
- [PollHandler](poll.md)
|
||||
- [PreCheckoutQueryHandler](pre_checkout_query.md)
|
||||
- [ShippingQueryHandler](shipping_query.md)
|
||||
|
||||
## BaseHandler
|
||||
|
||||
Base handler is abstract class and should be used in all other class-based handlers.
|
||||
Base handler is generic abstract class and should be used in all other class-based handlers.
|
||||
|
||||
Import: `#!python3 from aiogram.hanler import BaseHandler`
|
||||
|
||||
|
|
@ -21,3 +26,11 @@ This class is also have an default initializer and you don't need to change it.
|
|||
Initializer accepts current event and all contextual data and which can be accessed from the handler through attributes: `event: TelegramEvent` and `data: Dict[Any, str]`
|
||||
|
||||
If instance of the bot is specified in context data or current context it can be accessed through `bot` class attribute.
|
||||
|
||||
|
||||
### For example:
|
||||
```python3
|
||||
class MyHandler(BaseHandler[Message]):
|
||||
async def handle(self) -> Any:
|
||||
await self.event.answer("Hello!")
|
||||
```
|
||||
|
|
|
|||
29
docs/dispatcher/class_based_handlers/callback_query.md
Normal file
29
docs/dispatcher/class_based_handlers/callback_query.md
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# CallbackQueryHandler
|
||||
|
||||
There is base class for callback query handlers.
|
||||
|
||||
## Simple usage:
|
||||
```pyhton3
|
||||
from aiogram.handlers import CallbackQueryHandler
|
||||
|
||||
...
|
||||
|
||||
@router.callback_query_handler()
|
||||
class MyHandler(CallbackQueryHandler):
|
||||
async def handle(self) -> Any: ...
|
||||
|
||||
```
|
||||
|
||||
## Extension
|
||||
|
||||
This base handler is subclass of [BaseHandler](basics.md#basehandler) with some extensions:
|
||||
|
||||
- `self.from_user` is alias for `self.event.from_user`
|
||||
- `self.message` is alias for `self.event.message`
|
||||
- `self.callback_data` is alias for `self.event.data`
|
||||
|
||||
## Related pages
|
||||
|
||||
- [BaseHandler](basics.md#basehandler)
|
||||
- [CallbackQuery](../../api/types/callback_query.md)
|
||||
- [Router.callback_query_handler](../router.md#callback-query)
|
||||
28
docs/dispatcher/class_based_handlers/chosen_inline_result.md
Normal file
28
docs/dispatcher/class_based_handlers/chosen_inline_result.md
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# ChosenInlineResultHandler
|
||||
|
||||
There is base class for chosen inline result handlers.
|
||||
|
||||
## Simple usage:
|
||||
```pyhton3
|
||||
from aiogram.handlers import ChosenInlineResultHandler
|
||||
|
||||
...
|
||||
|
||||
@router.chosen_inline_result_handler()
|
||||
class MyHandler(ChosenInlineResultHandler):
|
||||
async def handle(self) -> Any: ...
|
||||
|
||||
```
|
||||
|
||||
## Extension
|
||||
|
||||
This base handler is subclass of [BaseHandler](basics.md#basehandler) with some extensions:
|
||||
|
||||
- `self.chat` is alias for `self.event.chat`
|
||||
- `self.from_user` is alias for `self.event.from_user`
|
||||
|
||||
## Related pages
|
||||
|
||||
- [BaseHandler](basics.md#basehandler)
|
||||
- [ChosenInlineResult](../../api/types/chosen_inline_result.md)
|
||||
- [Router.chosen_inline_result_handler](../router.md#chosen-inline-query)
|
||||
27
docs/dispatcher/class_based_handlers/inline_query.md
Normal file
27
docs/dispatcher/class_based_handlers/inline_query.md
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# InlineQueryHandler
|
||||
There is base class for inline query handlers.
|
||||
|
||||
## Simple usage:
|
||||
```pyhton3
|
||||
from aiogram.handlers import InlineQueryHandler
|
||||
|
||||
...
|
||||
|
||||
@router.inline_query_handler()
|
||||
class MyHandler(InlineQueryHandler):
|
||||
async def handle(self) -> Any: ...
|
||||
|
||||
```
|
||||
|
||||
## Extension
|
||||
|
||||
This base handler is subclass of [BaseHandler](basics.md#basehandler) with some extensions:
|
||||
|
||||
- `self.chat` is alias for `self.event.chat`
|
||||
- `self.query` is alias for `self.event.query`
|
||||
|
||||
## Related pages
|
||||
|
||||
- [BaseHandler](basics.md#basehandler)
|
||||
- [InlineQuery](../../api/types/inline_query.md)
|
||||
- [Router.inline_query_handler](../router.md#inline-query)
|
||||
|
|
@ -9,8 +9,8 @@ from aiogram.handlers import MessageHandler
|
|||
...
|
||||
|
||||
@router.message_handler()
|
||||
class MyTestMessageHandler(MessageHandler):
|
||||
async def handle() -> Any:
|
||||
class MyHandler(MessageHandler):
|
||||
async def handle(self) -> Any:
|
||||
return SendMessage(chat_id=self.chat.id, text="PASS")
|
||||
|
||||
```
|
||||
|
|
@ -21,3 +21,12 @@ This base handler is subclass of [BaseHandler](basics.md#basehandler) with some
|
|||
|
||||
- `self.chat` is alias for `self.event.chat`
|
||||
- `self.from_user` is alias for `self.event.from_user`
|
||||
|
||||
## Related pages
|
||||
|
||||
- [BaseHandler](basics.md#basehandler)
|
||||
- [Message](../../api/types/message.md)
|
||||
- [Router.message_handler](../router.md#message)
|
||||
- [Router.edited_message_handler](../router.md#edited-message)
|
||||
- [Router.channel_post_handler](../router.md#channel-post)
|
||||
- [Router.edited_channel_post_handler](../router.md#edited-channel-post)
|
||||
|
|
|
|||
28
docs/dispatcher/class_based_handlers/poll.md
Normal file
28
docs/dispatcher/class_based_handlers/poll.md
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# PollHandler
|
||||
|
||||
There is base class for poll handlers.
|
||||
|
||||
## Simple usage:
|
||||
```pyhton3
|
||||
from aiogram.handlers import PollHandler
|
||||
|
||||
...
|
||||
|
||||
@router.poll_handler()
|
||||
class MyHandler(PollHandler):
|
||||
async def handle(self) -> Any: ...
|
||||
|
||||
```
|
||||
|
||||
## Extension
|
||||
|
||||
This base handler is subclass of [BaseHandler](basics.md#basehandler) with some extensions:
|
||||
|
||||
- `self.question` is alias for `self.event.question`
|
||||
- `self.options` is alias for `self.event.options`
|
||||
|
||||
## Related pages
|
||||
|
||||
- [BaseHandler](basics.md#basehandler)
|
||||
- [Poll](../../api/types/poll.md)
|
||||
- [Router.poll_handler](../router.md#poll)
|
||||
27
docs/dispatcher/class_based_handlers/pre_checkout_query.md
Normal file
27
docs/dispatcher/class_based_handlers/pre_checkout_query.md
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# PreCheckoutQueryHandler
|
||||
|
||||
There is base class for callback query handlers.
|
||||
|
||||
## Simple usage:
|
||||
```pyhton3
|
||||
from aiogram.handlers import PreCheckoutQueryHandler
|
||||
|
||||
...
|
||||
|
||||
@router.pre_checkout_query_handler()
|
||||
class MyHandler(PreCheckoutQueryHandler):
|
||||
async def handle(self) -> Any: ...
|
||||
|
||||
```
|
||||
|
||||
## Extension
|
||||
|
||||
This base handler is subclass of [BaseHandler](basics.md#basehandler) with some extensions:
|
||||
|
||||
- `self.from_user` is alias for `self.event.from_user`
|
||||
|
||||
## Related pages
|
||||
|
||||
- [BaseHandler](basics.md#basehandler)
|
||||
- [PreCheckoutQuery](../../api/types/pre_checkout_query.md)
|
||||
- [Router.pre_checkout_query_handler](../router.md#pre-checkout-query)
|
||||
27
docs/dispatcher/class_based_handlers/shipping_query.md
Normal file
27
docs/dispatcher/class_based_handlers/shipping_query.md
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# ShippingQueryHandler
|
||||
|
||||
There is base class for callback query handlers.
|
||||
|
||||
## Simple usage:
|
||||
```pyhton3
|
||||
from aiogram.handlers import ShippingQueryHandler
|
||||
|
||||
...
|
||||
|
||||
@router.shipping_query_handler()
|
||||
class MyHandler(ShippingQueryHandler):
|
||||
async def handle(self) -> Any: ...
|
||||
|
||||
```
|
||||
|
||||
## Extension
|
||||
|
||||
This base handler is subclass of [BaseHandler](basics.md#basehandler) with some extensions:
|
||||
|
||||
- `self.from_user` is alias for `self.event.from_user`
|
||||
|
||||
## Related pages
|
||||
|
||||
- [BaseHandler](basics.md#basehandler)
|
||||
- [ShippingQuery](../../api/types/shipping_query.md)
|
||||
- [Router.shipping_query_handler](../router.md#shipping-query)
|
||||
|
|
@ -231,6 +231,12 @@ nav:
|
|||
- Class based handlers:
|
||||
- dispatcher/class_based_handlers/basics.md
|
||||
- dispatcher/class_based_handlers/message.md
|
||||
- dispatcher/class_based_handlers/callback_query.md
|
||||
- dispatcher/class_based_handlers/chosen_inline_result.md
|
||||
- dispatcher/class_based_handlers/inline_query.md
|
||||
- dispatcher/class_based_handlers/poll.md
|
||||
- dispatcher/class_based_handlers/pre_checkout_query.md
|
||||
- dispatcher/class_based_handlers/shipping_query.md
|
||||
- Build reports:
|
||||
- reports.md
|
||||
- Tests result: /reports/tests
|
||||
|
|
|
|||
26
tests/test_dispatcher/test_handler/test_callback_query.py
Normal file
26
tests/test_dispatcher/test_handler/test_callback_query.py
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
from typing import Any
|
||||
|
||||
import pytest
|
||||
from aiogram.api.types import CallbackQuery, User
|
||||
from aiogram.dispatcher.handler import CallbackQueryHandler
|
||||
|
||||
|
||||
class TestCallbackQueryHandler:
|
||||
@pytest.mark.asyncio
|
||||
async def test_attributes_aliases(self):
|
||||
event = CallbackQuery(
|
||||
id="chosen",
|
||||
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||
data="test",
|
||||
chat_instance="test",
|
||||
)
|
||||
|
||||
class MyHandler(CallbackQueryHandler):
|
||||
async def handle(self) -> Any:
|
||||
assert self.event == event
|
||||
assert self.from_user == self.event.from_user
|
||||
assert self.callback_data == self.event.data
|
||||
assert self.message == self.message
|
||||
return True
|
||||
|
||||
assert await MyHandler(event)
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
from typing import Any
|
||||
|
||||
import pytest
|
||||
from aiogram.api.types import CallbackQuery, ChosenInlineResult, User
|
||||
from aiogram.dispatcher.handler import ChosenInlineResultHandler
|
||||
|
||||
|
||||
class TestChosenInlineResultHandler:
|
||||
@pytest.mark.asyncio
|
||||
async def test_attributes_aliases(self):
|
||||
event = ChosenInlineResult(
|
||||
result_id="chosen",
|
||||
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||
query="test",
|
||||
)
|
||||
|
||||
class MyHandler(ChosenInlineResultHandler):
|
||||
async def handle(self) -> Any:
|
||||
assert self.event == event
|
||||
assert self.from_user == self.event.from_user
|
||||
assert self.query == self.event.query
|
||||
return True
|
||||
|
||||
assert await MyHandler(event)
|
||||
25
tests/test_dispatcher/test_handler/test_inline_query.py
Normal file
25
tests/test_dispatcher/test_handler/test_inline_query.py
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
from typing import Any
|
||||
|
||||
import pytest
|
||||
from aiogram.api.types import CallbackQuery, InlineQuery, User
|
||||
from aiogram.dispatcher.handler import InlineQueryHandler
|
||||
|
||||
|
||||
class TestCallbackQueryHandler:
|
||||
@pytest.mark.asyncio
|
||||
async def test_attributes_aliases(self):
|
||||
event = InlineQuery(
|
||||
id="query",
|
||||
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||
query="query",
|
||||
offset="0",
|
||||
)
|
||||
|
||||
class MyHandler(InlineQueryHandler):
|
||||
async def handle(self) -> Any:
|
||||
assert self.event == event
|
||||
assert self.from_user == self.event.from_user
|
||||
assert self.query == self.event.query
|
||||
return True
|
||||
|
||||
assert await MyHandler(event)
|
||||
34
tests/test_dispatcher/test_handler/test_poll.py
Normal file
34
tests/test_dispatcher/test_handler/test_poll.py
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
from typing import Any
|
||||
|
||||
import pytest
|
||||
from aiogram.api.types import (
|
||||
CallbackQuery,
|
||||
InlineQuery,
|
||||
Poll,
|
||||
PollOption,
|
||||
ShippingAddress,
|
||||
ShippingQuery,
|
||||
User,
|
||||
)
|
||||
from aiogram.dispatcher.handler import PollHandler
|
||||
|
||||
|
||||
class TestShippingQueryHandler:
|
||||
@pytest.mark.asyncio
|
||||
async def test_attributes_aliases(self):
|
||||
event = Poll(
|
||||
id="query",
|
||||
question="Q?",
|
||||
options=[PollOption(text="A1", voter_count=1)],
|
||||
is_closed=True,
|
||||
)
|
||||
|
||||
class MyHandler(PollHandler):
|
||||
async def handle(self) -> Any:
|
||||
assert self.event == event
|
||||
assert self.question == self.event.question
|
||||
assert self.options == self.event.options
|
||||
|
||||
return True
|
||||
|
||||
assert await MyHandler(event)
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
from typing import Any
|
||||
|
||||
import pytest
|
||||
from aiogram.api.types import PreCheckoutQuery, User
|
||||
from aiogram.dispatcher.handler import PreCheckoutQueryHandler
|
||||
|
||||
|
||||
class TestPreCheckoutQueryHandler:
|
||||
@pytest.mark.asyncio
|
||||
async def test_attributes_aliases(self):
|
||||
event = PreCheckoutQuery(
|
||||
id="query",
|
||||
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||
currency="BTC",
|
||||
total_amount=7,
|
||||
invoice_payload="payload",
|
||||
)
|
||||
|
||||
class MyHandler(PreCheckoutQueryHandler):
|
||||
async def handle(self) -> Any:
|
||||
assert self.event == event
|
||||
assert self.from_user == self.event.from_user
|
||||
return True
|
||||
|
||||
assert await MyHandler(event)
|
||||
31
tests/test_dispatcher/test_handler/test_shipping_query.py
Normal file
31
tests/test_dispatcher/test_handler/test_shipping_query.py
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
from typing import Any
|
||||
|
||||
import pytest
|
||||
from aiogram.api.types import CallbackQuery, InlineQuery, ShippingAddress, ShippingQuery, User
|
||||
from aiogram.dispatcher.handler import ShippingQueryHandler
|
||||
|
||||
|
||||
class TestShippingQueryHandler:
|
||||
@pytest.mark.asyncio
|
||||
async def test_attributes_aliases(self):
|
||||
event = ShippingQuery(
|
||||
id="query",
|
||||
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||
invoice_payload="payload",
|
||||
shipping_address=ShippingAddress(
|
||||
country_code="country_code",
|
||||
state="state",
|
||||
city="city",
|
||||
street_line1="street_line1",
|
||||
street_line2="street_line2",
|
||||
post_code="post_code",
|
||||
),
|
||||
)
|
||||
|
||||
class MyHandler(ShippingQueryHandler):
|
||||
async def handle(self) -> Any:
|
||||
assert self.event == event
|
||||
assert self.from_user == self.event.from_user
|
||||
return True
|
||||
|
||||
assert await MyHandler(event)
|
||||
Loading…
Add table
Add a link
Reference in a new issue