[3.x] Bot API 6.0 (#890)

* Base implementation

* Bump license

* Revert re-generated tests

* Fix tests, improved docs

* Remove TODO

* Removed unreachable code

* Changed type of `last_synchronization_error_date`

* Fixed wrongly cleaned code
This commit is contained in:
Alex Root Junior 2022-04-19 22:03:24 +03:00 committed by GitHub
parent 286cf39c8a
commit 497436595d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
81 changed files with 1942 additions and 147 deletions

View file

@ -0,0 +1,33 @@
import pytest
from aiogram.methods import AnswerWebAppQuery, Request
from aiogram.types import InlineQueryResult, SentWebAppMessage
from tests.mocked_bot import MockedBot
class TestAnswerWebAppQuery:
@pytest.mark.asyncio
async def test_method(self, bot: MockedBot):
prepare_result = bot.add_result_for(AnswerWebAppQuery, ok=True, result=SentWebAppMessage())
response: SentWebAppMessage = await AnswerWebAppQuery(
web_app_query_id="test",
result=InlineQueryResult(),
)
request: Request = bot.get_request()
assert request.method == "answerWebAppQuery"
# assert request.data == {}
assert response == prepare_result.result
@pytest.mark.asyncio
async def test_bot_method(self, bot: MockedBot):
prepare_result = bot.add_result_for(AnswerWebAppQuery, ok=True, result=SentWebAppMessage())
response: SentWebAppMessage = await bot.answer_web_app_query(
web_app_query_id="test",
result=InlineQueryResult(),
)
request: Request = bot.get_request()
assert request.method == "answerWebAppQuery"
# assert request.data == {}
assert response == prepare_result.result

View file

View file

View file

View file

@ -0,0 +1,27 @@
import pytest
from aiogram.methods import GetChatMenuButton, Request
from aiogram.types import MenuButton, MenuButtonDefault
from tests.mocked_bot import MockedBot
class TestGetChatMenuButton:
@pytest.mark.asyncio
async def test_method(self, bot: MockedBot):
prepare_result = bot.add_result_for(GetChatMenuButton, ok=True, result=MenuButtonDefault())
response: MenuButton = await GetChatMenuButton()
request: Request = bot.get_request()
assert request.method == "getChatMenuButton"
# assert request.data == {}
assert response == prepare_result.result
@pytest.mark.asyncio
async def test_bot_method(self, bot: MockedBot):
prepare_result = bot.add_result_for(GetChatMenuButton, ok=True, result=MenuButtonDefault())
response: MenuButton = await bot.get_chat_menu_button()
request: Request = bot.get_request()
assert request.method == "getChatMenuButton"
# assert request.data == {}
assert response == prepare_result.result

View file

@ -0,0 +1,53 @@
import pytest
from aiogram.methods import GetMyDefaultAdministratorRights, Request
from aiogram.types import ChatAdministratorRights
from tests.mocked_bot import MockedBot
class TestGetMyDefaultAdministratorRights:
@pytest.mark.asyncio
async def test_method(self, bot: MockedBot):
prepare_result = bot.add_result_for(
GetMyDefaultAdministratorRights,
ok=True,
result=ChatAdministratorRights(
is_anonymous=False,
can_manage_chat=False,
can_delete_messages=False,
can_manage_video_chats=False,
can_restrict_members=False,
can_promote_members=False,
can_change_info=False,
can_invite_users=False,
),
)
response: ChatAdministratorRights = await GetMyDefaultAdministratorRights()
request: Request = bot.get_request()
assert request.method == "getMyDefaultAdministratorRights"
# assert request.data == {}
assert response == prepare_result.result
@pytest.mark.asyncio
async def test_bot_method(self, bot: MockedBot):
prepare_result = bot.add_result_for(
GetMyDefaultAdministratorRights,
ok=True,
result=ChatAdministratorRights(
is_anonymous=False,
can_manage_chat=False,
can_delete_messages=False,
can_manage_video_chats=False,
can_restrict_members=False,
can_promote_members=False,
can_change_info=False,
can_invite_users=False,
),
)
response: ChatAdministratorRights = await bot.get_my_default_administrator_rights()
request: Request = bot.get_request()
assert request.method == "getMyDefaultAdministratorRights"
# assert request.data == {}
assert response == prepare_result.result

View file

@ -16,6 +16,7 @@ class TestGetStickerSet:
name="test",
title="test",
is_animated=False,
is_video=False,
contains_masks=False,
stickers=[
Sticker(
@ -23,6 +24,7 @@ class TestGetStickerSet:
width=42,
height=42,
is_animated=False,
is_video=False,
file_unique_id="file id",
)
],
@ -42,6 +44,7 @@ class TestGetStickerSet:
name="test",
title="test",
is_animated=False,
is_video=False,
contains_masks=False,
stickers=[
Sticker(
@ -49,6 +52,7 @@ class TestGetStickerSet:
width=42,
height=42,
is_animated=False,
is_video=False,
file_unique_id="file id",
)
],

View file

@ -22,6 +22,7 @@ class TestSendSticker:
width=42,
height=42,
is_animated=False,
is_video=False,
file_unique_id="file id",
),
chat=Chat(id=42, type="private"),
@ -45,6 +46,7 @@ class TestSendSticker:
width=42,
height=42,
is_animated=False,
is_video=False,
file_unique_id="file id",
),
chat=Chat(id=42, type="private"),

View file

@ -0,0 +1,26 @@
import pytest
from aiogram.methods import Request, SetChatMenuButton
from tests.mocked_bot import MockedBot
class TestSetChatMenuButton:
@pytest.mark.asyncio
async def test_method(self, bot: MockedBot):
prepare_result = bot.add_result_for(SetChatMenuButton, ok=True, result=True)
response: bool = await SetChatMenuButton()
request: Request = bot.get_request()
assert request.method == "setChatMenuButton"
# assert request.data == {}
assert response == prepare_result.result
@pytest.mark.asyncio
async def test_bot_method(self, bot: MockedBot):
prepare_result = bot.add_result_for(SetChatMenuButton, ok=True, result=True)
response: bool = await bot.set_chat_menu_button()
request: Request = bot.get_request()
assert request.method == "setChatMenuButton"
# assert request.data == {}
assert response == prepare_result.result

View file

@ -0,0 +1,26 @@
import pytest
from aiogram.methods import Request, SetMyDefaultAdministratorRights
from tests.mocked_bot import MockedBot
class TestSetMyDefaultAdministratorRights:
@pytest.mark.asyncio
async def test_method(self, bot: MockedBot):
prepare_result = bot.add_result_for(SetMyDefaultAdministratorRights, ok=True, result=True)
response: bool = await SetMyDefaultAdministratorRights()
request: Request = bot.get_request()
assert request.method == "setMyDefaultAdministratorRights"
# assert request.data == {}
assert response == prepare_result.result
@pytest.mark.asyncio
async def test_bot_method(self, bot: MockedBot):
prepare_result = bot.add_result_for(SetMyDefaultAdministratorRights, ok=True, result=True)
response: bool = await bot.set_my_default_administrator_rights()
request: Request = bot.get_request()
assert request.method == "setMyDefaultAdministratorRights"
# assert request.data == {}
assert response == prepare_result.result

View file

View file

@ -52,11 +52,13 @@ from aiogram.types import (
User,
Venue,
Video,
VideoChatEnded,
VideoChatParticipantsInvited,
VideoChatScheduled,
VideoChatStarted,
VideoNote,
Voice,
VoiceChatEnded,
VoiceChatParticipantsInvited,
VoiceChatStarted,
WebAppData,
)
from aiogram.types.message import ContentType, Message
@ -122,6 +124,7 @@ TEST_MESSAGE_STICKER = Message(
width=42,
height=42,
is_animated=False,
is_video=False,
),
chat=Chat(id=42, type="private"),
from_user=User(id=42, is_bot=False, first_name="Test"),
@ -318,29 +321,38 @@ TEST_MESSAGE_MESSAGE_AUTO_DELETE_TIMER_CHANGED = Message(
message_auto_delete_timer_changed=MessageAutoDeleteTimerChanged(message_auto_delete_time=42),
from_user=User(id=42, is_bot=False, first_name="Test"),
)
TEST_MESSAGE_VOICE_CHAT_STARTED = Message(
TEST_MESSAGE_VIDEO_CHAT_STARTED = 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"),
voice_chat_started=VoiceChatStarted(),
video_chat_started=VideoChatStarted(),
)
TEST_MESSAGE_VOICE_CHAT_ENDED = Message(
TEST_MESSAGE_VIDEO_CHAT_ENDED = 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"),
voice_chat_ended=VoiceChatEnded(duration=42),
video_chat_ended=VideoChatEnded(duration=42),
)
TEST_MESSAGE_VOICE_CHAT_PARTICIPANTS_INVITED = Message(
TEST_MESSAGE_VIDEO_CHAT_PARTICIPANTS_INVITED = 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"),
voice_chat_participants_invited=VoiceChatParticipantsInvited(
video_chat_participants_invited=VideoChatParticipantsInvited(
users=[User(id=69, is_bot=False, first_name="Test")]
),
)
TEST_MESSAGE_VIDEO_CHAT_SCHEDULED = 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"),
video_chat_scheduled=VideoChatScheduled(
start_date=datetime.datetime.now(),
),
)
TEST_MESSAGE_DICE = Message(
message_id=42,
date=datetime.datetime.now(),
@ -348,6 +360,13 @@ TEST_MESSAGE_DICE = Message(
dice=Dice(value=6, emoji="X"),
from_user=User(id=42, is_bot=False, first_name="Test"),
)
TEST_MESSAGE_WEB_APP_DATA = Message(
message_id=42,
date=datetime.datetime.now(),
chat=Chat(id=42, type="private"),
web_app_data=WebAppData(data="test", button_text="Test"),
from_user=User(id=42, is_bot=False, first_name="Test"),
)
TEST_MESSAGE_UNKNOWN = Message(
message_id=42,
date=datetime.datetime.now(),
@ -391,13 +410,15 @@ class TestMessage:
TEST_MESSAGE_MESSAGE_AUTO_DELETE_TIMER_CHANGED,
ContentType.MESSAGE_AUTO_DELETE_TIMER_CHANGED,
],
[TEST_MESSAGE_VOICE_CHAT_STARTED, ContentType.VOICE_CHAT_STARTED],
[TEST_MESSAGE_VOICE_CHAT_ENDED, ContentType.VOICE_CHAT_ENDED],
[TEST_MESSAGE_VIDEO_CHAT_SCHEDULED, ContentType.VIDEO_CHAT_SCHEDULED],
[TEST_MESSAGE_VIDEO_CHAT_STARTED, ContentType.VIDEO_CHAT_STARTED],
[TEST_MESSAGE_VIDEO_CHAT_ENDED, ContentType.VIDEO_CHAT_ENDED],
[
TEST_MESSAGE_VOICE_CHAT_PARTICIPANTS_INVITED,
ContentType.VOICE_CHAT_PARTICIPANTS_INVITED,
TEST_MESSAGE_VIDEO_CHAT_PARTICIPANTS_INVITED,
ContentType.VIDEO_CHAT_PARTICIPANTS_INVITED,
],
[TEST_MESSAGE_DICE, ContentType.DICE],
[TEST_MESSAGE_WEB_APP_DATA, ContentType.WEB_APP_DATA],
[TEST_MESSAGE_UNKNOWN, ContentType.UNKNOWN],
],
)
@ -535,9 +556,9 @@ class TestMessage:
[TEST_MESSAGE_PASSPORT_DATA, None],
[TEST_MESSAGE_POLL, SendPoll],
[TEST_MESSAGE_MESSAGE_AUTO_DELETE_TIMER_CHANGED, None],
[TEST_MESSAGE_VOICE_CHAT_STARTED, None],
[TEST_MESSAGE_VOICE_CHAT_ENDED, None],
[TEST_MESSAGE_VOICE_CHAT_PARTICIPANTS_INVITED, None],
[TEST_MESSAGE_VIDEO_CHAT_STARTED, None],
[TEST_MESSAGE_VIDEO_CHAT_ENDED, None],
[TEST_MESSAGE_VIDEO_CHAT_PARTICIPANTS_INVITED, None],
[TEST_MESSAGE_DICE, SendDice],
[TEST_MESSAGE_UNKNOWN, None],
],

View file

@ -82,11 +82,11 @@ class TestDispatcher:
assert dp.get("foo", 42) == 42
dp["foo"] = 1
assert dp._data["foo"] == 1
assert dp.workflow_data["foo"] == 1
assert dp["foo"] == 1
del dp["foo"]
assert "foo" not in dp._data
assert "foo" not in dp.workflow_data
def test_storage_property(self, dispatcher: Dispatcher):
assert dispatcher.storage is dispatcher.fsm.storage

View file

@ -320,7 +320,7 @@ class TestChatMemberUpdatedStatusFilter:
"can_be_edited": True,
"can_manage_chat": True,
"can_delete_messages": True,
"can_manage_voice_chats": True,
"can_manage_video_chats": True,
"can_restrict_members": True,
"can_promote_members": True,
"can_change_info": True,

View file

@ -0,0 +1,80 @@
import pytest
from aiogram.utils.web_app import (
WebAppInitData,
check_webapp_signature,
parse_webapp_init_data,
safe_parse_webapp_init_data,
)
class TestWebApp:
@pytest.mark.parametrize(
"token,case,result",
[
[
"42:TEST",
"auth_date=1650385342"
"&user=%7B%22id%22%3A42%2C%22first_name%22%3A%22Test%22%7D"
"&query_id=test"
"&hash=46d2ea5e32911ec8d30999b56247654460c0d20949b6277af519e76271182803",
True,
],
[
"42:INVALID",
"auth_date=1650385342"
"&user=%7B%22id%22%3A42%2C%22first_name%22%3A%22Test%22%7D"
"&query_id=test"
"&hash=46d2ea5e32911ec8d30999b56247654460c0d20949b6277af519e76271182803",
False,
],
[
"42:TEST",
"user=%7B%22id%22%3A42%2C%22first_name%22%3A%22Test%22%7D&query_id=test&hash=test",
False,
],
[
"42:TEST",
"user=%7B%22id%22%3A42%2C%22first_name%22%3A%22Test%22%7D&query_id=test",
False,
],
["42:TEST", "", False],
["42:TEST", "test&foo=bar=baz", False],
],
)
def test_check_webapp_signature(self, token, case, result):
assert check_webapp_signature(token, case) is result
def test_parse_web_app_init_data(self):
parsed = parse_webapp_init_data(
"auth_date=1650385342"
"&user=%7B%22id%22%3A42%2C%22first_name%22%3A%22Test%22%7D"
"&query_id=test"
"&hash=46d2ea5e32911ec8d30999b56247654460c0d20949b6277af519e76271182803",
)
assert isinstance(parsed, WebAppInitData)
assert parsed.user
assert parsed.user.first_name == "Test"
assert parsed.user.id == 42
assert parsed.query_id == "test"
assert parsed.hash == "46d2ea5e32911ec8d30999b56247654460c0d20949b6277af519e76271182803"
assert parsed.auth_date.year == 2022
def test_valid_safe_parse_webapp_init_data(self):
assert safe_parse_webapp_init_data(
"42:TEST",
"auth_date=1650385342"
"&user=%7B%22id%22%3A42%2C%22first_name%22%3A%22Test%22%7D"
"&query_id=test"
"&hash=46d2ea5e32911ec8d30999b56247654460c0d20949b6277af519e76271182803",
)
def test_invalid_safe_parse_webapp_init_data(self):
with pytest.raises(ValueError):
safe_parse_webapp_init_data(
"42:TOKEN",
"auth_date=1650385342"
"&user=%7B%22id%22%3A42%2C%22first_name%22%3A%22Test%22%7D"
"&query_id=test"
"&hash=test",
)