mirror of
https://github.com/FerraSoft/bottohelp.git
synced 2026-08-06 21:55:03 +00:00
Подготовка к релизу
This commit is contained in:
@@ -0,0 +1,297 @@
|
||||
"""
|
||||
Тесты для MessageTypeRouter.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from unittest.mock import Mock, AsyncMock
|
||||
from telegram import Update, Message, User, CallbackQuery
|
||||
|
||||
from core.message_router import MessageTypeRouter, MessageHandlerConfig
|
||||
from core.permissions import UserRole
|
||||
|
||||
|
||||
class TestMessageTypeRouter:
|
||||
"""Тесты маршрутизатора типов сообщений"""
|
||||
|
||||
@pytest.fixture
|
||||
def message_router(self):
|
||||
"""Фикстура для MessageTypeRouter"""
|
||||
return MessageTypeRouter()
|
||||
|
||||
@pytest.fixture
|
||||
def mock_update_text(self):
|
||||
"""Мок-объект для текстового сообщения"""
|
||||
update = Mock(spec=Update)
|
||||
message = Mock(spec=Message)
|
||||
user = Mock(spec=User)
|
||||
user.id = 123456789
|
||||
|
||||
message.text = "Hello world"
|
||||
message.voice = None
|
||||
message.photo = None
|
||||
update.message = message
|
||||
update.effective_user = user
|
||||
|
||||
# Mock chat for permission checking
|
||||
chat = Mock()
|
||||
member = Mock()
|
||||
member.status = 'member'
|
||||
chat.get_member = AsyncMock(return_value=member)
|
||||
update.effective_chat = chat
|
||||
|
||||
return update
|
||||
|
||||
@pytest.fixture
|
||||
def mock_update_voice(self):
|
||||
"""Мок-объект для голосового сообщения"""
|
||||
update = Mock(spec=Update)
|
||||
message = Mock(spec=Message)
|
||||
user = Mock(spec=User)
|
||||
user.id = 123456789
|
||||
voice = Mock()
|
||||
|
||||
message.text = None
|
||||
message.voice = voice
|
||||
message.photo = None
|
||||
update.message = message
|
||||
update.effective_user = user
|
||||
|
||||
# Mock chat for permission checking
|
||||
chat = Mock()
|
||||
member = Mock()
|
||||
member.status = 'member'
|
||||
chat.get_member = AsyncMock(return_value=member)
|
||||
update.effective_chat = chat
|
||||
|
||||
return update
|
||||
|
||||
@pytest.fixture
|
||||
def mock_update_callback(self):
|
||||
"""Мок-объект для callback запроса"""
|
||||
update = Mock(spec=Update)
|
||||
callback_query = Mock(spec=CallbackQuery)
|
||||
user = Mock(spec=User)
|
||||
user.id = 123456789
|
||||
|
||||
callback_query.data = "test_callback"
|
||||
update.callback_query = callback_query
|
||||
update.effective_user = user
|
||||
|
||||
# Mock chat for permission checking
|
||||
chat = Mock()
|
||||
member = Mock()
|
||||
member.status = 'member'
|
||||
chat.get_member = AsyncMock(return_value=member)
|
||||
update.effective_chat = chat
|
||||
|
||||
return update
|
||||
|
||||
@pytest.fixture
|
||||
def mock_context(self):
|
||||
"""Мок-объект для контекста"""
|
||||
return Mock()
|
||||
|
||||
def test_initialization(self, message_router):
|
||||
"""Тест инициализации маршрутизатора"""
|
||||
assert message_router.text_handlers == {}
|
||||
assert message_router.callback_handlers == {}
|
||||
assert message_router.voice_handlers == []
|
||||
assert len(message_router.photo_handlers) == 0
|
||||
|
||||
def test_register_text_handler(self, message_router):
|
||||
"""Тест регистрации обработчика текста"""
|
||||
async def handler(update, context):
|
||||
pass
|
||||
|
||||
message_router.register_text_handler(
|
||||
r'hello', handler, UserRole.USER, 1, 'Test handler'
|
||||
)
|
||||
|
||||
assert len(message_router.text_handlers) == 1
|
||||
pattern, config = list(message_router.text_handlers.items())[0]
|
||||
assert config.required_role == UserRole.USER
|
||||
assert config.priority == 1
|
||||
assert config.description == 'Test handler'
|
||||
|
||||
def test_register_text_handler_invalid_regex(self, message_router):
|
||||
"""Тест регистрации обработчика с невалидным regex"""
|
||||
async def handler(update, context):
|
||||
pass
|
||||
|
||||
# Неверный regex не должен вызывать исключение, но и не регистрироваться
|
||||
initial_count = len(message_router.text_handlers)
|
||||
|
||||
message_router.register_text_handler(
|
||||
r'[invalid', handler, UserRole.USER
|
||||
)
|
||||
|
||||
assert len(message_router.text_handlers) == initial_count
|
||||
|
||||
def test_register_callback_handler(self, message_router):
|
||||
"""Тест регистрации обработчика callback"""
|
||||
async def handler(update, context):
|
||||
pass
|
||||
|
||||
message_router.register_callback_handler(
|
||||
'test_callback', handler, UserRole.USER, 'Test callback handler'
|
||||
)
|
||||
|
||||
assert 'test_callback' in message_router.callback_handlers
|
||||
config = message_router.callback_handlers['test_callback']
|
||||
assert config.required_role == UserRole.USER
|
||||
assert config.description == 'Test callback handler'
|
||||
|
||||
def test_register_media_handler(self, message_router):
|
||||
"""Тест регистрации обработчика медиа"""
|
||||
async def handler(update, context):
|
||||
pass
|
||||
|
||||
message_router.register_media_handler(
|
||||
'photo', handler, UserRole.USER, 'Photo handler'
|
||||
)
|
||||
|
||||
assert len(message_router.photo_handlers) == 1
|
||||
config = message_router.photo_handlers[0]
|
||||
assert config.required_role == UserRole.USER
|
||||
assert config.description == 'Photo handler'
|
||||
|
||||
def test_register_voice_handler(self, message_router):
|
||||
"""Тест регистрации обработчика голосовых сообщений"""
|
||||
async def handler(update, context):
|
||||
pass
|
||||
|
||||
message_router.register_media_handler(
|
||||
'voice', handler, UserRole.USER, 'Voice handler'
|
||||
)
|
||||
|
||||
assert len(message_router.voice_handlers) == 1
|
||||
config = message_router.voice_handlers[0]
|
||||
assert config.required_role == UserRole.USER
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_route_text_message_no_match(self, message_router, mock_update_text, mock_context):
|
||||
"""Тест маршрутизации текста без совпадений"""
|
||||
result = await message_router.route_text_message(mock_update_text, mock_context)
|
||||
|
||||
assert result == False
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_route_text_message_with_match(self, message_router, mock_update_text, mock_context):
|
||||
"""Тест маршрутизации текста с совпадением"""
|
||||
handler_called = False
|
||||
|
||||
async def test_handler(update, context):
|
||||
nonlocal handler_called
|
||||
handler_called = True
|
||||
|
||||
message_router.register_text_handler(r'hello', test_handler, UserRole.USER)
|
||||
|
||||
result = await message_router.route_text_message(mock_update_text, mock_context)
|
||||
|
||||
# Проверяем, что обработчик был вызван
|
||||
assert handler_called == True
|
||||
assert result == True
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_route_text_message_insufficient_permissions(self, message_router, mock_update_text, mock_context):
|
||||
"""Тест маршрутизации текста при недостаточных правах"""
|
||||
handler_called = False
|
||||
|
||||
async def test_handler(update, context):
|
||||
nonlocal handler_called
|
||||
handler_called = True
|
||||
|
||||
# Регистрируем обработчик требующий админские права
|
||||
message_router.register_text_handler(r'hello', test_handler, UserRole.ADMIN)
|
||||
|
||||
result = await message_router.route_text_message(mock_update_text, mock_context)
|
||||
|
||||
assert result == False
|
||||
assert handler_called == False
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_route_callback_exact_match(self, message_router, mock_update_callback, mock_context):
|
||||
"""Тест маршрутизации callback с точным совпадением"""
|
||||
handler_called = False
|
||||
|
||||
async def test_handler(update, context):
|
||||
nonlocal handler_called
|
||||
handler_called = True
|
||||
|
||||
message_router.register_callback_handler('test_callback', test_handler, UserRole.USER)
|
||||
|
||||
result = await message_router.route_callback(mock_update_callback, mock_context)
|
||||
|
||||
# Проверяем, что обработчик был вызван
|
||||
assert handler_called == True
|
||||
assert result == True
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_route_callback_prefix_match(self, message_router, mock_update_callback, mock_context):
|
||||
"""Тест маршрутизации callback по префиксу"""
|
||||
handler_called = False
|
||||
|
||||
async def test_handler(update, context):
|
||||
nonlocal handler_called
|
||||
handler_called = True
|
||||
|
||||
message_router.register_callback_handler('test_', test_handler, UserRole.USER)
|
||||
|
||||
result = await message_router.route_callback(mock_update_callback, mock_context)
|
||||
|
||||
# Проверяем, что обработчик был вызван
|
||||
assert handler_called == True
|
||||
assert result == True
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_route_callback_no_match(self, message_router, mock_update_callback, mock_context):
|
||||
"""Тест маршрутизации callback без совпадений"""
|
||||
result = await message_router.route_callback(mock_update_callback, mock_context)
|
||||
|
||||
assert result == False
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_route_voice_message(self, message_router, mock_update_voice, mock_context):
|
||||
"""Тест маршрутизации голосовых сообщений"""
|
||||
handler_called = False
|
||||
|
||||
async def test_handler(update, context):
|
||||
nonlocal handler_called
|
||||
handler_called = True
|
||||
|
||||
message_router.register_media_handler('voice', test_handler, UserRole.USER)
|
||||
|
||||
result = await message_router.route_voice_message(mock_update_voice, mock_context)
|
||||
|
||||
# Проверяем, что обработчик был вызван
|
||||
assert handler_called == True
|
||||
assert result == True
|
||||
|
||||
def test_get_registered_handlers_count(self, message_router):
|
||||
"""Тест получения статистики обработчиков"""
|
||||
# Регистрируем несколько обработчиков
|
||||
async def handler(update, context):
|
||||
pass
|
||||
|
||||
message_router.register_text_handler(r'test', handler)
|
||||
message_router.register_callback_handler('callback', handler)
|
||||
message_router.register_media_handler('photo', handler)
|
||||
|
||||
stats = message_router.get_registered_handlers_count()
|
||||
|
||||
assert stats['text'] == 1
|
||||
assert stats['callback'] == 1
|
||||
assert stats['photo'] == 1
|
||||
assert stats['voice'] == 0
|
||||
|
||||
def test_message_handler_config(self):
|
||||
"""Тест конфигурации обработчика"""
|
||||
async def handler():
|
||||
pass
|
||||
|
||||
config = MessageHandlerConfig(handler, UserRole.MODERATOR, 5, 'Test config')
|
||||
|
||||
assert config.handler == handler
|
||||
assert config.required_role == UserRole.MODERATOR
|
||||
assert config.priority == 5
|
||||
assert config.description == 'Test config'
|
||||
Reference in New Issue
Block a user