from datetime import datetime, timedelta from unittest.mock import Mock, patch import pytest from aiogram import types from helper_bot.handlers.voice.utils import (format_time_ago, get_last_message_text, get_user_emoji_safe, plural_time, validate_voice_message) class TestVoiceUtils: """Тесты для утилит voice модуля""" @pytest.fixture def mock_bot_db(self): """Мок для базы данных""" mock_db = Mock() mock_db.settings = { 'Telegram': { 'group_for_logs': 'test_logs_chat' } } return mock_db @pytest.fixture def mock_message(self): """Мок для сообщения""" message = Mock(spec=types.Message) message.from_user.id = 123 message.from_user.first_name = "Test" message.from_user.full_name = "Test User" message.from_user.username = "testuser" message.from_user.is_bot = False message.from_user.language_code = "ru" message.chat.id = 456 return message @pytest.mark.asyncio async def test_get_last_message_text(self, mock_bot_db): """Тест получения последнего сообщения""" # Возвращаем UNIX timestamp from unittest.mock import AsyncMock mock_bot_db.last_date_audio = AsyncMock(return_value=1641034800) # 2022-01-01 12:00:00 result = await get_last_message_text(mock_bot_db) assert result is not None assert "минут" in result or "часа" in result or "дня" in result or "день" in result or "дней" in result mock_bot_db.last_date_audio.assert_called_once() @pytest.mark.asyncio async def test_validate_voice_message_valid(self): """Тест валидации голосового сообщения""" mock_message = Mock() mock_message.content_type = 'voice' mock_message.voice = Mock() result = await validate_voice_message(mock_message) assert result is True @pytest.mark.asyncio async def test_validate_voice_message_invalid(self): """Тест валидации невалидного сообщения""" mock_message = Mock() mock_message.voice = None result = await validate_voice_message(mock_message) assert result is False @pytest.mark.asyncio async def test_get_user_emoji_safe_with_emoji(self, mock_bot_db): """Тест безопасного получения эмодзи пользователя когда эмодзи есть""" from unittest.mock import AsyncMock mock_bot_db.get_user_emoji = AsyncMock(return_value="😊") result = await get_user_emoji_safe(mock_bot_db, 123) assert result == "😊" mock_bot_db.get_user_emoji.assert_called_once_with(123) @pytest.mark.asyncio async def test_get_user_emoji_safe_without_emoji(self, mock_bot_db): """Тест безопасного получения эмодзи пользователя когда эмодзи нет""" from unittest.mock import AsyncMock mock_bot_db.get_user_emoji = AsyncMock(return_value=None) result = await get_user_emoji_safe(mock_bot_db, 123) assert result == "😊" mock_bot_db.get_user_emoji.assert_called_once_with(123) @pytest.mark.asyncio async def test_get_user_emoji_safe_with_empty_emoji(self, mock_bot_db): """Тест безопасного получения эмодзи пользователя с пустым эмодзи""" from unittest.mock import AsyncMock mock_bot_db.get_user_emoji = AsyncMock(return_value="") result = await get_user_emoji_safe(mock_bot_db, 123) assert result == "😊" mock_bot_db.get_user_emoji.assert_called_once_with(123) @pytest.mark.asyncio async def test_get_user_emoji_safe_with_error(self, mock_bot_db): """Тест безопасного получения эмодзи пользователя при ошибке""" from unittest.mock import AsyncMock mock_bot_db.get_user_emoji = AsyncMock(return_value="Ошибка") result = await get_user_emoji_safe(mock_bot_db, 123) assert result == "Ошибка" mock_bot_db.get_user_emoji.assert_called_once_with(123) def test_format_time_ago_minutes(self): """Тест форматирования времени в минутах""" from datetime import datetime, timedelta # Создаем дату 30 минут назад test_date = (datetime.now() - timedelta(minutes=30)).strftime("%Y-%m-%d %H:%M:%S") result = format_time_ago(test_date) assert result is not None assert "минут" in result assert "30" in result or "29" in result or "31" in result def test_format_time_ago_hours(self): """Тест форматирования времени в часах""" from datetime import datetime, timedelta # Создаем дату 2 часа назад test_date = (datetime.now() - timedelta(hours=2)).strftime("%Y-%m-%d %H:%M:%S") result = format_time_ago(test_date) assert result is not None assert "часа" in result or "часов" in result def test_format_time_ago_days(self): """Тест форматирования времени в днях""" from datetime import datetime, timedelta # Создаем дату 3 дня назад test_date = (datetime.now() - timedelta(days=3)).strftime("%Y-%m-%d %H:%M:%S") result = format_time_ago(test_date) assert result is not None assert "дня" in result or "дней" in result def test_format_time_ago_none(self): """Тест форматирования времени с None""" result = format_time_ago(None) assert result is None def test_format_time_ago_invalid_format(self): """Тест форматирования времени с неверным форматом""" result = format_time_ago("invalid_date_format") assert result is None def test_plural_time_minutes(self): """Тест множественного числа для минут""" assert "1 минуту" in plural_time(1, 1) assert "2 минуты" in plural_time(1, 2) assert "5 минут" in plural_time(1, 5) assert "11 минут" in plural_time(1, 11) assert "21 минуту" in plural_time(1, 21) def test_plural_time_hours(self): """Тест множественного числа для часов""" assert "1 час" in plural_time(2, 1) assert "2 часа" in plural_time(2, 2) assert "5 часов" in plural_time(2, 5) assert "11 часов" in plural_time(2, 11) assert "21 час" in plural_time(2, 21) def test_plural_time_days(self): """Тест множественного числа для дней""" assert "1 день" in plural_time(3, 1) assert "2 дня" in plural_time(3, 2) assert "5 дней" in plural_time(3, 5) assert "11 дней" in plural_time(3, 11) assert "21 день" in plural_time(3, 21) def test_plural_time_invalid_type(self): """Тест множественного числа с неверным типом""" result = plural_time(4, 5) assert result == "5" def test_plural_time_edge_cases(self): """Тест граничных случаев для множественного числа""" # Тест для 0 assert "0 минут" in plural_time(1, 0) assert "0 часов" in plural_time(2, 0) assert "0 дней" in plural_time(3, 0) # Тест для больших чисел assert "100 минут" in plural_time(1, 100) assert "100 часов" in plural_time(2, 100) assert "100 дней" in plural_time(3, 100) if __name__ == '__main__': pytest.main([__file__])