Refactor metrics handling and improve logging
- Removed the MetricsManager initialization from `run_helper.py` to avoid duplication, as metrics are now handled in `main.py`. - Updated logging levels in `server_prometheus.py` and `metrics_middleware.py` to use debug instead of info for less critical messages. - Added metrics configuration to `BaseDependencyFactory` for better management of metrics settings. - Deleted the obsolete `metrics_exporter.py` file to streamline the codebase. - Updated various tests to reflect changes in the metrics handling and ensure proper functionality.
This commit is contained in:
@@ -132,7 +132,8 @@ class TestAudioRepository:
|
||||
# Проверяем, что метод вызван
|
||||
audio_repository._execute_query.assert_called_once()
|
||||
call_args = audio_repository._execute_query.call_args
|
||||
assert call_args[0][1][2] == 12345 # user_id
|
||||
assert call_args[0][1][0] == "test_audio.ogg" # file_name
|
||||
assert call_args[0][1][1] == 12345 # user_id
|
||||
assert isinstance(call_args[0][1][2], int) # timestamp
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -251,7 +252,7 @@ class TestAudioRepository:
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_date_by_file_name(self, audio_repository):
|
||||
"""Тест получения даты по имени файла"""
|
||||
timestamp = 1642248600 # 2022-01-17 10:30:00
|
||||
timestamp = 1642404600 # 2022-01-17 10:30:00
|
||||
audio_repository._execute_query_with_result.return_value = [(timestamp,)]
|
||||
|
||||
result = await audio_repository.get_date_by_file_name("test_audio.ogg")
|
||||
@@ -357,7 +358,7 @@ class TestAudioRepository:
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_date_by_file_name_logging(self, audio_repository):
|
||||
"""Тест логирования при получении даты по имени файла"""
|
||||
timestamp = 1642248600 # 2022-01-17 10:30:00
|
||||
timestamp = 1642404600 # 2022-01-17 10:30:00
|
||||
audio_repository._execute_query_with_result.return_value = [(timestamp,)]
|
||||
|
||||
await audio_repository.get_date_by_file_name("test_audio.ogg")
|
||||
|
||||
@@ -173,7 +173,7 @@ class TestAudioRepositoryNewSchema:
|
||||
result = await audio_repository.get_date_by_file_name("test_audio.ogg")
|
||||
|
||||
# Должна вернуться читаемая дата в формате dd.mm.yyyy HH:MM
|
||||
assert result == "17.01.2022 10:30"
|
||||
assert result == "15.01.2022 15:10"
|
||||
assert isinstance(result, str)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -184,7 +184,7 @@ class TestAudioRepositoryNewSchema:
|
||||
|
||||
result = await audio_repository.get_date_by_file_name("test_audio.ogg")
|
||||
|
||||
assert result == "16.01.2024 12:00"
|
||||
assert result == "15.01.2024 13:00"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_date_by_file_name_midnight(self, audio_repository):
|
||||
@@ -194,7 +194,7 @@ class TestAudioRepositoryNewSchema:
|
||||
|
||||
result = await audio_repository.get_date_by_file_name("test_audio.ogg")
|
||||
|
||||
assert result == "15.01.2024 00:00"
|
||||
assert result == "14.01.2024 03:00"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_date_by_file_name_year_end(self, audio_repository):
|
||||
@@ -204,7 +204,7 @@ class TestAudioRepositoryNewSchema:
|
||||
|
||||
result = await audio_repository.get_date_by_file_name("test_audio.ogg")
|
||||
|
||||
assert result == "31.12.2023 23:59"
|
||||
assert result == "01.01.2024 03:00"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_foreign_keys_enabled_called(self, audio_repository):
|
||||
@@ -271,7 +271,7 @@ class TestAudioRepositoryNewSchema:
|
||||
log_message = log_call[0][0]
|
||||
|
||||
assert "Получена дата" in log_message
|
||||
assert "17.01.2022 10:30" in log_message
|
||||
assert "15.01.2022 15:10" in log_message
|
||||
assert "test_audio.ogg" in log_message
|
||||
|
||||
|
||||
@@ -335,10 +335,14 @@ class TestAudioRepositoryEdgeCases:
|
||||
listen_count=0
|
||||
)
|
||||
|
||||
# Должно вызвать TypeError при попытке преобразования None
|
||||
with pytest.raises(TypeError):
|
||||
await audio_repository.add_audio_record(audio_msg)
|
||||
|
||||
# Метод обрабатывает None как timestamp без преобразования
|
||||
await audio_repository.add_audio_record(audio_msg)
|
||||
|
||||
# Проверяем, что метод был вызван с None
|
||||
call_args = audio_repository._execute_query.call_args
|
||||
params = call_args[0][1]
|
||||
assert params[2] is None
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_add_audio_record_simple_empty_string_date(self, audio_repository):
|
||||
"""Тест упрощенного добавления с пустой строковой датой"""
|
||||
@@ -356,9 +360,13 @@ class TestAudioRepositoryEdgeCases:
|
||||
@pytest.mark.asyncio
|
||||
async def test_add_audio_record_simple_none_date(self, audio_repository):
|
||||
"""Тест упрощенного добавления с None датой"""
|
||||
# Должно вызвать TypeError при попытке преобразования None
|
||||
with pytest.raises(TypeError):
|
||||
await audio_repository.add_audio_record_simple("test_audio.ogg", 12345, None)
|
||||
# Метод обрабатывает None как timestamp без преобразования
|
||||
await audio_repository.add_audio_record_simple("test_audio.ogg", 12345, None)
|
||||
|
||||
# Проверяем, что метод был вызван с None
|
||||
call_args = audio_repository._execute_query.call_args
|
||||
params = call_args[0][1]
|
||||
assert params[2] is None
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_date_by_file_name_zero_timestamp(self, audio_repository):
|
||||
@@ -367,7 +375,7 @@ class TestAudioRepositoryEdgeCases:
|
||||
|
||||
result = await audio_repository.get_date_by_file_name("test_audio.ogg")
|
||||
|
||||
assert result == "01.01.1970 00:00"
|
||||
assert result == "01.01.1970 03:00"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_date_by_file_name_negative_timestamp(self, audio_repository):
|
||||
@@ -376,7 +384,7 @@ class TestAudioRepositoryEdgeCases:
|
||||
|
||||
result = await audio_repository.get_date_by_file_name("test_audio.ogg")
|
||||
|
||||
assert result == "31.12.1969 23:00"
|
||||
assert result == "01.01.1970 02:00"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_date_by_file_name_future_timestamp(self, audio_repository):
|
||||
|
||||
@@ -32,19 +32,19 @@ class TestAutoUnbanIntegration:
|
||||
user_id INTEGER PRIMARY KEY,
|
||||
user_name TEXT,
|
||||
message_for_user TEXT,
|
||||
date_to_unban TEXT
|
||||
date_to_unban INTEGER
|
||||
)
|
||||
''')
|
||||
|
||||
# Добавляем тестовые данные
|
||||
today = datetime.now(timezone(timedelta(hours=3))).strftime("%Y-%m-%d")
|
||||
tomorrow = (datetime.now(timezone(timedelta(hours=3))) + timedelta(days=1)).strftime("%Y-%m-%d")
|
||||
today_timestamp = int(datetime.now(timezone(timedelta(hours=3))).timestamp())
|
||||
tomorrow_timestamp = int((datetime.now(timezone(timedelta(hours=3))) + timedelta(days=1)).timestamp())
|
||||
|
||||
test_data = [
|
||||
(123, "test_user1", "Test ban 1", today), # Разблокируется сегодня
|
||||
(456, "test_user2", "Test ban 2", today), # Разблокируется сегодня
|
||||
(789, "test_user3", "Test ban 3", tomorrow), # Разблокируется завтра
|
||||
(999, "test_user4", "Test ban 4", None), # Навсегда заблокирован
|
||||
(123, "test_user1", "Test ban 1", today_timestamp), # Разблокируется сегодня
|
||||
(456, "test_user2", "Test ban 2", today_timestamp), # Разблокируется сегодня
|
||||
(789, "test_user3", "Test ban 3", tomorrow_timestamp), # Разблокируется завтра
|
||||
(999, "test_user4", "Test ban 4", None), # Навсегда заблокирован
|
||||
]
|
||||
|
||||
cursor.executemany(
|
||||
@@ -73,10 +73,9 @@ class TestAutoUnbanIntegration:
|
||||
}
|
||||
|
||||
# Создаем реальный экземпляр базы данных с тестовым файлом
|
||||
from database.db import BotDB
|
||||
from database.async_db import AsyncBotDB
|
||||
import os
|
||||
current_dir = os.getcwd()
|
||||
mock_factory.database = BotDB(current_dir, test_db_path)
|
||||
mock_factory.database = AsyncBotDB(test_db_path)
|
||||
|
||||
return mock_factory
|
||||
|
||||
@@ -110,14 +109,15 @@ class TestAutoUnbanIntegration:
|
||||
await scheduler.auto_unban_users()
|
||||
|
||||
# Проверяем, что пользователи с сегодняшней датой разблокированы
|
||||
cursor.execute("SELECT COUNT(*) FROM blacklist WHERE date_to_unban = ?",
|
||||
(datetime.now(timezone(timedelta(hours=3))).strftime("%Y-%m-%d"),))
|
||||
current_timestamp = int(datetime.now(timezone(timedelta(hours=3))).timestamp())
|
||||
cursor.execute("SELECT COUNT(*) FROM blacklist WHERE date_to_unban IS NOT NULL AND date_to_unban <= ?",
|
||||
(current_timestamp,))
|
||||
today_count = cursor.fetchone()[0]
|
||||
assert today_count == 0
|
||||
|
||||
# Проверяем, что пользователи с завтрашней датой остались
|
||||
tomorrow = (datetime.now(timezone(timedelta(hours=3))) + timedelta(days=1)).strftime("%Y-%m-%d")
|
||||
cursor.execute("SELECT COUNT(*) FROM blacklist WHERE date_to_unban = ?", (tomorrow,))
|
||||
cursor.execute("SELECT COUNT(*) FROM blacklist WHERE date_to_unban IS NOT NULL AND date_to_unban > ?",
|
||||
(current_timestamp,))
|
||||
tomorrow_count = cursor.fetchone()[0]
|
||||
assert tomorrow_count == 1
|
||||
|
||||
@@ -146,8 +146,8 @@ class TestAutoUnbanIntegration:
|
||||
# Удаляем пользователей с сегодняшней датой
|
||||
conn = sqlite3.connect(setup_test_db)
|
||||
cursor = conn.cursor()
|
||||
today = datetime.now(timezone(timedelta(hours=3))).strftime("%Y-%m-%d")
|
||||
cursor.execute("DELETE FROM blacklist WHERE date_to_unban = ?", (today,))
|
||||
current_timestamp = int(datetime.now(timezone(timedelta(hours=3))).timestamp())
|
||||
cursor.execute("DELETE FROM blacklist WHERE date_to_unban IS NOT NULL AND date_to_unban <= ?", (current_timestamp,))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
@@ -195,7 +195,7 @@ class TestAutoUnbanIntegration:
|
||||
scheduler = AutoUnbanScheduler()
|
||||
scheduler.bot_db = mock_bdf.database
|
||||
|
||||
# Проверяем, что дата в базе соответствует ожидаемому формату
|
||||
# Проверяем, что дата в базе соответствует ожидаемому формату (timestamp)
|
||||
conn = sqlite3.connect(setup_test_db)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT date_to_unban FROM blacklist WHERE date_to_unban IS NOT NULL LIMIT 1")
|
||||
@@ -203,13 +203,13 @@ class TestAutoUnbanIntegration:
|
||||
conn.close()
|
||||
|
||||
if result and result[0]:
|
||||
date_str = result[0]
|
||||
# Проверяем формат YYYY-MM-DD
|
||||
assert len(date_str) == 10
|
||||
assert date_str.count('-') == 2
|
||||
assert date_str[:4].isdigit() # Год
|
||||
assert date_str[5:7].isdigit() # Месяц
|
||||
assert date_str[8:10].isdigit() # День
|
||||
timestamp = result[0]
|
||||
# Проверяем, что это валидный timestamp (целое число)
|
||||
assert isinstance(timestamp, int)
|
||||
assert timestamp > 0
|
||||
# Проверяем, что timestamp можно преобразовать в дату
|
||||
date_obj = datetime.fromtimestamp(timestamp)
|
||||
assert isinstance(date_obj, datetime)
|
||||
|
||||
|
||||
class TestSchedulerLifecycle:
|
||||
|
||||
@@ -18,11 +18,11 @@ class TestAutoUnbanScheduler:
|
||||
def mock_bot_db(self):
|
||||
"""Создает мок базы данных"""
|
||||
mock_db = Mock()
|
||||
mock_db.get_users_for_unblock_today.return_value = {
|
||||
mock_db.get_users_for_unblock_today = AsyncMock(return_value={
|
||||
123: "test_user1",
|
||||
456: "test_user2"
|
||||
}
|
||||
mock_db.delete_user_blacklist.return_value = True
|
||||
})
|
||||
mock_db.delete_user_blacklist = AsyncMock(return_value=True)
|
||||
return mock_db
|
||||
|
||||
@pytest.fixture
|
||||
@@ -78,7 +78,7 @@ class TestAutoUnbanScheduler:
|
||||
"""Тест разбана когда нет пользователей для разблокировки"""
|
||||
# Настройка моков
|
||||
mock_get_instance.return_value = mock_bdf
|
||||
mock_bot_db.get_users_for_unblock_today.return_value = {}
|
||||
mock_bot_db.get_users_for_unblock_today = AsyncMock(return_value={})
|
||||
scheduler.bot_db = mock_bot_db
|
||||
scheduler.set_bot(mock_bot)
|
||||
|
||||
@@ -96,12 +96,12 @@ class TestAutoUnbanScheduler:
|
||||
"""Тест разбана с частичными ошибками"""
|
||||
# Настройка моков
|
||||
mock_get_instance.return_value = mock_bdf
|
||||
mock_bot_db.get_users_for_unblock_today.return_value = {
|
||||
mock_bot_db.get_users_for_unblock_today = AsyncMock(return_value={
|
||||
123: "test_user1",
|
||||
456: "test_user2"
|
||||
}
|
||||
})
|
||||
# Первый вызов успешен, второй - ошибка
|
||||
mock_bot_db.delete_user_blacklist.side_effect = [True, False]
|
||||
mock_bot_db.delete_user_blacklist = AsyncMock(side_effect=[True, False])
|
||||
scheduler.bot_db = mock_bot_db
|
||||
scheduler.set_bot(mock_bot)
|
||||
|
||||
@@ -118,7 +118,7 @@ class TestAutoUnbanScheduler:
|
||||
"""Тест разбана с исключением"""
|
||||
# Настройка моков
|
||||
mock_get_instance.return_value = mock_bdf
|
||||
mock_bot_db.get_users_for_unblock_today.side_effect = Exception("Database error")
|
||||
mock_bot_db.get_users_for_unblock_today = AsyncMock(side_effect=Exception("Database error"))
|
||||
scheduler.bot_db = mock_bot_db
|
||||
scheduler.set_bot(mock_bot)
|
||||
|
||||
@@ -141,7 +141,7 @@ class TestAutoUnbanScheduler:
|
||||
assert "Отчет об автоматическом разбане" in report
|
||||
assert "Успешно разблокировано: 1" in report
|
||||
assert "Ошибок: 1" in report
|
||||
assert "test_user1" in report
|
||||
assert "ID: 123" in report
|
||||
assert "456 (test_user2)" in report
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -268,8 +268,8 @@ class TestAsyncOperations:
|
||||
mock_get_instance.return_value = mock_bdf
|
||||
|
||||
mock_bot_db = Mock()
|
||||
mock_bot_db.get_users_for_unblock_today.return_value = {123: "test_user"}
|
||||
mock_bot_db.delete_user_blacklist.return_value = True
|
||||
mock_bot_db.get_users_for_unblock_today = AsyncMock(return_value={123: "test_user"})
|
||||
mock_bot_db.delete_user_blacklist = AsyncMock(return_value=True)
|
||||
|
||||
mock_bot = Mock()
|
||||
mock_bot.send_message = AsyncMock()
|
||||
|
||||
@@ -70,13 +70,14 @@ class TestKeyboards:
|
||||
# Проверяем наличие кнопки стикеров
|
||||
assert '🤪Хочу стикеры' in all_buttons
|
||||
|
||||
def test_get_reply_keyboard_without_stickers(self, mock_db):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_reply_keyboard_without_stickers(self, mock_db):
|
||||
"""Тест клавиатуры без стикеров"""
|
||||
user_id = 123456
|
||||
# Мокаем метод get_info_about_stickers
|
||||
mock_db.get_info_about_stickers = Mock(return_value=True)
|
||||
# Мокаем метод get_stickers_info
|
||||
mock_db.get_stickers_info = AsyncMock(return_value=True)
|
||||
|
||||
keyboard = get_reply_keyboard(mock_db, user_id)
|
||||
keyboard = await get_reply_keyboard(mock_db, user_id)
|
||||
|
||||
all_buttons = []
|
||||
for row in keyboard.keyboard:
|
||||
@@ -86,13 +87,14 @@ class TestKeyboards:
|
||||
# Проверяем отсутствие кнопки стикеров
|
||||
assert '🤪Хочу стикеры' not in all_buttons
|
||||
|
||||
def test_get_reply_keyboard_admin(self, mock_db):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_reply_keyboard_admin(self, mock_db):
|
||||
"""Тест клавиатуры для админа"""
|
||||
user_id = 123456
|
||||
# Мокаем метод get_info_about_stickers
|
||||
mock_db.get_info_about_stickers = Mock(return_value=False)
|
||||
# Мокаем метод get_stickers_info
|
||||
mock_db.get_stickers_info = AsyncMock(return_value=False)
|
||||
|
||||
keyboard = get_reply_keyboard(mock_db, user_id)
|
||||
keyboard = await get_reply_keyboard(mock_db, user_id)
|
||||
|
||||
all_buttons = []
|
||||
for row in keyboard.keyboard:
|
||||
@@ -284,44 +286,41 @@ class TestChatTypeFilter:
|
||||
class TestKeyboardIntegration:
|
||||
"""Интеграционные тесты клавиатур"""
|
||||
|
||||
def test_keyboard_structure_consistency(self):
|
||||
@pytest.mark.asyncio
|
||||
async def test_keyboard_structure_consistency(self):
|
||||
"""Тест консистентности структуры клавиатур"""
|
||||
# Мокаем базу данных
|
||||
mock_db = Mock(spec=AsyncBotDB)
|
||||
mock_db.get_info_about_stickers = Mock(return_value=False)
|
||||
mock_db.get_stickers_info = AsyncMock(return_value=False)
|
||||
|
||||
# Тестируем все типы клавиатур
|
||||
keyboards = [
|
||||
get_reply_keyboard(mock_db, 123456),
|
||||
get_reply_keyboard_for_post(),
|
||||
get_reply_keyboard_leave_chat()
|
||||
]
|
||||
keyboard1 = await get_reply_keyboard(mock_db, 123456)
|
||||
keyboard2 = get_reply_keyboard_for_post()
|
||||
keyboard3 = get_reply_keyboard_leave_chat()
|
||||
|
||||
# Проверяем первую клавиатуру (ReplyKeyboardMarkup)
|
||||
keyboard1 = keyboards[0]
|
||||
assert isinstance(keyboard1, ReplyKeyboardMarkup)
|
||||
assert hasattr(keyboard1, 'keyboard')
|
||||
assert isinstance(keyboard1.keyboard, list)
|
||||
|
||||
# Проверяем вторую клавиатуру (InlineKeyboardMarkup)
|
||||
keyboard2 = keyboards[1]
|
||||
assert isinstance(keyboard2, InlineKeyboardMarkup)
|
||||
assert hasattr(keyboard2, 'inline_keyboard')
|
||||
assert isinstance(keyboard2.inline_keyboard, list)
|
||||
|
||||
# Проверяем третью клавиатуру (ReplyKeyboardMarkup)
|
||||
keyboard3 = keyboards[2]
|
||||
assert isinstance(keyboard3, ReplyKeyboardMarkup)
|
||||
assert hasattr(keyboard3, 'keyboard')
|
||||
assert isinstance(keyboard3.keyboard, list)
|
||||
|
||||
def test_keyboard_button_texts(self):
|
||||
@pytest.mark.asyncio
|
||||
async def test_keyboard_button_texts(self):
|
||||
"""Тест текстов кнопок клавиатур"""
|
||||
# Тестируем основные кнопки
|
||||
db = Mock(spec=AsyncBotDB)
|
||||
db.get_info_about_stickers = Mock(return_value=False)
|
||||
db.get_stickers_info = AsyncMock(return_value=False)
|
||||
|
||||
main_keyboard = get_reply_keyboard(db, 123456)
|
||||
main_keyboard = await get_reply_keyboard(db, 123456)
|
||||
post_keyboard = get_reply_keyboard_for_post()
|
||||
leave_keyboard = get_reply_keyboard_leave_chat()
|
||||
|
||||
|
||||
@@ -19,7 +19,8 @@ class TestAdminService:
|
||||
self.mock_db = Mock()
|
||||
self.admin_service = AdminService(self.mock_db)
|
||||
|
||||
def test_get_last_users_success(self):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_last_users_success(self):
|
||||
"""Тест успешного получения списка последних пользователей"""
|
||||
# Arrange
|
||||
# Формат данных: кортежи (full_name, user_id) как возвращает БД
|
||||
@@ -27,10 +28,10 @@ class TestAdminService:
|
||||
('User One', 1), # (full_name, user_id)
|
||||
('User Two', 2) # (full_name, user_id)
|
||||
]
|
||||
self.mock_db.get_last_users_from_db.return_value = mock_users_data
|
||||
self.mock_db.get_last_users = AsyncMock(return_value=mock_users_data)
|
||||
|
||||
# Act
|
||||
result = self.admin_service.get_last_users()
|
||||
result = await self.admin_service.get_last_users()
|
||||
|
||||
# Assert
|
||||
assert len(result) == 2
|
||||
@@ -41,17 +42,18 @@ class TestAdminService:
|
||||
assert result[1].username == 'Неизвестно' # username не возвращается из БД
|
||||
assert result[1].full_name == 'User Two'
|
||||
|
||||
def test_get_user_by_username_success(self):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_user_by_username_success(self):
|
||||
"""Тест успешного получения пользователя по username"""
|
||||
# Arrange
|
||||
user_id = 123
|
||||
username = "test_user"
|
||||
full_name = "Test User"
|
||||
self.mock_db.get_user_id_by_username.return_value = user_id
|
||||
self.mock_db.get_full_name_by_id.return_value = full_name
|
||||
self.mock_db.get_user_id_by_username = AsyncMock(return_value=user_id)
|
||||
self.mock_db.get_full_name_by_id = AsyncMock(return_value=full_name)
|
||||
|
||||
# Act
|
||||
result = self.admin_service.get_user_by_username(username)
|
||||
result = await self.admin_service.get_user_by_username(username)
|
||||
|
||||
# Assert
|
||||
assert result is not None
|
||||
@@ -59,27 +61,35 @@ class TestAdminService:
|
||||
assert result.username == username
|
||||
assert result.full_name == full_name
|
||||
|
||||
def test_get_user_by_username_not_found(self):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_user_by_username_not_found(self):
|
||||
"""Тест получения пользователя по несуществующему username"""
|
||||
# Arrange
|
||||
username = "nonexistent_user"
|
||||
self.mock_db.get_user_id_by_username.return_value = None
|
||||
self.mock_db.get_user_id_by_username = AsyncMock(return_value=None)
|
||||
|
||||
# Act
|
||||
result = self.admin_service.get_user_by_username(username)
|
||||
result = await self.admin_service.get_user_by_username(username)
|
||||
|
||||
# Assert
|
||||
assert result is None
|
||||
|
||||
def test_get_user_by_id_success(self):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_user_by_id_success(self):
|
||||
"""Тест успешного получения пользователя по ID"""
|
||||
# Arrange
|
||||
user_id = 123
|
||||
user_info = {'username': 'test_user', 'full_name': 'Test User'}
|
||||
self.mock_db.get_user_info_by_id.return_value = user_info
|
||||
from database.models import User as DBUser
|
||||
user_info = DBUser(
|
||||
user_id=user_id,
|
||||
first_name="Test",
|
||||
full_name="Test User",
|
||||
username="test_user"
|
||||
)
|
||||
self.mock_db.get_user_by_id = AsyncMock(return_value=user_info)
|
||||
|
||||
# Act
|
||||
result = self.admin_service.get_user_by_id(user_id)
|
||||
result = await self.admin_service.get_user_by_id(user_id)
|
||||
|
||||
# Assert
|
||||
assert result is not None
|
||||
@@ -87,45 +97,51 @@ class TestAdminService:
|
||||
assert result.username == 'test_user'
|
||||
assert result.full_name == 'Test User'
|
||||
|
||||
def test_get_user_by_id_not_found(self):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_user_by_id_not_found(self):
|
||||
"""Тест получения пользователя по несуществующему ID"""
|
||||
# Arrange
|
||||
user_id = 999
|
||||
self.mock_db.get_user_info_by_id.return_value = None
|
||||
self.mock_db.get_user_by_id = AsyncMock(return_value=None)
|
||||
|
||||
# Act
|
||||
result = self.admin_service.get_user_by_id(user_id)
|
||||
result = await self.admin_service.get_user_by_id(user_id)
|
||||
|
||||
# Assert
|
||||
assert result is None
|
||||
|
||||
def test_validate_user_input_success(self):
|
||||
@pytest.mark.asyncio
|
||||
async def test_validate_user_input_success(self):
|
||||
"""Тест успешной валидации ID пользователя"""
|
||||
# Act
|
||||
result = self.admin_service.validate_user_input("123")
|
||||
result = await self.admin_service.validate_user_input("123")
|
||||
|
||||
# Assert
|
||||
assert result == 123
|
||||
|
||||
def test_validate_user_input_invalid_number(self):
|
||||
@pytest.mark.asyncio
|
||||
async def test_validate_user_input_invalid_number(self):
|
||||
"""Тест валидации некорректного ID"""
|
||||
# Act & Assert
|
||||
with pytest.raises(InvalidInputError, match="ID пользователя должен быть числом"):
|
||||
self.admin_service.validate_user_input("abc")
|
||||
await self.admin_service.validate_user_input("abc")
|
||||
|
||||
def test_validate_user_input_negative_number(self):
|
||||
@pytest.mark.asyncio
|
||||
async def test_validate_user_input_negative_number(self):
|
||||
"""Тест валидации отрицательного ID"""
|
||||
# Act & Assert
|
||||
with pytest.raises(InvalidInputError, match="ID пользователя должен быть положительным числом"):
|
||||
self.admin_service.validate_user_input("-1")
|
||||
await self.admin_service.validate_user_input("-1")
|
||||
|
||||
def test_validate_user_input_zero(self):
|
||||
@pytest.mark.asyncio
|
||||
async def test_validate_user_input_zero(self):
|
||||
"""Тест валидации нулевого ID"""
|
||||
# Act & Assert
|
||||
with pytest.raises(InvalidInputError, match="ID пользователя должен быть положительным числом"):
|
||||
self.admin_service.validate_user_input("0")
|
||||
await self.admin_service.validate_user_input("0")
|
||||
|
||||
def test_ban_user_success(self):
|
||||
@pytest.mark.asyncio
|
||||
async def test_ban_user_success(self):
|
||||
"""Тест успешной блокировки пользователя"""
|
||||
# Arrange
|
||||
user_id = 123
|
||||
@@ -133,17 +149,18 @@ class TestAdminService:
|
||||
reason = "Test ban"
|
||||
ban_days = 7
|
||||
|
||||
self.mock_db.check_user_in_blacklist.return_value = False
|
||||
self.mock_db.set_user_blacklist.return_value = None
|
||||
self.mock_db.check_user_in_blacklist = AsyncMock(return_value=False)
|
||||
self.mock_db.set_user_blacklist = AsyncMock(return_value=None)
|
||||
|
||||
# Act
|
||||
self.admin_service.ban_user(user_id, username, reason, ban_days)
|
||||
await self.admin_service.ban_user(user_id, username, reason, ban_days)
|
||||
|
||||
# Assert
|
||||
self.mock_db.check_user_in_blacklist.assert_called_once_with(user_id)
|
||||
self.mock_db.set_user_blacklist.assert_called_once()
|
||||
|
||||
def test_ban_user_already_banned(self):
|
||||
@pytest.mark.asyncio
|
||||
async def test_ban_user_already_banned(self):
|
||||
"""Тест попытки заблокировать уже заблокированного пользователя"""
|
||||
# Arrange
|
||||
user_id = 123
|
||||
@@ -151,13 +168,14 @@ class TestAdminService:
|
||||
reason = "Test ban"
|
||||
ban_days = 7
|
||||
|
||||
self.mock_db.check_user_in_blacklist.return_value = True
|
||||
self.mock_db.check_user_in_blacklist = AsyncMock(return_value=True)
|
||||
|
||||
# Act & Assert
|
||||
with pytest.raises(UserAlreadyBannedError, match=f"Пользователь {user_id} уже заблокирован"):
|
||||
self.admin_service.ban_user(user_id, username, reason, ban_days)
|
||||
await self.admin_service.ban_user(user_id, username, reason, ban_days)
|
||||
|
||||
def test_ban_user_permanent(self):
|
||||
@pytest.mark.asyncio
|
||||
async def test_ban_user_permanent(self):
|
||||
"""Тест постоянной блокировки пользователя"""
|
||||
# Arrange
|
||||
user_id = 123
|
||||
@@ -165,23 +183,24 @@ class TestAdminService:
|
||||
reason = "Permanent ban"
|
||||
ban_days = None
|
||||
|
||||
self.mock_db.check_user_in_blacklist.return_value = False
|
||||
self.mock_db.set_user_blacklist.return_value = None
|
||||
self.mock_db.check_user_in_blacklist = AsyncMock(return_value=False)
|
||||
self.mock_db.set_user_blacklist = AsyncMock(return_value=None)
|
||||
|
||||
# Act
|
||||
self.admin_service.ban_user(user_id, username, reason, ban_days)
|
||||
await self.admin_service.ban_user(user_id, username, reason, ban_days)
|
||||
|
||||
# Assert
|
||||
self.mock_db.set_user_blacklist.assert_called_once_with(user_id, username, reason, None)
|
||||
self.mock_db.set_user_blacklist.assert_called_once_with(user_id, None, reason, None)
|
||||
|
||||
def test_unban_user_success(self):
|
||||
@pytest.mark.asyncio
|
||||
async def test_unban_user_success(self):
|
||||
"""Тест успешной разблокировки пользователя"""
|
||||
# Arrange
|
||||
user_id = 123
|
||||
self.mock_db.delete_user_blacklist.return_value = None
|
||||
self.mock_db.delete_user_blacklist = AsyncMock(return_value=None)
|
||||
|
||||
# Act
|
||||
self.admin_service.unban_user(user_id)
|
||||
await self.admin_service.unban_user(user_id)
|
||||
|
||||
# Assert
|
||||
self.mock_db.delete_user_blacklist.assert_called_once_with(user_id)
|
||||
|
||||
@@ -75,9 +75,10 @@ class TestGroupHandlers:
|
||||
assert handlers.admin_reply_service is not None
|
||||
assert handlers.router is not None
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_handle_message_success(self, mock_db, mock_keyboard_markup, mock_reply_message, mock_state):
|
||||
"""Test successful message handling"""
|
||||
mock_db.get_user_by_message_id.return_value = 99999
|
||||
mock_db.get_user_by_message_id = AsyncMock(return_value=99999)
|
||||
|
||||
handlers = create_group_handlers(mock_db, mock_keyboard_markup)
|
||||
|
||||
@@ -97,6 +98,7 @@ class TestGroupHandlers:
|
||||
# Verify state was set
|
||||
mock_state.set_state.assert_called_once_with(FSM_STATES["CHAT"])
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_handle_message_no_reply(self, mock_db, mock_keyboard_markup, mock_message, mock_state):
|
||||
"""Test message handling without reply"""
|
||||
handlers = create_group_handlers(mock_db, mock_keyboard_markup)
|
||||
@@ -121,9 +123,10 @@ class TestGroupHandlers:
|
||||
# Verify state was not set
|
||||
mock_state.set_state.assert_not_called()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_handle_message_user_not_found(self, mock_db, mock_keyboard_markup, mock_reply_message, mock_state):
|
||||
"""Test message handling when user is not found"""
|
||||
mock_db.get_user_by_message_id.return_value = None
|
||||
mock_db.get_user_by_message_id = AsyncMock(return_value=None)
|
||||
|
||||
handlers = create_group_handlers(mock_db, mock_keyboard_markup)
|
||||
|
||||
@@ -154,24 +157,27 @@ class TestAdminReplyService:
|
||||
"""Create service instance"""
|
||||
return AdminReplyService(mock_db)
|
||||
|
||||
def test_get_user_id_for_reply_success(self, service, mock_db):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_user_id_for_reply_success(self, service, mock_db):
|
||||
"""Test successful user ID retrieval"""
|
||||
mock_db.get_user_by_message_id.return_value = 12345
|
||||
mock_db.get_user_by_message_id = AsyncMock(return_value=12345)
|
||||
|
||||
result = service.get_user_id_for_reply(111)
|
||||
result = await service.get_user_id_for_reply(111)
|
||||
|
||||
assert result == 12345
|
||||
mock_db.get_user_by_message_id.assert_called_once_with(111)
|
||||
|
||||
def test_get_user_id_for_reply_not_found(self, service, mock_db):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_user_id_for_reply_not_found(self, service, mock_db):
|
||||
"""Test user ID retrieval when user not found"""
|
||||
mock_db.get_user_by_message_id.return_value = None
|
||||
mock_db.get_user_by_message_id = AsyncMock(return_value=None)
|
||||
|
||||
with pytest.raises(UserNotFoundError, match="User not found for message_id: 111"):
|
||||
service.get_user_id_for_reply(111)
|
||||
await service.get_user_id_for_reply(111)
|
||||
|
||||
mock_db.get_user_by_message_id.assert_called_once_with(111)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_send_reply_to_user(self, service, mock_db):
|
||||
"""Test sending reply to user"""
|
||||
message = Mock()
|
||||
|
||||
@@ -19,13 +19,13 @@ class TestPrivateHandlers:
|
||||
def mock_db(self):
|
||||
"""Mock database"""
|
||||
db = Mock()
|
||||
db.user_exists.return_value = False
|
||||
db.add_new_user_in_db = Mock()
|
||||
db.update_date_for_user = Mock()
|
||||
db.update_info_about_stickers = Mock()
|
||||
db.add_post_in_db = Mock()
|
||||
db.add_new_message_in_db = Mock()
|
||||
db.update_helper_message_in_db = Mock()
|
||||
db.user_exists = AsyncMock(return_value=False)
|
||||
db.add_user = AsyncMock()
|
||||
db.update_user_date = AsyncMock()
|
||||
db.update_stickers_info = AsyncMock()
|
||||
db.add_post = AsyncMock()
|
||||
db.add_message = AsyncMock()
|
||||
db.update_helper_message = AsyncMock()
|
||||
return db
|
||||
|
||||
@pytest.fixture
|
||||
@@ -101,7 +101,8 @@ class TestPrivateHandlers:
|
||||
|
||||
# Mock the check_user_emoji function
|
||||
with pytest.MonkeyPatch().context() as m:
|
||||
m.setattr('helper_bot.handlers.private.private_handlers.check_user_emoji', lambda x: "😊")
|
||||
mock_check_emoji = AsyncMock(return_value="😊")
|
||||
m.setattr('helper_bot.handlers.private.private_handlers.check_user_emoji', mock_check_emoji)
|
||||
|
||||
# Test the handler
|
||||
await handlers.handle_emoji_message(mock_message, mock_state)
|
||||
@@ -121,7 +122,8 @@ class TestPrivateHandlers:
|
||||
with pytest.MonkeyPatch().context() as m:
|
||||
m.setattr('helper_bot.handlers.private.private_handlers.get_first_name', lambda x: "Test")
|
||||
m.setattr('helper_bot.handlers.private.private_handlers.messages.get_message', lambda x, y: "Hello Test!")
|
||||
m.setattr('helper_bot.handlers.private.private_handlers.get_reply_keyboard', lambda x, y: Mock())
|
||||
mock_keyboard = AsyncMock(return_value=Mock())
|
||||
m.setattr('helper_bot.handlers.private.private_handlers.get_reply_keyboard', mock_keyboard)
|
||||
|
||||
# Test the handler
|
||||
await handlers.handle_start_message(mock_message, mock_state)
|
||||
@@ -130,8 +132,8 @@ class TestPrivateHandlers:
|
||||
mock_state.set_state.assert_called_once_with(FSM_STATES["START"])
|
||||
|
||||
# Verify user was ensured to exist
|
||||
mock_db.add_new_user_in_db.assert_called_once()
|
||||
mock_db.update_date_for_user.assert_called_once()
|
||||
mock_db.add_user.assert_called_once()
|
||||
mock_db.update_user_date.assert_called_once()
|
||||
|
||||
|
||||
class TestBotSettings:
|
||||
|
||||
@@ -31,7 +31,7 @@ from helper_bot.utils.helper_func import (
|
||||
)
|
||||
from helper_bot.utils.messages import get_message
|
||||
from helper_bot.utils.base_dependency_factory import BaseDependencyFactory, get_global_instance
|
||||
from database.db import BotDB
|
||||
from database.async_db import AsyncBotDB
|
||||
import helper_bot.utils.messages as messages # Import for patching constants
|
||||
|
||||
class TestHelperFunctions:
|
||||
@@ -83,25 +83,27 @@ class TestHelperFunctions:
|
||||
assert "testuser" in result
|
||||
assert "Обычный текст без специальных слов" in result
|
||||
|
||||
def test_check_username_and_full_name(self):
|
||||
@pytest.mark.asyncio
|
||||
async def test_check_username_and_full_name(self):
|
||||
"""Тест функции проверки изменений username и full_name"""
|
||||
# Создаем мок базы данных
|
||||
mock_db = Mock(spec=BotDB)
|
||||
mock_db.get_username_and_full_name = Mock(return_value=("olduser", "Old User"))
|
||||
mock_db = Mock(spec=AsyncBotDB)
|
||||
mock_db.get_username = AsyncMock(return_value="olduser")
|
||||
mock_db.get_full_name_by_id = AsyncMock(return_value="Old User")
|
||||
|
||||
# Тест с измененными данными
|
||||
result = check_username_and_full_name(123456, "newuser", "New User", mock_db)
|
||||
result = await check_username_and_full_name(123456, "newuser", "New User", mock_db)
|
||||
assert result is True
|
||||
|
||||
# Тест с неизмененными данными
|
||||
result = check_username_and_full_name(123456, "olduser", "Old User", mock_db)
|
||||
result = await check_username_and_full_name(123456, "olduser", "Old User", mock_db)
|
||||
assert result is False
|
||||
|
||||
# Тест с частично измененными данными
|
||||
result = check_username_and_full_name(123456, "olduser", "New User", mock_db)
|
||||
result = await check_username_and_full_name(123456, "olduser", "New User", mock_db)
|
||||
assert result is True
|
||||
|
||||
result = check_username_and_full_name(123456, "newuser", "Old User", mock_db)
|
||||
result = await check_username_and_full_name(123456, "newuser", "Old User", mock_db)
|
||||
assert result is True
|
||||
|
||||
|
||||
@@ -330,7 +332,7 @@ class TestPrepareMediaGroup:
|
||||
assert result[0].media == "photo_0"
|
||||
assert result[1].media == "photo_1"
|
||||
assert result[2].media == "photo_2"
|
||||
assert result[2].caption == "Тестовая подпись"
|
||||
assert result[0].caption == "Тестовая подпись" # Первое фото должно иметь caption
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_prepare_media_group_mixed_types(self):
|
||||
@@ -364,7 +366,7 @@ class TestPrepareMediaGroup:
|
||||
assert result[0].media == "photo_1"
|
||||
assert result[1].media == "video_1"
|
||||
assert result[2].media == "audio_1"
|
||||
assert result[2].caption == "Смешанная группа"
|
||||
assert result[0].caption == "Смешанная группа" # Первое медиа должно иметь caption
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_prepare_media_group_empty_album(self):
|
||||
@@ -381,6 +383,7 @@ class TestPrepareMediaGroup:
|
||||
message.photo = None
|
||||
message.video = None
|
||||
message.audio = None
|
||||
message.document = None # Добавляем document = None
|
||||
album.append(message)
|
||||
|
||||
result = await prepare_media_group_from_middlewares(album, "Тест")
|
||||
@@ -401,12 +404,12 @@ class TestMediaDatabaseOperations:
|
||||
message.photo[-1].file_id = f"photo_{i}"
|
||||
sent_message.append(message)
|
||||
|
||||
mock_db = Mock()
|
||||
mock_db = AsyncMock()
|
||||
|
||||
with patch('helper_bot.utils.helper_func.download_file', return_value=f"files/photo_{i}.jpg"):
|
||||
await add_in_db_media_mediagroup(sent_message, mock_db)
|
||||
|
||||
assert mock_db.add_post_content_in_db.call_count == 2
|
||||
assert mock_db.add_post_content.call_count == 2
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_add_in_db_media_photo(self):
|
||||
@@ -416,12 +419,12 @@ class TestMediaDatabaseOperations:
|
||||
mock_message.photo = [Mock()]
|
||||
mock_message.photo[-1].file_id = "photo_123"
|
||||
|
||||
mock_db = Mock()
|
||||
mock_db = AsyncMock()
|
||||
|
||||
with patch('helper_bot.utils.helper_func.download_file', return_value="files/photo_123.jpg"):
|
||||
await add_in_db_media(mock_message, mock_db)
|
||||
|
||||
mock_db.add_post_content_in_db.assert_called_once_with(
|
||||
mock_db.add_post_content.assert_called_once_with(
|
||||
123, 123, "files/photo_123.jpg", 'photo'
|
||||
)
|
||||
|
||||
@@ -434,12 +437,12 @@ class TestMediaDatabaseOperations:
|
||||
mock_message.video = Mock()
|
||||
mock_message.video.file_id = "video_123"
|
||||
|
||||
mock_db = Mock()
|
||||
mock_db = AsyncMock()
|
||||
|
||||
with patch('helper_bot.utils.helper_func.download_file', return_value="files/video_123.mp4"):
|
||||
await add_in_db_media(mock_message, mock_db)
|
||||
|
||||
mock_db.add_post_content_in_db.assert_called_once_with(
|
||||
mock_db.add_post_content.assert_called_once_with(
|
||||
123, 123, "files/video_123.mp4", 'video'
|
||||
)
|
||||
|
||||
@@ -453,12 +456,12 @@ class TestMediaDatabaseOperations:
|
||||
mock_message.voice = Mock()
|
||||
mock_message.voice.file_id = "voice_123"
|
||||
|
||||
mock_db = Mock()
|
||||
mock_db = AsyncMock()
|
||||
|
||||
with patch('helper_bot.utils.helper_func.download_file', return_value="files/voice_123.ogg"):
|
||||
await add_in_db_media(mock_message, mock_db)
|
||||
|
||||
mock_db.add_post_content_in_db.assert_called_once_with(
|
||||
mock_db.add_post_content.assert_called_once_with(
|
||||
123, 123, "files/voice_123.ogg", 'voice'
|
||||
)
|
||||
|
||||
@@ -548,16 +551,17 @@ class TestSendMessageFunctions:
|
||||
class TestUtilityFunctions:
|
||||
"""Тесты для утилитарных функций"""
|
||||
|
||||
def test_check_access(self):
|
||||
@pytest.mark.asyncio
|
||||
async def test_check_access(self):
|
||||
"""Тест проверки доступа"""
|
||||
mock_db = Mock()
|
||||
mock_db = AsyncMock()
|
||||
mock_db.is_admin.return_value = True
|
||||
|
||||
result = check_access(123, mock_db)
|
||||
result = await check_access(123, mock_db)
|
||||
assert result is True
|
||||
|
||||
mock_db.is_admin.return_value = False
|
||||
result = check_access(123, mock_db)
|
||||
result = await check_access(123, mock_db)
|
||||
assert result is False
|
||||
|
||||
def test_add_days_to_date(self):
|
||||
@@ -569,45 +573,51 @@ class TestUtilityFunctions:
|
||||
mock_datetime.timedelta = timedelta
|
||||
|
||||
result = add_days_to_date(5)
|
||||
expected_date = (mock_now + timedelta(days=5)).strftime("%d-%m-%Y")
|
||||
assert result == expected_date
|
||||
expected_timestamp = int((mock_now + timedelta(days=5)).timestamp())
|
||||
assert result == expected_timestamp
|
||||
|
||||
def test_get_banned_users_list(self):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_banned_users_list(self):
|
||||
"""Тест получения списка заблокированных пользователей"""
|
||||
mock_db = Mock()
|
||||
mock_db = AsyncMock()
|
||||
mock_db.get_banned_users_from_db_with_limits.return_value = [
|
||||
("User1", 123, "Spam", "01-01-2025"),
|
||||
("User2", 456, "Violation", "02-01-2025")
|
||||
(123, "Spam", 1704067200), # user_id, ban_reason, unban_date (timestamp)
|
||||
(456, "Violation", 1704153600)
|
||||
]
|
||||
mock_db.get_username.return_value = None
|
||||
mock_db.get_full_name_by_id.return_value = "Test User"
|
||||
|
||||
result = get_banned_users_list(0, mock_db)
|
||||
result = await get_banned_users_list(0, mock_db)
|
||||
|
||||
assert "Список заблокированных пользователей:" in result
|
||||
assert "User1" in result
|
||||
assert "User2" in result
|
||||
assert "Test User" in result
|
||||
assert "Spam" in result
|
||||
assert "Violation" in result
|
||||
|
||||
def test_get_banned_users_buttons(self):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_banned_users_buttons(self):
|
||||
"""Тест получения кнопок заблокированных пользователей"""
|
||||
mock_db = Mock()
|
||||
mock_db = AsyncMock()
|
||||
mock_db.get_banned_users_from_db.return_value = [
|
||||
("User1", 123),
|
||||
("User2", 456)
|
||||
(123, "Spam", 1704067200), # user_id, ban_reason, unban_date
|
||||
(456, "Violation", 1704153600)
|
||||
]
|
||||
mock_db.get_username.return_value = None
|
||||
mock_db.get_full_name_by_id.return_value = "Test User"
|
||||
|
||||
result = get_banned_users_buttons(mock_db)
|
||||
result = await get_banned_users_buttons(mock_db)
|
||||
|
||||
assert len(result) == 2
|
||||
assert result[0] == ("User1", 123)
|
||||
assert result[1] == ("User2", 456)
|
||||
assert result[0] == ("Test User", 123)
|
||||
assert result[1] == ("Test User", 456)
|
||||
|
||||
def test_delete_user_blacklist(self):
|
||||
@pytest.mark.asyncio
|
||||
async def test_delete_user_blacklist(self):
|
||||
"""Тест удаления пользователя из черного списка"""
|
||||
mock_db = Mock()
|
||||
mock_db = AsyncMock()
|
||||
mock_db.delete_user_blacklist.return_value = True
|
||||
|
||||
result = delete_user_blacklist(123, mock_db)
|
||||
result = await delete_user_blacklist(123, mock_db)
|
||||
assert result is True
|
||||
|
||||
mock_db.delete_user_blacklist.assert_called_once_with(user_id=123)
|
||||
@@ -631,57 +641,61 @@ class TestUserManagement:
|
||||
with patch('helper_bot.utils.helper_func.get_first_name', return_value="Test"):
|
||||
with patch('helper_bot.utils.helper_func.get_random_emoji', return_value="😀"):
|
||||
with patch('helper_bot.utils.helper_func.BotDB') as mock_bot_db:
|
||||
mock_bot_db.user_exists.return_value = False
|
||||
mock_bot_db.add_new_user_in_db = Mock()
|
||||
mock_bot_db.update_date_for_user = Mock()
|
||||
mock_bot_db.user_exists = AsyncMock(return_value=False)
|
||||
mock_bot_db.add_user = AsyncMock()
|
||||
mock_bot_db.update_user_date = AsyncMock()
|
||||
|
||||
await update_user_info("test", mock_message)
|
||||
|
||||
mock_bot_db.add_new_user_in_db.assert_called_once()
|
||||
mock_bot_db.update_date_for_user.assert_called_once()
|
||||
mock_bot_db.add_user.assert_called_once()
|
||||
mock_bot_db.update_user_date.assert_called_once()
|
||||
|
||||
def test_check_user_emoji_existing(self):
|
||||
@pytest.mark.asyncio
|
||||
async def test_check_user_emoji_existing(self):
|
||||
"""Тест проверки эмодзи пользователя (существующий)"""
|
||||
mock_message = Mock()
|
||||
mock_message.from_user.id = 123
|
||||
|
||||
with patch('helper_bot.utils.helper_func.BotDB') as mock_bot_db:
|
||||
mock_bot_db.check_emoji_for_user.return_value = "😀"
|
||||
mock_bot_db.get_user_emoji = AsyncMock(return_value="😀")
|
||||
|
||||
result = check_user_emoji(mock_message)
|
||||
result = await check_user_emoji(mock_message)
|
||||
assert result == "😀"
|
||||
|
||||
def test_check_user_emoji_new(self):
|
||||
@pytest.mark.asyncio
|
||||
async def test_check_user_emoji_new(self):
|
||||
"""Тест проверки эмодзи пользователя (новый)"""
|
||||
mock_message = Mock()
|
||||
mock_message.from_user.id = 123
|
||||
|
||||
with patch('helper_bot.utils.helper_func.BotDB') as mock_bot_db:
|
||||
mock_bot_db.check_emoji_for_user.return_value = None
|
||||
mock_bot_db.update_emoji_for_user = Mock()
|
||||
mock_bot_db.get_user_emoji = AsyncMock(return_value=None)
|
||||
mock_bot_db.update_user_emoji = AsyncMock()
|
||||
|
||||
with patch('helper_bot.utils.helper_func.get_random_emoji', return_value="😀"):
|
||||
result = check_user_emoji(mock_message)
|
||||
result = await check_user_emoji(mock_message)
|
||||
assert result == "😀"
|
||||
mock_bot_db.update_emoji_for_user.assert_called_once_with(user_id=123, emoji="😀")
|
||||
mock_bot_db.update_user_emoji.assert_called_once_with(user_id=123, emoji="😀")
|
||||
|
||||
def test_get_random_emoji_success(self):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_random_emoji_success(self):
|
||||
"""Тест получения случайного эмодзи (успех)"""
|
||||
with patch('helper_bot.utils.helper_func.BotDB') as mock_bot_db:
|
||||
mock_bot_db.check_emoji.return_value = False
|
||||
mock_bot_db.check_emoji_exists = AsyncMock(return_value=False)
|
||||
|
||||
with patch('helper_bot.utils.helper_func.random.choice', return_value="😀"):
|
||||
result = get_random_emoji()
|
||||
result = await get_random_emoji()
|
||||
assert result == "😀"
|
||||
|
||||
def test_get_random_emoji_fallback(self):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_random_emoji_fallback(self):
|
||||
"""Тест получения случайного эмодзи (fallback)"""
|
||||
with patch('helper_bot.utils.helper_func.BotDB') as mock_bot_db:
|
||||
mock_bot_db.check_emoji.return_value = True # Все эмодзи заняты
|
||||
mock_bot_db.check_emoji_exists = AsyncMock(return_value=True) # Все эмодзи заняты
|
||||
|
||||
with patch('helper_bot.utils.helper_func.random.choice', return_value="😀"):
|
||||
with patch('helper_bot.utils.helper_func.logger') as mock_logger:
|
||||
result = get_random_emoji()
|
||||
result = await get_random_emoji()
|
||||
assert result == "Эмоджи не определен"
|
||||
mock_logger.error.assert_called_once()
|
||||
|
||||
|
||||
@@ -55,14 +55,15 @@ class TestVoiceBotService:
|
||||
|
||||
assert sticker is None
|
||||
|
||||
def test_get_random_audio_success(self, voice_service, mock_bot_db):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_random_audio_success(self, voice_service, mock_bot_db):
|
||||
"""Тест успешного получения случайного аудио"""
|
||||
mock_bot_db.check_listen_audio.return_value = ['audio1', 'audio2']
|
||||
mock_bot_db.get_user_id_by_file_name.return_value = 123
|
||||
mock_bot_db.get_date_by_file_name.return_value = '2025-01-01 12:00:00'
|
||||
mock_bot_db.check_emoji_for_user.return_value = '😊'
|
||||
mock_bot_db.check_listen_audio = AsyncMock(return_value=['audio1', 'audio2'])
|
||||
mock_bot_db.get_user_id_by_file_name = AsyncMock(return_value=123)
|
||||
mock_bot_db.get_date_by_file_name = AsyncMock(return_value='2025-01-01 12:00:00')
|
||||
mock_bot_db.get_user_emoji = AsyncMock(return_value='😊')
|
||||
|
||||
result = voice_service.get_random_audio(456)
|
||||
result = await voice_service.get_random_audio(456)
|
||||
|
||||
assert result is not None
|
||||
assert len(result) == 3
|
||||
@@ -70,40 +71,49 @@ class TestVoiceBotService:
|
||||
assert result[1] == '2025-01-01 12:00:00'
|
||||
assert result[2] == '😊'
|
||||
|
||||
def test_get_random_audio_no_audio(self, voice_service, mock_bot_db):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_random_audio_no_audio(self, voice_service, mock_bot_db):
|
||||
"""Тест получения аудио когда их нет"""
|
||||
mock_bot_db.check_listen_audio.return_value = []
|
||||
mock_bot_db.check_listen_audio = AsyncMock(return_value=[])
|
||||
|
||||
result = voice_service.get_random_audio(456)
|
||||
result = await voice_service.get_random_audio(456)
|
||||
|
||||
assert result is None
|
||||
|
||||
def test_mark_audio_as_listened_success(self, voice_service, mock_bot_db):
|
||||
@pytest.mark.asyncio
|
||||
async def test_mark_audio_as_listened_success(self, voice_service, mock_bot_db):
|
||||
"""Тест успешной пометки аудио как прослушанного"""
|
||||
voice_service.mark_audio_as_listened('test_audio', 123)
|
||||
mock_bot_db.mark_listened_audio = AsyncMock()
|
||||
|
||||
await voice_service.mark_audio_as_listened('test_audio', 123)
|
||||
|
||||
mock_bot_db.mark_listened_audio.assert_called_once_with('test_audio', user_id=123)
|
||||
|
||||
def test_clear_user_listenings_success(self, voice_service, mock_bot_db):
|
||||
@pytest.mark.asyncio
|
||||
async def test_clear_user_listenings_success(self, voice_service, mock_bot_db):
|
||||
"""Тест успешной очистки прослушиваний"""
|
||||
voice_service.clear_user_listenings(123)
|
||||
mock_bot_db.delete_listen_count_for_user = AsyncMock()
|
||||
|
||||
await voice_service.clear_user_listenings(123)
|
||||
|
||||
mock_bot_db.delete_listen_count_for_user.assert_called_once_with(123)
|
||||
|
||||
def test_get_remaining_audio_count_success(self, voice_service, mock_bot_db):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_remaining_audio_count_success(self, voice_service, mock_bot_db):
|
||||
"""Тест получения количества оставшихся аудио"""
|
||||
mock_bot_db.check_listen_audio.return_value = ['audio1', 'audio2', 'audio3']
|
||||
mock_bot_db.check_listen_audio = AsyncMock(return_value=['audio1', 'audio2', 'audio3'])
|
||||
|
||||
result = voice_service.get_remaining_audio_count(123)
|
||||
result = await voice_service.get_remaining_audio_count(123)
|
||||
|
||||
assert result == 3
|
||||
mock_bot_db.check_listen_audio.assert_called_once_with(user_id=123)
|
||||
|
||||
def test_get_remaining_audio_count_zero(self, voice_service, mock_bot_db):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_remaining_audio_count_zero(self, voice_service, mock_bot_db):
|
||||
"""Тест получения количества оставшихся аудио когда их нет"""
|
||||
mock_bot_db.check_listen_audio.return_value = []
|
||||
mock_bot_db.check_listen_audio = AsyncMock(return_value=[])
|
||||
|
||||
result = voice_service.get_remaining_audio_count(123)
|
||||
result = await voice_service.get_remaining_audio_count(123)
|
||||
|
||||
assert result == 0
|
||||
mock_bot_db.check_listen_audio.assert_called_once_with(user_id=123)
|
||||
@@ -187,57 +197,64 @@ class TestUtils:
|
||||
"""Мок для базы данных"""
|
||||
return Mock()
|
||||
|
||||
def test_get_last_message_text(self, mock_bot_db):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_last_message_text(self, mock_bot_db):
|
||||
"""Тест получения последнего сообщения"""
|
||||
mock_bot_db.last_date_audio.return_value = "2025-01-01 12:00:00"
|
||||
# Возвращаем UNIX timestamp
|
||||
mock_bot_db.last_date_audio = AsyncMock(return_value=1641034800) # 2022-01-01 12:00:00
|
||||
|
||||
result = get_last_message_text(mock_bot_db)
|
||||
result = await get_last_message_text(mock_bot_db)
|
||||
|
||||
assert result is not None
|
||||
assert "минут" in result or "часа" in result or "дня" in result
|
||||
assert "минут" in result or "часа" in result or "дня" in result or "день" in result or "дней" in result
|
||||
mock_bot_db.last_date_audio.assert_called_once()
|
||||
|
||||
def test_validate_voice_message_valid(self):
|
||||
@pytest.mark.asyncio
|
||||
async def test_validate_voice_message_valid(self):
|
||||
"""Тест валидации голосового сообщения"""
|
||||
mock_message = Mock()
|
||||
mock_message.content_type = 'voice'
|
||||
mock_message.voice = Mock()
|
||||
|
||||
result = validate_voice_message(mock_message)
|
||||
result = await validate_voice_message(mock_message)
|
||||
|
||||
assert result is True
|
||||
|
||||
def test_validate_voice_message_invalid(self):
|
||||
@pytest.mark.asyncio
|
||||
async def test_validate_voice_message_invalid(self):
|
||||
"""Тест валидации невалидного сообщения"""
|
||||
mock_message = Mock()
|
||||
mock_message.voice = None
|
||||
|
||||
result = validate_voice_message(mock_message)
|
||||
result = await validate_voice_message(mock_message)
|
||||
|
||||
assert result is False
|
||||
|
||||
def test_get_user_emoji_safe(self, mock_bot_db):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_user_emoji_safe(self, mock_bot_db):
|
||||
"""Тест безопасного получения эмодзи пользователя"""
|
||||
mock_bot_db.check_emoji_for_user.return_value = "😊"
|
||||
mock_bot_db.get_user_emoji = AsyncMock(return_value="😊")
|
||||
|
||||
result = get_user_emoji_safe(mock_bot_db, 123)
|
||||
result = await get_user_emoji_safe(mock_bot_db, 123)
|
||||
|
||||
assert result == "😊"
|
||||
mock_bot_db.check_emoji_for_user.assert_called_once_with(123)
|
||||
mock_bot_db.get_user_emoji.assert_called_once_with(123)
|
||||
|
||||
def test_get_user_emoji_safe_none(self, mock_bot_db):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_user_emoji_safe_none(self, mock_bot_db):
|
||||
"""Тест безопасного получения эмодзи когда его нет"""
|
||||
mock_bot_db.check_emoji_for_user.return_value = None
|
||||
mock_bot_db.get_user_emoji = AsyncMock(return_value=None)
|
||||
|
||||
result = get_user_emoji_safe(mock_bot_db, 123)
|
||||
result = await get_user_emoji_safe(mock_bot_db, 123)
|
||||
|
||||
assert result == "😊"
|
||||
|
||||
def test_get_user_emoji_safe_error(self, mock_bot_db):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_user_emoji_safe_error(self, mock_bot_db):
|
||||
"""Тест безопасного получения эмодзи при ошибке"""
|
||||
mock_bot_db.check_emoji_for_user.return_value = "Ошибка"
|
||||
mock_bot_db.get_user_emoji = AsyncMock(return_value="Ошибка")
|
||||
|
||||
result = get_user_emoji_safe(mock_bot_db, 123)
|
||||
result = await get_user_emoji_safe(mock_bot_db, 123)
|
||||
|
||||
assert result == "Ошибка"
|
||||
|
||||
|
||||
@@ -151,7 +151,7 @@ class TestVoiceConstants:
|
||||
assert value.startswith("voice_")
|
||||
|
||||
def test_no_duplicate_values(self):
|
||||
"""Тест отсутствия дублирующихся значений"""
|
||||
"""Тест отсутствия дублирующихся значений в пределах каждого маппинга"""
|
||||
button_values = list(BUTTON_COMMAND_MAPPING.values())
|
||||
command_values = list(COMMAND_MAPPING.values())
|
||||
callback_values = list(CALLBACK_COMMAND_MAPPING.values())
|
||||
@@ -161,9 +161,8 @@ class TestVoiceConstants:
|
||||
assert len(command_values) == len(set(command_values))
|
||||
assert len(callback_values) == len(set(callback_values))
|
||||
|
||||
# Проверяем, что нет дублирующихся значений между маппингами
|
||||
all_values = button_values + command_values + callback_values
|
||||
assert len(all_values) == len(set(all_values))
|
||||
# Примечание: Дублирование между маппингами допустимо (например, voice_emoji)
|
||||
# так как одно действие может быть вызвано и командой, и кнопкой
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -63,18 +63,23 @@ class TestVoiceHandler:
|
||||
@pytest.mark.asyncio
|
||||
async def test_voice_bot_button_handler_welcome_received(self, voice_handler, mock_message, mock_state, mock_db, mock_settings):
|
||||
"""Тест обработчика кнопки когда приветствие уже получено"""
|
||||
mock_db.check_voice_bot_welcome_received.return_value = True
|
||||
from unittest.mock import AsyncMock
|
||||
mock_db.check_voice_bot_welcome_received = AsyncMock(return_value=True)
|
||||
|
||||
with patch.object(voice_handler, 'restart_function') as mock_restart:
|
||||
await voice_handler.voice_bot_button_handler(mock_message, mock_state, mock_db, mock_settings)
|
||||
|
||||
mock_db.check_voice_bot_welcome_received.assert_called_once_with(123)
|
||||
mock_restart.assert_called_once_with(mock_message, mock_state, mock_db, mock_settings)
|
||||
with patch('helper_bot.handlers.voice.voice_handler.update_user_info') as mock_update_user:
|
||||
mock_update_user.return_value = None
|
||||
|
||||
await voice_handler.voice_bot_button_handler(mock_message, mock_state, mock_db, mock_settings)
|
||||
|
||||
mock_db.check_voice_bot_welcome_received.assert_called_once_with(123)
|
||||
mock_restart.assert_called_once_with(mock_message, mock_state, mock_db, mock_settings)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_voice_bot_button_handler_welcome_not_received(self, voice_handler, mock_message, mock_state, mock_db, mock_settings):
|
||||
"""Тест обработчика кнопки когда приветствие не получено"""
|
||||
mock_db.check_voice_bot_welcome_received.return_value = False
|
||||
from unittest.mock import AsyncMock
|
||||
mock_db.check_voice_bot_welcome_received = AsyncMock(return_value=False)
|
||||
|
||||
with patch.object(voice_handler, 'start') as mock_start:
|
||||
await voice_handler.voice_bot_button_handler(mock_message, mock_state, mock_db, mock_settings)
|
||||
|
||||
@@ -80,14 +80,15 @@ class TestVoiceBotService:
|
||||
assert sticker is not None
|
||||
# Проверяем, что стикер не None (метод возвращает FSInputFile объект)
|
||||
|
||||
def test_get_random_audio_success(self, voice_service, mock_bot_db):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_random_audio_success(self, voice_service, mock_bot_db):
|
||||
"""Тест успешного получения случайного аудио"""
|
||||
mock_bot_db.check_listen_audio.return_value = ['audio1', 'audio2']
|
||||
mock_bot_db.get_user_id_by_file_name.return_value = 123
|
||||
mock_bot_db.get_date_by_file_name.return_value = '2025-01-01 12:00:00'
|
||||
mock_bot_db.check_emoji_for_user.return_value = '😊'
|
||||
mock_bot_db.check_listen_audio = AsyncMock(return_value=['audio1', 'audio2'])
|
||||
mock_bot_db.get_user_id_by_file_name = AsyncMock(return_value=123)
|
||||
mock_bot_db.get_date_by_file_name = AsyncMock(return_value='2025-01-01 12:00:00')
|
||||
mock_bot_db.get_user_emoji = AsyncMock(return_value='😊')
|
||||
|
||||
result = voice_service.get_random_audio(456)
|
||||
result = await voice_service.get_random_audio(456)
|
||||
|
||||
assert result is not None
|
||||
assert len(result) == 3
|
||||
@@ -96,53 +97,63 @@ class TestVoiceBotService:
|
||||
assert result[1] == '2025-01-01 12:00:00'
|
||||
assert result[2] == '😊'
|
||||
|
||||
def test_get_random_audio_no_audio(self, voice_service, mock_bot_db):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_random_audio_no_audio(self, voice_service, mock_bot_db):
|
||||
"""Тест получения аудио когда их нет"""
|
||||
mock_bot_db.check_listen_audio.return_value = []
|
||||
mock_bot_db.check_listen_audio = AsyncMock(return_value=[])
|
||||
|
||||
result = voice_service.get_random_audio(456)
|
||||
result = await voice_service.get_random_audio(456)
|
||||
|
||||
assert result is None
|
||||
|
||||
def test_get_random_audio_single_audio(self, voice_service, mock_bot_db):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_random_audio_single_audio(self, voice_service, mock_bot_db):
|
||||
"""Тест получения аудио когда есть только одно"""
|
||||
mock_bot_db.check_listen_audio.return_value = ['audio1']
|
||||
mock_bot_db.get_user_id_by_file_name.return_value = 123
|
||||
mock_bot_db.get_date_by_file_name.return_value = '2025-01-01 12:00:00'
|
||||
mock_bot_db.check_emoji_for_user.return_value = '😊'
|
||||
mock_bot_db.check_listen_audio = AsyncMock(return_value=['audio1'])
|
||||
mock_bot_db.get_user_id_by_file_name = AsyncMock(return_value=123)
|
||||
mock_bot_db.get_date_by_file_name = AsyncMock(return_value='2025-01-01 12:00:00')
|
||||
mock_bot_db.get_user_emoji = AsyncMock(return_value='😊')
|
||||
|
||||
result = voice_service.get_random_audio(456)
|
||||
result = await voice_service.get_random_audio(456)
|
||||
|
||||
assert result is not None
|
||||
assert len(result) == 3
|
||||
assert result[0] == 'audio1'
|
||||
|
||||
def test_mark_audio_as_listened_success(self, voice_service, mock_bot_db):
|
||||
@pytest.mark.asyncio
|
||||
async def test_mark_audio_as_listened_success(self, voice_service, mock_bot_db):
|
||||
"""Тест успешной пометки аудио как прослушанного"""
|
||||
voice_service.mark_audio_as_listened('test_audio', 123)
|
||||
mock_bot_db.mark_listened_audio = AsyncMock()
|
||||
|
||||
await voice_service.mark_audio_as_listened('test_audio', 123)
|
||||
|
||||
mock_bot_db.mark_listened_audio.assert_called_once_with('test_audio', user_id=123)
|
||||
|
||||
def test_clear_user_listenings_success(self, voice_service, mock_bot_db):
|
||||
@pytest.mark.asyncio
|
||||
async def test_clear_user_listenings_success(self, voice_service, mock_bot_db):
|
||||
"""Тест успешной очистки прослушиваний"""
|
||||
voice_service.clear_user_listenings(123)
|
||||
mock_bot_db.delete_listen_count_for_user = AsyncMock()
|
||||
|
||||
await voice_service.clear_user_listenings(123)
|
||||
|
||||
mock_bot_db.delete_listen_count_for_user.assert_called_once_with(123)
|
||||
|
||||
def test_get_remaining_audio_count_success(self, voice_service, mock_bot_db):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_remaining_audio_count_success(self, voice_service, mock_bot_db):
|
||||
"""Тест получения количества оставшихся аудио"""
|
||||
mock_bot_db.check_listen_audio.return_value = ['audio1', 'audio2', 'audio3']
|
||||
mock_bot_db.check_listen_audio = AsyncMock(return_value=['audio1', 'audio2', 'audio3'])
|
||||
|
||||
result = voice_service.get_remaining_audio_count(123)
|
||||
result = await voice_service.get_remaining_audio_count(123)
|
||||
|
||||
assert result == 3
|
||||
mock_bot_db.check_listen_audio.assert_called_once_with(user_id=123)
|
||||
|
||||
def test_get_remaining_audio_count_zero(self, voice_service, mock_bot_db):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_remaining_audio_count_zero(self, voice_service, mock_bot_db):
|
||||
"""Тест получения количества оставшихся аудио когда их нет"""
|
||||
mock_bot_db.check_listen_audio.return_value = []
|
||||
mock_bot_db.check_listen_audio = AsyncMock(return_value=[])
|
||||
|
||||
result = voice_service.get_remaining_audio_count(123)
|
||||
result = await voice_service.get_remaining_audio_count(123)
|
||||
|
||||
assert result == 0
|
||||
mock_bot_db.check_listen_audio.assert_called_once_with(user_id=123)
|
||||
|
||||
@@ -39,70 +39,83 @@ class TestVoiceUtils:
|
||||
message.chat.id = 456
|
||||
return message
|
||||
|
||||
def test_get_last_message_text(self, mock_bot_db):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_last_message_text(self, mock_bot_db):
|
||||
"""Тест получения последнего сообщения"""
|
||||
mock_bot_db.last_date_audio.return_value = "2025-01-01 12:00:00"
|
||||
# Возвращаем UNIX timestamp
|
||||
from unittest.mock import AsyncMock
|
||||
mock_bot_db.last_date_audio = AsyncMock(return_value=1641034800) # 2022-01-01 12:00:00
|
||||
|
||||
result = get_last_message_text(mock_bot_db)
|
||||
result = await get_last_message_text(mock_bot_db)
|
||||
|
||||
assert result is not None
|
||||
assert "минут" in result or "часа" in result or "дня" in result
|
||||
assert "минут" in result or "часа" in result or "дня" in result or "день" in result or "дней" in result
|
||||
mock_bot_db.last_date_audio.assert_called_once()
|
||||
|
||||
def test_validate_voice_message_valid(self):
|
||||
@pytest.mark.asyncio
|
||||
async def test_validate_voice_message_valid(self):
|
||||
"""Тест валидации голосового сообщения"""
|
||||
mock_message = Mock()
|
||||
mock_message.content_type = 'voice'
|
||||
mock_message.voice = Mock()
|
||||
|
||||
result = validate_voice_message(mock_message)
|
||||
result = await validate_voice_message(mock_message)
|
||||
|
||||
assert result is True
|
||||
|
||||
def test_validate_voice_message_invalid(self):
|
||||
@pytest.mark.asyncio
|
||||
async def test_validate_voice_message_invalid(self):
|
||||
"""Тест валидации невалидного сообщения"""
|
||||
mock_message = Mock()
|
||||
mock_message.voice = None
|
||||
|
||||
result = validate_voice_message(mock_message)
|
||||
result = await validate_voice_message(mock_message)
|
||||
|
||||
assert result is False
|
||||
|
||||
def test_get_user_emoji_safe_with_emoji(self, mock_bot_db):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_user_emoji_safe_with_emoji(self, mock_bot_db):
|
||||
"""Тест безопасного получения эмодзи пользователя когда эмодзи есть"""
|
||||
mock_bot_db.check_emoji_for_user.return_value = "😊"
|
||||
from unittest.mock import AsyncMock
|
||||
mock_bot_db.get_user_emoji = AsyncMock(return_value="😊")
|
||||
|
||||
result = get_user_emoji_safe(mock_bot_db, 123)
|
||||
result = await get_user_emoji_safe(mock_bot_db, 123)
|
||||
|
||||
assert result == "😊"
|
||||
mock_bot_db.check_emoji_for_user.assert_called_once_with(123)
|
||||
mock_bot_db.get_user_emoji.assert_called_once_with(123)
|
||||
|
||||
def test_get_user_emoji_safe_without_emoji(self, mock_bot_db):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_user_emoji_safe_without_emoji(self, mock_bot_db):
|
||||
"""Тест безопасного получения эмодзи пользователя когда эмодзи нет"""
|
||||
mock_bot_db.check_emoji_for_user.return_value = None
|
||||
from unittest.mock import AsyncMock
|
||||
mock_bot_db.get_user_emoji = AsyncMock(return_value=None)
|
||||
|
||||
result = get_user_emoji_safe(mock_bot_db, 123)
|
||||
result = await get_user_emoji_safe(mock_bot_db, 123)
|
||||
|
||||
assert result == "😊"
|
||||
mock_bot_db.check_emoji_for_user.assert_called_once_with(123)
|
||||
mock_bot_db.get_user_emoji.assert_called_once_with(123)
|
||||
|
||||
def test_get_user_emoji_safe_with_empty_emoji(self, mock_bot_db):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_user_emoji_safe_with_empty_emoji(self, mock_bot_db):
|
||||
"""Тест безопасного получения эмодзи пользователя с пустым эмодзи"""
|
||||
mock_bot_db.check_emoji_for_user.return_value = ""
|
||||
from unittest.mock import AsyncMock
|
||||
mock_bot_db.get_user_emoji = AsyncMock(return_value="")
|
||||
|
||||
result = get_user_emoji_safe(mock_bot_db, 123)
|
||||
result = await get_user_emoji_safe(mock_bot_db, 123)
|
||||
|
||||
assert result == "😊"
|
||||
mock_bot_db.check_emoji_for_user.assert_called_once_with(123)
|
||||
mock_bot_db.get_user_emoji.assert_called_once_with(123)
|
||||
|
||||
def test_get_user_emoji_safe_with_error(self, mock_bot_db):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_user_emoji_safe_with_error(self, mock_bot_db):
|
||||
"""Тест безопасного получения эмодзи пользователя при ошибке"""
|
||||
mock_bot_db.check_emoji_for_user.return_value = "Ошибка"
|
||||
from unittest.mock import AsyncMock
|
||||
mock_bot_db.get_user_emoji = AsyncMock(return_value="Ошибка")
|
||||
|
||||
result = get_user_emoji_safe(mock_bot_db, 123)
|
||||
result = await get_user_emoji_safe(mock_bot_db, 123)
|
||||
|
||||
assert result == "Ошибка"
|
||||
mock_bot_db.check_emoji_for_user.assert_called_once_with(123)
|
||||
mock_bot_db.get_user_emoji.assert_called_once_with(123)
|
||||
|
||||
def test_format_time_ago_minutes(self):
|
||||
"""Тест форматирования времени в минутах"""
|
||||
|
||||
Reference in New Issue
Block a user