ruff format --check падает на 7 файлах (не 5 как было указано). Изменения — чистое форматирование: line wrapping, trailing commas, blank lines. Никаких логических изменений. Файлы: bot.py, tests/test_commands_news.py, tests/test_commands_pg.py, tests/test_fetch_weather.py, tests/test_help_command.py, tests/test_morning_runner.py, utils/pogoda.py
238 lines
8.1 KiB
Python
238 lines
8.1 KiB
Python
"""Тесты для bot.TextHelpCommand — текстовая справка по командам."""
|
||
|
||
import sys
|
||
from pathlib import Path
|
||
from unittest.mock import AsyncMock, MagicMock, patch
|
||
|
||
import pytest
|
||
|
||
ROOT_DIR = Path(__file__).resolve().parent.parent
|
||
sys.path.insert(0, str(ROOT_DIR))
|
||
|
||
|
||
@pytest.fixture
|
||
def help_command() -> "bot.TextHelpCommand":
|
||
"""Создать экземпляр TextHelpCommand."""
|
||
import bot
|
||
|
||
return bot.TextHelpCommand()
|
||
|
||
|
||
class TestGetCommandSignature:
|
||
"""Тесты get_command_signature."""
|
||
|
||
def test_simple_command_no_signature(self, help_command) -> None:
|
||
"""Команда без параметров."""
|
||
cmd = MagicMock()
|
||
cmd.qualified_name = "pg"
|
||
cmd.signature = ""
|
||
result = help_command.get_command_signature(cmd)
|
||
assert result == "!pg "
|
||
|
||
def test_command_with_signature(self, help_command) -> None:
|
||
"""Команда с параметрами."""
|
||
cmd = MagicMock()
|
||
cmd.qualified_name = "search"
|
||
cmd.signature = "<query>"
|
||
result = help_command.get_command_signature(cmd)
|
||
assert result == "!search <query>"
|
||
|
||
def test_group_command(self, help_command) -> None:
|
||
"""Групповая команда."""
|
||
cmd = MagicMock()
|
||
cmd.qualified_name = "mod ban"
|
||
cmd.signature = "<user>"
|
||
result = help_command.get_command_signature(cmd)
|
||
assert result == "!mod ban <user>"
|
||
|
||
|
||
class TestSendBotHelp:
|
||
"""Тесты send_bot_help."""
|
||
|
||
@pytest.mark.asyncio
|
||
async def test_send_bot_help_shows_commands(self, help_command) -> None:
|
||
"""Должен показать список команд по когам."""
|
||
cmd = MagicMock()
|
||
cmd.name = "pg"
|
||
cmd.hidden = False
|
||
cmd.short_doc = "Прогноз погоды"
|
||
|
||
cog = MagicMock()
|
||
cog.qualified_name = "Pg"
|
||
|
||
destination = MagicMock()
|
||
destination.send = AsyncMock(return_value=None)
|
||
|
||
with patch.object(help_command, "get_destination", return_value=destination):
|
||
mapping = {cog: [cmd], None: []}
|
||
await help_command.send_bot_help(mapping)
|
||
|
||
destination.send.assert_awaited_once()
|
||
message = destination.send.call_args[0][0]
|
||
assert "Доступные команды:" in message
|
||
assert "!pg - Прогноз погоды" in message
|
||
assert "!<название команды>" in message
|
||
|
||
@pytest.mark.asyncio
|
||
async def test_send_bot_help_skips_hidden(self, help_command) -> None:
|
||
"""Скрытые команды не должны показываться."""
|
||
cmd = MagicMock()
|
||
cmd.name = "hidden_cmd"
|
||
cmd.hidden = True
|
||
cmd.short_doc = "Скрытая"
|
||
|
||
cog = MagicMock()
|
||
|
||
destination = MagicMock()
|
||
destination.send = AsyncMock(return_value=None)
|
||
|
||
with patch.object(help_command, "get_destination", return_value=destination):
|
||
mapping = {cog: [cmd]}
|
||
await help_command.send_bot_help(mapping)
|
||
|
||
destination.send.assert_awaited_once()
|
||
message = destination.send.call_args[0][0]
|
||
assert "hidden_cmd" not in message
|
||
|
||
@pytest.mark.asyncio
|
||
async def test_send_bot_help_shows_none_cog(self, help_command) -> None:
|
||
"""Команды без cog (None) должны показываться, если не hidden."""
|
||
cmd = MagicMock()
|
||
cmd.name = "standalone"
|
||
cmd.hidden = False
|
||
cmd.short_doc = "Самостоятельная"
|
||
|
||
destination = MagicMock()
|
||
destination.send = AsyncMock(return_value=None)
|
||
|
||
with patch.object(help_command, "get_destination", return_value=destination):
|
||
mapping = {None: [cmd]}
|
||
await help_command.send_bot_help(mapping)
|
||
|
||
destination.send.assert_awaited_once()
|
||
message = destination.send.call_args[0][0]
|
||
assert "standalone" in message
|
||
assert "Самостоятельная" in message
|
||
|
||
@pytest.mark.asyncio
|
||
async def test_send_bot_help_hides_none_cog_hidden_cmd(self, help_command) -> None:
|
||
"""Hidden команды без cog не должны показываться."""
|
||
cmd = MagicMock()
|
||
cmd.name = "hidden_standalone"
|
||
cmd.hidden = True
|
||
cmd.short_doc = "Скрытая"
|
||
|
||
destination = MagicMock()
|
||
destination.send = AsyncMock(return_value=None)
|
||
|
||
with patch.object(help_command, "get_destination", return_value=destination):
|
||
mapping = {None: [cmd]}
|
||
await help_command.send_bot_help(mapping)
|
||
|
||
destination.send.assert_awaited_once()
|
||
message = destination.send.call_args[0][0]
|
||
assert "hidden_standalone" not in message
|
||
|
||
@pytest.mark.asyncio
|
||
async def test_send_bot_help_empty_doc(self, help_command) -> None:
|
||
"""Команда без doc -> пустая строка описания."""
|
||
cmd = MagicMock()
|
||
cmd.name = "cat"
|
||
cmd.hidden = False
|
||
cmd.short_doc = ""
|
||
|
||
cog = MagicMock()
|
||
destination = MagicMock()
|
||
destination.send = AsyncMock(return_value=None)
|
||
|
||
with patch.object(help_command, "get_destination", return_value=destination):
|
||
mapping = {cog: [cmd]}
|
||
await help_command.send_bot_help(mapping)
|
||
|
||
message = destination.send.call_args[0][0]
|
||
assert "!cat - " in message
|
||
|
||
|
||
class TestSendCommandHelp:
|
||
"""Тесты send_command_help."""
|
||
|
||
@pytest.mark.asyncio
|
||
async def test_send_command_help_basic(self, help_command) -> None:
|
||
"""Базовая справка по команде."""
|
||
cmd = MagicMock()
|
||
cmd.qualified_name = "pg"
|
||
cmd.signature = ""
|
||
cmd.doc = "Прогноз погоды"
|
||
cmd.short_doc = "Прогноз погоды"
|
||
cmd.aliases = []
|
||
|
||
destination = MagicMock()
|
||
destination.send = AsyncMock(return_value=None)
|
||
|
||
with patch.object(help_command, "get_destination", return_value=destination):
|
||
await help_command.send_command_help(cmd)
|
||
|
||
message = destination.send.call_args[0][0]
|
||
assert "!pg " in message
|
||
assert "Прогноз погоды" in message
|
||
|
||
@pytest.mark.asyncio
|
||
async def test_send_command_help_with_aliases(self, help_command) -> None:
|
||
"""Команда с алиасами."""
|
||
cmd = MagicMock()
|
||
cmd.qualified_name = "pg"
|
||
cmd.signature = ""
|
||
cmd.doc = "Погода"
|
||
cmd.short_doc = "Погода"
|
||
cmd.aliases = ["weather", "w"]
|
||
|
||
destination = MagicMock()
|
||
destination.send = AsyncMock(return_value=None)
|
||
|
||
with patch.object(help_command, "get_destination", return_value=destination):
|
||
await help_command.send_command_help(cmd)
|
||
|
||
message = destination.send.call_args[0][0]
|
||
assert "!weather, !w" in message
|
||
|
||
|
||
class TestSendCogHelp:
|
||
"""Тесты send_cog_help."""
|
||
|
||
@pytest.mark.asyncio
|
||
async def test_send_cog_help(self, help_command) -> None:
|
||
"""Справка по когу."""
|
||
cmd = MagicMock()
|
||
cmd.name = "pg"
|
||
cmd.hidden = False
|
||
cmd.short_doc = "Погода"
|
||
|
||
cog = MagicMock()
|
||
cog.qualified_name = "Pg"
|
||
cog.get_commands.return_value = [cmd]
|
||
|
||
destination = MagicMock()
|
||
destination.send = AsyncMock(return_value=None)
|
||
|
||
with patch.object(help_command, "get_destination", return_value=destination):
|
||
await help_command.send_cog_help(cog)
|
||
|
||
message = destination.send.call_args[0][0]
|
||
assert "[Pg]:" in message
|
||
assert "!pg - Погода" in message
|
||
|
||
|
||
class TestSendErrorMessage:
|
||
"""Тесты send_error_message."""
|
||
|
||
@pytest.mark.asyncio
|
||
async def test_send_error_message(self, help_command) -> None:
|
||
"""Сообщение об ошибке."""
|
||
destination = MagicMock()
|
||
destination.send = AsyncMock(return_value=None)
|
||
|
||
with patch.object(help_command, "get_destination", return_value=destination):
|
||
await help_command.send_error_message("Command not found")
|
||
|
||
destination.send.assert_awaited_once_with("Command not found")
|