from __future__ import annotations import unittest from types import SimpleNamespace from unittest.mock import AsyncMock, patch from pyrogram.enums import MessageEntityType from app.commands.builtins import command_registry, txt from app.transcription import TranscriptionError class TxtCommandTests(unittest.IsolatedAsyncioTestCase): def test_txt_is_registered_as_shared(self) -> None: definition = command_registry.resolve("txt") self.assertIsNotNone(definition) self.assertTrue(definition.is_shared) self.assertEqual(definition.guest_prefix, "..") def _ctx(self, *, reply=None, args: str = ""): message = SimpleNamespace( id=123, reply_to_message=reply, react=AsyncMock(), reply_text=AsyncMock(), ) return SimpleNamespace( args=args, message=message, replied_message=reply, client=SimpleNamespace(download_media=AsyncMock(return_value="downloaded.ogg")), manager=SimpleNamespace( config=SimpleNamespace(elevenlabs=SimpleNamespace()) ), reply=message.reply_text, ) async def test_invalid_usage_only_reacts_with_dislike(self) -> None: ctx = self._ctx() await txt(ctx) ctx.message.react.assert_awaited_once_with("👎") ctx.reply.assert_not_awaited() ctx.client.download_media.assert_not_awaited() async def test_api_error_only_reacts_with_dislike(self) -> None: media = SimpleNamespace(mime_type="audio/ogg") reply = SimpleNamespace(voice=media, video_note=None, video=None) ctx = self._ctx(reply=reply) with patch( "app.commands.builtins.transcribe_file", AsyncMock(side_effect=TranscriptionError("API failed")), ): with self.assertLogs("app.commands.builtins", level="ERROR"): await txt(ctx) ctx.message.react.assert_awaited_once_with("👎") ctx.reply.assert_not_awaited() async def test_success_replies_with_expandable_blockquote(self) -> None: media = SimpleNamespace(mime_type="video/mp4") reply = SimpleNamespace(voice=None, video_note=media, video=None) ctx = self._ctx(reply=reply) with patch( "app.commands.builtins.transcribe_file", AsyncMock(return_value="Расшифрованный текст"), ) as transcribe: await txt(ctx) ctx.message.react.assert_not_awaited() ctx.reply.assert_awaited_once() self.assertEqual(ctx.reply.await_args.args[0], "Расшифрованный текст") entity = ctx.reply.await_args.kwargs["entities"][0] self.assertEqual(entity.type, MessageEntityType.BLOCKQUOTE) self.assertTrue(entity.expandable) transcribe.assert_awaited_once() async def test_arguments_make_otherwise_valid_command_invalid(self) -> None: media = SimpleNamespace(mime_type="video/mp4") reply = SimpleNamespace(voice=None, video_note=None, video=media) ctx = self._ctx(reply=reply, args="unexpected") await txt(ctx) ctx.message.react.assert_awaited_once_with("👎") ctx.reply.assert_not_awaited() if __name__ == "__main__": unittest.main()