mirror of
https://github.com/aiogram/aiogram.git
synced 2026-04-08 16:37:47 +00:00
Added full support of the Bot API 9.4 (#1761)
* Bump API schema to version 9.4, add new object types, methods, and properties.
* Add tests for `ChatOwnerChanged` and `ChatOwnerLeft` message types
* Add tests for `GetUserProfileAudios`, `RemoveMyProfilePhoto`, and `SetMyProfilePhoto` methods
* Bump version
* Update Makefile variables and refactor `test_get_user_profile_audios.py`
* Document new features and updates from Bot API 9.4 in changelog
* Add `ButtonStyle` enum to represent button styles in the Telegram API
* Fix review issues from PR #1761
- Remove stray '-' artifact from GameHighScore docstring and butcher schema
- Fix Makefile reformat target scope inconsistency (ruff check --fix)
- Fix ButtonStyle enum source URL (#chat -> #inlinekeyboardbutton)
- Add User.get_profile_audios() shortcut method (parallel to get_profile_photos)
- Test ChatOwnerLeft with new_owner=None (edge case)
- Add VideoQuality type and Video.qualities nesting tests
- Add User.get_profile_audios() test
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Revert "Fix review issues from PR #1761"
This reverts commit 2184e98988.
* Update source links for `ButtonStyle` documentation to reflect accurate API references
* Fix review issues from PR #1761 (#1762)
* Fix review issues from PR #1761
- Remove stray '-' artifact from GameHighScore docstring
- Fix Makefile reformat target scope inconsistency (ruff check --fix)
- Add User.get_profile_audios() shortcut method (parallel to get_profile_photos)
- Test ChatOwnerLeft with new_owner=None (edge case)
- Add VideoQuality type and Video.qualities nesting tests
- Add User.get_profile_audios() test
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Address review comments: use fixture and variables in tests, add changelog
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Address review follow-ups for PR #1762
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Reformat code
* Shut up, ruff
---------
Co-authored-by: latand <latand666@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Kostiantyn Kriuchkov <36363097+Latand@users.noreply.github.com>
This commit is contained in:
parent
da7bfdca0c
commit
49d0784e33
67 changed files with 1457 additions and 61 deletions
19
tests/test_api/test_methods/test_get_user_profile_audios.py
Normal file
19
tests/test_api/test_methods/test_get_user_profile_audios.py
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
from aiogram.methods import GetUserProfileAudios
|
||||
from aiogram.types import Audio, UserProfileAudios
|
||||
from tests.mocked_bot import MockedBot
|
||||
|
||||
|
||||
class TestGetUserProfileAudios:
|
||||
async def test_bot_method(self, bot: MockedBot):
|
||||
prepare_result = bot.add_result_for(
|
||||
GetUserProfileAudios,
|
||||
ok=True,
|
||||
result=UserProfileAudios(
|
||||
total_count=1,
|
||||
audios=[Audio(file_id="file_id", file_unique_id="file_unique_id", duration=120)],
|
||||
),
|
||||
)
|
||||
|
||||
response: UserProfileAudios = await bot.get_user_profile_audios(user_id=42)
|
||||
bot.get_request()
|
||||
assert response == prepare_result.result
|
||||
11
tests/test_api/test_methods/test_remove_my_profile_photo.py
Normal file
11
tests/test_api/test_methods/test_remove_my_profile_photo.py
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
from aiogram.methods import RemoveMyProfilePhoto
|
||||
from tests.mocked_bot import MockedBot
|
||||
|
||||
|
||||
class TestRemoveMyProfilePhoto:
|
||||
async def test_bot_method(self, bot: MockedBot):
|
||||
prepare_result = bot.add_result_for(RemoveMyProfilePhoto, ok=True, result=True)
|
||||
|
||||
response: bool = await bot.remove_my_profile_photo()
|
||||
bot.get_request()
|
||||
assert response == prepare_result.result
|
||||
14
tests/test_api/test_methods/test_set_my_profile_photo.py
Normal file
14
tests/test_api/test_methods/test_set_my_profile_photo.py
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
from aiogram.methods import SetMyProfilePhoto
|
||||
from aiogram.types import InputProfilePhotoStatic
|
||||
from tests.mocked_bot import MockedBot
|
||||
|
||||
|
||||
class TestSetMyProfilePhoto:
|
||||
async def test_bot_method(self, bot: MockedBot):
|
||||
prepare_result = bot.add_result_for(SetMyProfilePhoto, ok=True, result=True)
|
||||
|
||||
response: bool = await bot.set_my_profile_photo(
|
||||
photo=InputProfilePhotoStatic(photo="file_id")
|
||||
)
|
||||
bot.get_request()
|
||||
assert response == prepare_result.result
|
||||
|
|
@ -46,6 +46,8 @@ from aiogram.types import (
|
|||
Chat,
|
||||
ChatBackground,
|
||||
ChatBoostAdded,
|
||||
ChatOwnerChanged,
|
||||
ChatOwnerLeft,
|
||||
ChatShared,
|
||||
Checklist,
|
||||
ChecklistTask,
|
||||
|
|
@ -253,6 +255,31 @@ TEST_MESSAGE_LEFT_CHAT_MEMBER = Message(
|
|||
chat=Chat(id=42, type="private"),
|
||||
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||
)
|
||||
TEST_MESSAGE_CHAT_OWNER_LEFT = Message(
|
||||
message_id=42,
|
||||
date=datetime.datetime.now(),
|
||||
chat_owner_left=ChatOwnerLeft(
|
||||
new_owner=User(id=43, is_bot=False, first_name="NewOwner"),
|
||||
),
|
||||
chat=Chat(id=42, type="private"),
|
||||
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||
)
|
||||
TEST_MESSAGE_CHAT_OWNER_LEFT_NO_SUCCESSOR = Message(
|
||||
message_id=42,
|
||||
date=datetime.datetime.now(),
|
||||
chat_owner_left=ChatOwnerLeft(),
|
||||
chat=Chat(id=42, type="private"),
|
||||
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||
)
|
||||
TEST_MESSAGE_CHAT_OWNER_CHANGED = Message(
|
||||
message_id=42,
|
||||
date=datetime.datetime.now(),
|
||||
chat_owner_changed=ChatOwnerChanged(
|
||||
new_owner=User(id=43, is_bot=False, first_name="NewOwner"),
|
||||
),
|
||||
chat=Chat(id=42, type="private"),
|
||||
from_user=User(id=42, is_bot=False, first_name="Test"),
|
||||
)
|
||||
TEST_MESSAGE_INVOICE = Message(
|
||||
message_id=42,
|
||||
date=datetime.datetime.now(),
|
||||
|
|
@ -849,6 +876,8 @@ MESSAGES_AND_CONTENT_TYPES = [
|
|||
[TEST_MESSAGE_LOCATION, ContentType.LOCATION],
|
||||
[TEST_MESSAGE_NEW_CHAT_MEMBERS, ContentType.NEW_CHAT_MEMBERS],
|
||||
[TEST_MESSAGE_LEFT_CHAT_MEMBER, ContentType.LEFT_CHAT_MEMBER],
|
||||
[TEST_MESSAGE_CHAT_OWNER_LEFT, ContentType.CHAT_OWNER_LEFT],
|
||||
[TEST_MESSAGE_CHAT_OWNER_CHANGED, ContentType.CHAT_OWNER_CHANGED],
|
||||
[TEST_MESSAGE_INVOICE, ContentType.INVOICE],
|
||||
[TEST_MESSAGE_SUCCESSFUL_PAYMENT, ContentType.SUCCESSFUL_PAYMENT],
|
||||
[TEST_MESSAGE_CONNECTED_WEBSITE, ContentType.CONNECTED_WEBSITE],
|
||||
|
|
@ -930,6 +959,8 @@ MESSAGES_AND_COPY_METHODS = [
|
|||
[TEST_MESSAGE_STORY, ForwardMessage],
|
||||
[TEST_MESSAGE_NEW_CHAT_MEMBERS, None],
|
||||
[TEST_MESSAGE_LEFT_CHAT_MEMBER, None],
|
||||
[TEST_MESSAGE_CHAT_OWNER_LEFT, None],
|
||||
[TEST_MESSAGE_CHAT_OWNER_CHANGED, None],
|
||||
[TEST_MESSAGE_INVOICE, None],
|
||||
[TEST_MESSAGE_SUCCESSFUL_PAYMENT, None],
|
||||
[TEST_MESSAGE_CONNECTED_WEBSITE, None],
|
||||
|
|
@ -1023,6 +1054,11 @@ class TestMessage:
|
|||
def test_content_type(self, message: Message, content_type: str):
|
||||
assert message.content_type == content_type
|
||||
|
||||
def test_chat_owner_left_no_successor(self):
|
||||
assert (
|
||||
TEST_MESSAGE_CHAT_OWNER_LEFT_NO_SUCCESSOR.content_type == ContentType.CHAT_OWNER_LEFT
|
||||
)
|
||||
|
||||
def test_as_reply_parameters(self):
|
||||
message = Message(
|
||||
message_id=42, chat=Chat(id=42, type="private"), date=datetime.datetime.now()
|
||||
|
|
|
|||
|
|
@ -56,3 +56,9 @@ class TestUser:
|
|||
|
||||
method = user.get_profile_photos(description="test")
|
||||
assert method.user_id == user.id
|
||||
|
||||
def test_get_profile_audios(self):
|
||||
user = User(id=42, is_bot=False, first_name="Test", last_name="User")
|
||||
|
||||
method = user.get_profile_audios(description="test")
|
||||
assert method.user_id == user.id
|
||||
|
|
|
|||
61
tests/test_api/test_types/test_video_quality.py
Normal file
61
tests/test_api/test_types/test_video_quality.py
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
import pytest
|
||||
|
||||
from aiogram.types import Video, VideoQuality
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def video_quality():
|
||||
return VideoQuality(
|
||||
file_id="abc123",
|
||||
file_unique_id="unique123",
|
||||
width=1920,
|
||||
height=1080,
|
||||
codec="h264",
|
||||
)
|
||||
|
||||
|
||||
class TestVideoQuality:
|
||||
def test_instantiation(self, video_quality: VideoQuality):
|
||||
assert video_quality.file_id == "abc123"
|
||||
assert video_quality.file_unique_id == "unique123"
|
||||
assert video_quality.width == 1920
|
||||
assert video_quality.height == 1080
|
||||
assert video_quality.codec == "h264"
|
||||
assert video_quality.file_size is None
|
||||
|
||||
def test_instantiation_with_file_size(self):
|
||||
file_size = 1048576
|
||||
vq = VideoQuality(
|
||||
file_id="abc123",
|
||||
file_unique_id="unique123",
|
||||
width=1920,
|
||||
height=1080,
|
||||
codec="h265",
|
||||
file_size=file_size,
|
||||
)
|
||||
assert vq.file_size == file_size
|
||||
|
||||
def test_video_with_qualities(self, video_quality: VideoQuality):
|
||||
file_size = 524288
|
||||
video = Video(
|
||||
file_id="video123",
|
||||
file_unique_id="unique_video123",
|
||||
width=1920,
|
||||
height=1080,
|
||||
duration=120,
|
||||
qualities=[
|
||||
video_quality,
|
||||
VideoQuality(
|
||||
file_id="q2",
|
||||
file_unique_id="uq2",
|
||||
width=1280,
|
||||
height=720,
|
||||
codec="h264",
|
||||
file_size=file_size,
|
||||
),
|
||||
],
|
||||
)
|
||||
assert video.qualities is not None
|
||||
assert len(video.qualities) == 2
|
||||
assert video.qualities[0].width == 1920
|
||||
assert video.qualities[1].file_size == file_size
|
||||
Loading…
Add table
Add a link
Reference in a new issue