mirror of
https://github.com/aiogram/aiogram.git
synced 2025-12-10 17:53:17 +00:00
Add tests for content types
This commit is contained in:
parent
8df6c345c3
commit
6ee05fb901
6 changed files with 391 additions and 10 deletions
|
|
@ -58,7 +58,7 @@ from .labeled_price import LabeledPrice
|
||||||
from .location import Location
|
from .location import Location
|
||||||
from .login_url import LoginUrl
|
from .login_url import LoginUrl
|
||||||
from .mask_position import MaskPosition
|
from .mask_position import MaskPosition
|
||||||
from .message import Message
|
from .message import ContentType, Message
|
||||||
from .message_entity import MessageEntity
|
from .message_entity import MessageEntity
|
||||||
from .order_info import OrderInfo
|
from .order_info import OrderInfo
|
||||||
from .passport_data import PassportData
|
from .passport_data import PassportData
|
||||||
|
|
@ -104,6 +104,7 @@ __all__ = (
|
||||||
"User",
|
"User",
|
||||||
"Chat",
|
"Chat",
|
||||||
"Message",
|
"Message",
|
||||||
|
"ContentType",
|
||||||
"MessageEntity",
|
"MessageEntity",
|
||||||
"PhotoSize",
|
"PhotoSize",
|
||||||
"Audio",
|
"Audio",
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@ from typing import Dict, Tuple, Union
|
||||||
|
|
||||||
from .base import BaseFilter
|
from .base import BaseFilter
|
||||||
from .command import Command, CommandObject
|
from .command import Command, CommandObject
|
||||||
|
from .content_types import ContentTypesFilter
|
||||||
from .text import Text
|
from .text import Text
|
||||||
from .content_type import ContentTypesFilter
|
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
"BUILTIN_FILTERS",
|
"BUILTIN_FILTERS",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
from typing import Any, Dict, List, Optional, Union
|
from typing import Any, Dict, List, Optional, Union
|
||||||
|
|
||||||
from pydantic import root_validator
|
from pydantic import validator
|
||||||
|
|
||||||
from ...api.types import Message
|
from ...api.types import Message
|
||||||
from ...api.types.message import ContentType
|
from ...api.types.message import ContentType
|
||||||
|
|
@ -10,17 +10,18 @@ from .base import BaseFilter
|
||||||
class ContentTypesFilter(BaseFilter):
|
class ContentTypesFilter(BaseFilter):
|
||||||
content_types: Optional[List[str]] = None
|
content_types: Optional[List[str]] = None
|
||||||
|
|
||||||
@root_validator
|
@validator("content_types", always=True)
|
||||||
def validate_constraints(cls, values: Dict[str, Any]) -> Dict[str, Any]:
|
def _validate_content_types(cls, value: Optional[List[str]]) -> Optional[List[str]]:
|
||||||
if "content_types" not in values or not values["content_types"]:
|
if not value:
|
||||||
values["content_types"] = [ContentType.TEXT]
|
value = [ContentType.TEXT]
|
||||||
allowed_content_types = set(ContentType.all())
|
allowed_content_types = set(ContentType.all())
|
||||||
bad_content_types = set(values["content_types"]) - allowed_content_types
|
bad_content_types = set(value) - allowed_content_types
|
||||||
if bad_content_types:
|
if bad_content_types:
|
||||||
raise ValueError(f"Invalid content types {bad_content_types} is not allowed here")
|
raise ValueError(f"Invalid content types {bad_content_types} is not allowed here")
|
||||||
return values
|
return value
|
||||||
|
|
||||||
async def __call__(self, message: Message) -> Union[bool, Dict[str, Any]]:
|
async def __call__(self, message: Message) -> Union[bool, Dict[str, Any]]:
|
||||||
if not self.content_types:
|
if not self.content_types: # pragma: no cover
|
||||||
|
# Is impossible but needed for valid typechecking
|
||||||
return False
|
return False
|
||||||
return ContentType.ANY in self.content_types or message.content_type in self.content_types
|
return ContentType.ANY in self.content_types or message.content_type in self.content_types
|
||||||
354
tests/test_api/test_types/test_message.py
Normal file
354
tests/test_api/test_types/test_message.py
Normal file
|
|
@ -0,0 +1,354 @@
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from aiogram.api.types import (
|
||||||
|
Animation,
|
||||||
|
Audio,
|
||||||
|
Chat,
|
||||||
|
Contact,
|
||||||
|
Document,
|
||||||
|
EncryptedCredentials,
|
||||||
|
Game,
|
||||||
|
Invoice,
|
||||||
|
Location,
|
||||||
|
PassportData,
|
||||||
|
PhotoSize,
|
||||||
|
Poll,
|
||||||
|
PollOption,
|
||||||
|
Sticker,
|
||||||
|
SuccessfulPayment,
|
||||||
|
User,
|
||||||
|
Venue,
|
||||||
|
Video,
|
||||||
|
VideoNote,
|
||||||
|
Voice,
|
||||||
|
)
|
||||||
|
from aiogram.api.types.message import ContentType, Message
|
||||||
|
|
||||||
|
|
||||||
|
class TestMessage:
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"message,content_type",
|
||||||
|
[
|
||||||
|
[
|
||||||
|
Message(
|
||||||
|
message_id=42,
|
||||||
|
date=datetime.datetime.now(),
|
||||||
|
text="test",
|
||||||
|
chat=Chat(id=42, type="private"),
|
||||||
|
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||||
|
),
|
||||||
|
ContentType.TEXT,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
Message(
|
||||||
|
message_id=42,
|
||||||
|
date=datetime.datetime.now(),
|
||||||
|
audio=Audio(file_id="file id", duration=42),
|
||||||
|
chat=Chat(id=42, type="private"),
|
||||||
|
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||||
|
),
|
||||||
|
ContentType.AUDIO,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
Message(
|
||||||
|
message_id=42,
|
||||||
|
date=datetime.datetime.now(),
|
||||||
|
animation=Animation(file_id="file id", width=42, height=42, duration=0),
|
||||||
|
chat=Chat(id=42, type="private"),
|
||||||
|
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||||
|
),
|
||||||
|
ContentType.ANIMATION,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
Message(
|
||||||
|
message_id=42,
|
||||||
|
date=datetime.datetime.now(),
|
||||||
|
document=Document(file_id="file id"),
|
||||||
|
chat=Chat(id=42, type="private"),
|
||||||
|
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||||
|
),
|
||||||
|
ContentType.DOCUMENT,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
Message(
|
||||||
|
message_id=42,
|
||||||
|
date=datetime.datetime.now(),
|
||||||
|
game=Game(
|
||||||
|
title="title",
|
||||||
|
description="description",
|
||||||
|
photo=[PhotoSize(file_id="file id", width=42, height=42)],
|
||||||
|
),
|
||||||
|
chat=Chat(id=42, type="private"),
|
||||||
|
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||||
|
),
|
||||||
|
ContentType.GAME,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
Message(
|
||||||
|
message_id=42,
|
||||||
|
date=datetime.datetime.now(),
|
||||||
|
photo=[PhotoSize(file_id="file id", width=42, height=42)],
|
||||||
|
chat=Chat(id=42, type="private"),
|
||||||
|
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||||
|
),
|
||||||
|
ContentType.PHOTO,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
Message(
|
||||||
|
message_id=42,
|
||||||
|
date=datetime.datetime.now(),
|
||||||
|
sticker=Sticker(file_id="file id", width=42, height=42, is_animated=False),
|
||||||
|
chat=Chat(id=42, type="private"),
|
||||||
|
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||||
|
),
|
||||||
|
ContentType.STICKER,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
Message(
|
||||||
|
message_id=42,
|
||||||
|
date=datetime.datetime.now(),
|
||||||
|
video=Video(file_id="file id", width=42, height=42, duration=0),
|
||||||
|
chat=Chat(id=42, type="private"),
|
||||||
|
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||||
|
),
|
||||||
|
ContentType.VIDEO,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
Message(
|
||||||
|
message_id=42,
|
||||||
|
date=datetime.datetime.now(),
|
||||||
|
video_note=VideoNote(file_id="file id", length=0, duration=0),
|
||||||
|
chat=Chat(id=42, type="private"),
|
||||||
|
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||||
|
),
|
||||||
|
ContentType.VIDEO_NOTE,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
Message(
|
||||||
|
message_id=42,
|
||||||
|
date=datetime.datetime.now(),
|
||||||
|
voice=Voice(file_id="file id", duration=0),
|
||||||
|
chat=Chat(id=42, type="private"),
|
||||||
|
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||||
|
),
|
||||||
|
ContentType.VOICE,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
Message(
|
||||||
|
message_id=42,
|
||||||
|
date=datetime.datetime.now(),
|
||||||
|
contact=Contact(phone_number="911", first_name="911"),
|
||||||
|
chat=Chat(id=42, type="private"),
|
||||||
|
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||||
|
),
|
||||||
|
ContentType.CONTACT,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
Message(
|
||||||
|
message_id=42,
|
||||||
|
date=datetime.datetime.now(),
|
||||||
|
venue=Venue(
|
||||||
|
location=Location(latitude=3.14, longitude=3.14),
|
||||||
|
title="Cupboard Under the Stairs",
|
||||||
|
address="Under the stairs, 4 Privet Drive, "
|
||||||
|
"Little Whinging, Surrey, England, Great Britain",
|
||||||
|
),
|
||||||
|
chat=Chat(id=42, type="private"),
|
||||||
|
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||||
|
),
|
||||||
|
ContentType.VENUE,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
Message(
|
||||||
|
message_id=42,
|
||||||
|
date=datetime.datetime.now(),
|
||||||
|
location=Location(longitude=3.14, latitude=3.14),
|
||||||
|
chat=Chat(id=42, type="private"),
|
||||||
|
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||||
|
),
|
||||||
|
ContentType.LOCATION,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
Message(
|
||||||
|
message_id=42,
|
||||||
|
date=datetime.datetime.now(),
|
||||||
|
new_chat_members=[User(id=42, is_bot=False, first_name="Test")],
|
||||||
|
chat=Chat(id=42, type="private"),
|
||||||
|
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||||
|
),
|
||||||
|
ContentType.NEW_CHAT_MEMBERS,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
Message(
|
||||||
|
message_id=42,
|
||||||
|
date=datetime.datetime.now(),
|
||||||
|
left_chat_member=User(id=42, is_bot=False, first_name="Test"),
|
||||||
|
chat=Chat(id=42, type="private"),
|
||||||
|
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||||
|
),
|
||||||
|
ContentType.LEFT_CHAT_MEMBER,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
Message(
|
||||||
|
message_id=42,
|
||||||
|
date=datetime.datetime.now(),
|
||||||
|
invoice=Invoice(
|
||||||
|
title="test",
|
||||||
|
description="test",
|
||||||
|
start_parameter="brilliant",
|
||||||
|
currency="BTC",
|
||||||
|
total_amount=1,
|
||||||
|
),
|
||||||
|
chat=Chat(id=42, type="private"),
|
||||||
|
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||||
|
),
|
||||||
|
ContentType.INVOICE,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
Message(
|
||||||
|
message_id=42,
|
||||||
|
date=datetime.datetime.now(),
|
||||||
|
successful_payment=SuccessfulPayment(
|
||||||
|
currency="BTC",
|
||||||
|
total_amount=42,
|
||||||
|
invoice_payload="payload",
|
||||||
|
telegram_payment_charge_id="charge",
|
||||||
|
provider_payment_charge_id="payment",
|
||||||
|
),
|
||||||
|
chat=Chat(id=42, type="private"),
|
||||||
|
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||||
|
),
|
||||||
|
ContentType.SUCCESSFUL_PAYMENT,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
Message(
|
||||||
|
message_id=42,
|
||||||
|
date=datetime.datetime.now(),
|
||||||
|
connected_website="token",
|
||||||
|
chat=Chat(id=42, type="private"),
|
||||||
|
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||||
|
),
|
||||||
|
ContentType.CONNECTED_WEBSITE,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
Message(
|
||||||
|
message_id=42,
|
||||||
|
date=datetime.datetime.now(),
|
||||||
|
migrate_from_chat_id=42,
|
||||||
|
chat=Chat(id=42, type="private"),
|
||||||
|
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||||
|
),
|
||||||
|
ContentType.MIGRATE_FROM_CHAT_ID,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
Message(
|
||||||
|
message_id=42,
|
||||||
|
date=datetime.datetime.now(),
|
||||||
|
migrate_to_chat_id=42,
|
||||||
|
chat=Chat(id=42, type="private"),
|
||||||
|
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||||
|
),
|
||||||
|
ContentType.MIGRATE_TO_CHAT_ID,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
Message(
|
||||||
|
message_id=42,
|
||||||
|
date=datetime.datetime.now(),
|
||||||
|
pinned_message=Message(
|
||||||
|
message_id=42,
|
||||||
|
date=datetime.datetime.now(),
|
||||||
|
text="pinned",
|
||||||
|
chat=Chat(id=42, type="private"),
|
||||||
|
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||||
|
),
|
||||||
|
chat=Chat(id=42, type="private"),
|
||||||
|
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||||
|
),
|
||||||
|
ContentType.PINNED_MESSAGE,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
Message(
|
||||||
|
message_id=42,
|
||||||
|
date=datetime.datetime.now(),
|
||||||
|
new_chat_title="test",
|
||||||
|
chat=Chat(id=42, type="private"),
|
||||||
|
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||||
|
),
|
||||||
|
ContentType.NEW_CHAT_TITLE,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
Message(
|
||||||
|
message_id=42,
|
||||||
|
date=datetime.datetime.now(),
|
||||||
|
new_chat_photo=[PhotoSize(file_id="file id", width=42, height=42)],
|
||||||
|
chat=Chat(id=42, type="private"),
|
||||||
|
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||||
|
),
|
||||||
|
ContentType.NEW_CHAT_PHOTO,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
Message(
|
||||||
|
message_id=42,
|
||||||
|
date=datetime.datetime.now(),
|
||||||
|
delete_chat_photo=True,
|
||||||
|
chat=Chat(id=42, type="private"),
|
||||||
|
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||||
|
),
|
||||||
|
ContentType.DELETE_CHAT_PHOTO,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
Message(
|
||||||
|
message_id=42,
|
||||||
|
date=datetime.datetime.now(),
|
||||||
|
group_chat_created=True,
|
||||||
|
chat=Chat(id=42, type="private"),
|
||||||
|
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||||
|
),
|
||||||
|
ContentType.GROUP_CHAT_CREATED,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
Message(
|
||||||
|
message_id=42,
|
||||||
|
date=datetime.datetime.now(),
|
||||||
|
passport_data=PassportData(
|
||||||
|
data=[],
|
||||||
|
credentials=EncryptedCredentials(data="test", hash="test", secret="test"),
|
||||||
|
),
|
||||||
|
chat=Chat(id=42, type="private"),
|
||||||
|
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||||
|
),
|
||||||
|
ContentType.PASSPORT_DATA,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
Message(
|
||||||
|
message_id=42,
|
||||||
|
date=datetime.datetime.now(),
|
||||||
|
poll=Poll(
|
||||||
|
id="QA",
|
||||||
|
question="Q",
|
||||||
|
options=[
|
||||||
|
PollOption(text="A", voter_count=0),
|
||||||
|
PollOption(text="B", voter_count=0),
|
||||||
|
],
|
||||||
|
is_closed=False,
|
||||||
|
),
|
||||||
|
chat=Chat(id=42, type="private"),
|
||||||
|
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||||
|
),
|
||||||
|
ContentType.POLL,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
Message(
|
||||||
|
message_id=42,
|
||||||
|
date=datetime.datetime.now(),
|
||||||
|
chat=Chat(id=42, type="private"),
|
||||||
|
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||||
|
),
|
||||||
|
ContentType.UNKNOWN,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_content_type(self, message: Message, content_type: str):
|
||||||
|
assert message.content_type == content_type
|
||||||
|
|
@ -3,6 +3,7 @@ import functools
|
||||||
from typing import Any, Awaitable, Callable, Dict, NoReturn, Union
|
from typing import Any, Awaitable, Callable, Dict, NoReturn, Union
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from aiogram.api.types import Chat, Message, User
|
from aiogram.api.types import Chat, Message, User
|
||||||
from aiogram.dispatcher.event.handler import HandlerObject
|
from aiogram.dispatcher.event.handler import HandlerObject
|
||||||
from aiogram.dispatcher.event.observer import EventObserver, SkipHandler, TelegramEventObserver
|
from aiogram.dispatcher.event.observer import EventObserver, SkipHandler, TelegramEventObserver
|
||||||
|
|
|
||||||
24
tests/test_dispatcher/test_filters/test_content_types.py
Normal file
24
tests/test_dispatcher/test_filters/test_content_types.py
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
import pytest
|
||||||
|
from pydantic import ValidationError
|
||||||
|
|
||||||
|
from aiogram.dispatcher.filters import ContentTypesFilter
|
||||||
|
|
||||||
|
|
||||||
|
class TestContentTypesFilter:
|
||||||
|
def test_validator_empty(self):
|
||||||
|
filter_ = ContentTypesFilter()
|
||||||
|
assert filter_.content_types == ["text"]
|
||||||
|
|
||||||
|
def test_validator_empty_list(self):
|
||||||
|
filter_ = ContentTypesFilter(content_types=[])
|
||||||
|
assert filter_.content_types == ["text"]
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("values", [["text", "photo"], ["sticker"]])
|
||||||
|
def test_validator_with_values(self, values):
|
||||||
|
filter_ = ContentTypesFilter(content_types=values)
|
||||||
|
assert filter_.content_types == values
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("values", [["test"], ["text", "test"], ["TEXT"]])
|
||||||
|
def test_validator_with_bad_values(self, values):
|
||||||
|
with pytest.raises(ValidationError):
|
||||||
|
ContentTypesFilter(content_types=values)
|
||||||
Loading…
Add table
Add a link
Reference in a new issue