Enhance /hottest command with optional limit
This commit is contained in:
parent
9fdb4b35cd
commit
a0eeba0918
@ -51,7 +51,7 @@ def get_router(storage: IVectorStore, processor: ILLMProvider, allowed_chat_id:
|
|||||||
"/start - Start the bot\n"
|
"/start - Start the bot\n"
|
||||||
"/help - Show this help message\n"
|
"/help - Show this help message\n"
|
||||||
"/latest [category] - Show the latest enriched news trends\n"
|
"/latest [category] - Show the latest enriched news trends\n"
|
||||||
"/hottest - Show top 10 ranked hot trends\n"
|
"/hottest [limit] - Show top ranked hot trends (default 10, max 50)\n"
|
||||||
"/search query - Search for news\n"
|
"/search query - Search for news\n"
|
||||||
"/stats - Show database statistics\n"
|
"/stats - Show database statistics\n"
|
||||||
"/params - Show LLM processor parameters\n"
|
"/params - Show LLM processor parameters\n"
|
||||||
@ -95,11 +95,22 @@ def get_router(storage: IVectorStore, processor: ILLMProvider, allowed_chat_id:
|
|||||||
await message.answer("Latest news:", reply_markup=builder.as_markup())
|
await message.answer("Latest news:", reply_markup=builder.as_markup())
|
||||||
|
|
||||||
@router.message(Command("hottest"))
|
@router.message(Command("hottest"))
|
||||||
async def command_hottest_handler(message: Message) -> None:
|
async def command_hottest_handler(message: Message, command: CommandObject) -> None:
|
||||||
"""
|
"""
|
||||||
This handler receives messages with `/hottest` command
|
This handler receives messages with `/hottest` command
|
||||||
"""
|
"""
|
||||||
items = await storage.get_top_ranked(limit=10)
|
limit = 10
|
||||||
|
if command.args:
|
||||||
|
try:
|
||||||
|
limit = int(command.args)
|
||||||
|
if limit <= 0:
|
||||||
|
limit = 10
|
||||||
|
elif limit > 50:
|
||||||
|
limit = 50
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
items = await storage.get_top_ranked(limit=limit)
|
||||||
|
|
||||||
if not items:
|
if not items:
|
||||||
await message.answer("No hot trends found yet.")
|
await message.answer("No hot trends found yet.")
|
||||||
@ -113,7 +124,7 @@ def get_router(storage: IVectorStore, processor: ILLMProvider, allowed_chat_id:
|
|||||||
callback_data=f"detail:{item_id}"
|
callback_data=f"detail:{item_id}"
|
||||||
))
|
))
|
||||||
|
|
||||||
await message.answer("Top 10 Hottest Trends:", reply_markup=builder.as_markup())
|
await message.answer(f"Top {len(items)} Hottest Trends:", reply_markup=builder.as_markup())
|
||||||
|
|
||||||
@router.message(Command("search"))
|
@router.message(Command("search"))
|
||||||
async def command_search_handler(message: Message, command: CommandObject) -> None:
|
async def command_search_handler(message: Message, command: CommandObject) -> None:
|
||||||
|
|||||||
@ -176,15 +176,16 @@ async def test_command_hottest_handler(router, mock_storage, allowed_chat_id, mo
|
|||||||
message = AsyncMock()
|
message = AsyncMock()
|
||||||
message.chat.id = int(allowed_chat_id)
|
message.chat.id = int(allowed_chat_id)
|
||||||
message.answer = AsyncMock()
|
message.answer = AsyncMock()
|
||||||
|
command = CommandObject(prefix="/", command="hottest", args=None)
|
||||||
|
|
||||||
mock_storage.get_top_ranked.return_value = [mock_item]
|
mock_storage.get_top_ranked.return_value = [mock_item]
|
||||||
|
|
||||||
await handler(message=message)
|
await handler(message=message, command=command)
|
||||||
|
|
||||||
mock_storage.get_top_ranked.assert_called_once_with(limit=10)
|
mock_storage.get_top_ranked.assert_called_once_with(limit=10)
|
||||||
message.answer.assert_called_once()
|
message.answer.assert_called_once()
|
||||||
args, kwargs = message.answer.call_args
|
args, kwargs = message.answer.call_args
|
||||||
assert "Top 10 Hottest Trends:" in args[0]
|
assert "Top 1 Hottest Trends:" in args[0]
|
||||||
assert "reply_markup" in kwargs
|
assert "reply_markup" in kwargs
|
||||||
assert "🔥" in str(kwargs["reply_markup"])
|
assert "🔥" in str(kwargs["reply_markup"])
|
||||||
|
|
||||||
@ -194,10 +195,11 @@ async def test_command_hottest_handler_empty(router, mock_storage, allowed_chat_
|
|||||||
message = AsyncMock()
|
message = AsyncMock()
|
||||||
message.chat.id = int(allowed_chat_id)
|
message.chat.id = int(allowed_chat_id)
|
||||||
message.answer = AsyncMock()
|
message.answer = AsyncMock()
|
||||||
|
command = CommandObject(prefix="/", command="hottest", args=None)
|
||||||
|
|
||||||
mock_storage.get_top_ranked.return_value = []
|
mock_storage.get_top_ranked.return_value = []
|
||||||
|
|
||||||
await handler(message=message)
|
await handler(message=message, command=command)
|
||||||
|
|
||||||
message.answer.assert_called_once_with("No hot trends found yet.")
|
message.answer.assert_called_once_with("No hot trends found yet.")
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import uuid
|
|||||||
import pytest
|
import pytest
|
||||||
from unittest.mock import AsyncMock, MagicMock
|
from unittest.mock import AsyncMock, MagicMock
|
||||||
from aiogram.types import Message, InlineKeyboardMarkup
|
from aiogram.types import Message, InlineKeyboardMarkup
|
||||||
|
from aiogram.filters import CommandObject
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from src.bot.handlers import get_router
|
from src.bot.handlers import get_router
|
||||||
@ -59,14 +60,15 @@ async def test_command_hottest_handler_success(router, mock_storage, allowed_cha
|
|||||||
mock_storage.get_top_ranked.return_value = mock_items
|
mock_storage.get_top_ranked.return_value = mock_items
|
||||||
|
|
||||||
# 2. Act
|
# 2. Act
|
||||||
await handler(message=message)
|
command = CommandObject(prefix='/', command='hottest', args=None)
|
||||||
|
await handler(message=message, command=command)
|
||||||
|
|
||||||
# 3. Assert
|
# 3. Assert
|
||||||
mock_storage.get_top_ranked.assert_called_once_with(limit=10)
|
mock_storage.get_top_ranked.assert_called_once_with(limit=10)
|
||||||
message.answer.assert_called_once()
|
message.answer.assert_called_once()
|
||||||
|
|
||||||
args, kwargs = message.answer.call_args
|
args, kwargs = message.answer.call_args
|
||||||
assert "Top 10 Hottest Trends:" in args[0]
|
assert "Top 3 Hottest Trends:" in args[0]
|
||||||
assert "reply_markup" in kwargs
|
assert "reply_markup" in kwargs
|
||||||
assert isinstance(kwargs["reply_markup"], InlineKeyboardMarkup)
|
assert isinstance(kwargs["reply_markup"], InlineKeyboardMarkup)
|
||||||
|
|
||||||
@ -95,8 +97,72 @@ async def test_command_hottest_handler_empty(router, mock_storage, allowed_chat_
|
|||||||
mock_storage.get_top_ranked.return_value = []
|
mock_storage.get_top_ranked.return_value = []
|
||||||
|
|
||||||
# 2. Act
|
# 2. Act
|
||||||
await handler(message=message)
|
command = CommandObject(prefix='/', command='hottest', args=None)
|
||||||
|
await handler(message=message, command=command)
|
||||||
|
|
||||||
# 3. Assert
|
# 3. Assert
|
||||||
mock_storage.get_top_ranked.assert_called_once_with(limit=10)
|
mock_storage.get_top_ranked.assert_called_once_with(limit=10)
|
||||||
message.answer.assert_called_once_with("No hot trends found yet.")
|
message.answer.assert_called_once_with("No hot trends found yet.")
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_command_hottest_handler_custom_limit(router, mock_storage, allowed_chat_id):
|
||||||
|
"""
|
||||||
|
Test that /hottest command with custom limit correctly passes it to storage.
|
||||||
|
"""
|
||||||
|
# 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
|
||||||
|
command = CommandObject(prefix='/', command='hottest', args='25')
|
||||||
|
await handler(message=message, command=command)
|
||||||
|
|
||||||
|
# 3. Assert
|
||||||
|
mock_storage.get_top_ranked.assert_called_once_with(limit=25)
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_command_hottest_handler_max_limit(router, mock_storage, allowed_chat_id):
|
||||||
|
"""
|
||||||
|
Test that /hottest command enforces maximum limit.
|
||||||
|
"""
|
||||||
|
# 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
|
||||||
|
command = CommandObject(prefix='/', command='hottest', args='1000')
|
||||||
|
await handler(message=message, command=command)
|
||||||
|
|
||||||
|
# 3. Assert
|
||||||
|
mock_storage.get_top_ranked.assert_called_once_with(limit=50)
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_command_hottest_handler_invalid_limit(router, mock_storage, allowed_chat_id):
|
||||||
|
"""
|
||||||
|
Test that /hottest command handles invalid limit by falling back to default.
|
||||||
|
"""
|
||||||
|
# 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
|
||||||
|
command = CommandObject(prefix='/', command='hottest', args='invalid')
|
||||||
|
await handler(message=message, command=command)
|
||||||
|
|
||||||
|
# 3. Assert
|
||||||
|
mock_storage.get_top_ranked.assert_called_once_with(limit=10)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user