import uuid import pytest from unittest.mock import AsyncMock, MagicMock from aiogram.types import Message, InlineKeyboardMarkup from datetime import datetime from src.bot.handlers import get_router from src.processor.dto import EnrichedNewsItemDTO @pytest.fixture def mock_storage(): return AsyncMock() @pytest.fixture def mock_processor(): processor = MagicMock() processor.get_info.return_value = {"model": "test-model"} return processor @pytest.fixture def allowed_chat_id(): return "123456789" @pytest.fixture def router(mock_storage, mock_processor, allowed_chat_id): return get_router(mock_storage, mock_processor, allowed_chat_id) def get_handler(router, callback_name): for handler in router.message.handlers: if handler.callback.__name__ == callback_name: return handler.callback raise ValueError(f"Handler {callback_name} not found") @pytest.mark.asyncio async def test_command_hottest_handler_success(router, mock_storage, allowed_chat_id): """ Test that /hottest command calls get_top_ranked and returns a list of items. """ # 1. Arrange handler = get_handler(router, "command_hottest_handler") message = AsyncMock() message.chat = MagicMock() message.chat.id = int(allowed_chat_id) message.answer = AsyncMock() mock_items = [ EnrichedNewsItemDTO( title=f"Hot News {i}", url=f"https://example.com/{i}", content_text=f"Content {i}", source="Source", timestamp=datetime.now(), relevance_score=10-i, summary_ru=f"Сводка {i}", anomalies_detected=[], category="Tech" ) for i in range(3) ] mock_storage.get_top_ranked.return_value = mock_items # 2. Act await handler(message=message) # 3. Assert mock_storage.get_top_ranked.assert_called_once_with(limit=10) message.answer.assert_called_once() args, kwargs = message.answer.call_args assert "Top 10 Hottest Trends:" in args[0] assert "reply_markup" in kwargs assert isinstance(kwargs["reply_markup"], InlineKeyboardMarkup) # Check if all 3 items are in the markup markup = kwargs["reply_markup"] assert len(markup.inline_keyboard) == 3 # Check if icons and scores are present button_text = markup.inline_keyboard[0][0].text assert "🔥" in button_text assert "[10/10]" in button_text assert "Hot News 0" in button_text @pytest.mark.asyncio async def test_command_hottest_handler_empty(router, mock_storage, allowed_chat_id): """ Test that /hottest command handles empty results correctly. """ # 1. Arrange handler = get_handler(router, "command_hottest_handler") message = AsyncMock() message.chat = MagicMock() message.chat.id = int(allowed_chat_id) message.answer = AsyncMock() mock_storage.get_top_ranked.return_value = [] # 2. Act await handler(message=message) # 3. Assert mock_storage.get_top_ranked.assert_called_once_with(limit=10) message.answer.assert_called_once_with("No hot trends found yet.")