mirror of
https://github.com/FerraSoft/bottohelp.git
synced 2026-08-06 21:55:03 +00:00
648 lines
29 KiB
Python
648 lines
29 KiB
Python
"""
|
|
Комплексные интеграционные тесты полного пользовательского сценария.
|
|
Тестирование полной цепочки взаимодействия пользователя с ботом:
|
|
от /start -> игры -> модерация -> донаты -> достижения.
|
|
Проверяет взаимодействие всех слоев архитектуры в реальном сценарии использования.
|
|
"""
|
|
|
|
import pytest
|
|
import tempfile
|
|
import os
|
|
from unittest.mock import Mock, AsyncMock, patch
|
|
from datetime import datetime
|
|
|
|
# Добавляем корневую директорию в путь
|
|
import sys
|
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
|
|
from core.config import Config
|
|
from services.user_service import UserService
|
|
from services.game_service import GameService
|
|
from services.moderation_service import ModerationService
|
|
from services.donation_service import DonationService
|
|
from handlers.user_handlers import UserHandlers
|
|
from handlers.game_handlers import GameHandlers
|
|
from handlers.moderation_handlers import ModerationHandlers
|
|
from database import UserRepository, ScoreRepository, PaymentRepository
|
|
|
|
|
|
class TestFullUserScenarioIntegration:
|
|
"""Комплексные интеграционные тесты полного сценария использования бота"""
|
|
|
|
@pytest.fixture
|
|
def temp_config(self):
|
|
"""Временный файл конфигурации для интеграционных тестов"""
|
|
with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f:
|
|
f.write("""
|
|
BOT_TOKEN = "123456789:integration_test_token"
|
|
ADMIN_IDS = [123456789, 987654321]
|
|
MODERATOR_IDS = [555666777]
|
|
OPENWEATHER_API_KEY = "test_key"
|
|
NEWS_API_KEY = "test_key"
|
|
OPENAI_API_KEY = "test_key"
|
|
STRIPE_SECRET_KEY = "sk_test_123456789"
|
|
YOOKASSA_SHOP_ID = "123456"
|
|
YOOKASSA_SECRET_KEY = "test_secret_key"
|
|
""")
|
|
config_path = f.name
|
|
|
|
yield config_path
|
|
|
|
# Очистка
|
|
if os.path.exists(config_path):
|
|
os.unlink(config_path)
|
|
|
|
@pytest.fixture
|
|
def temp_db(self):
|
|
"""Временная база данных для тестов с полной инициализацией"""
|
|
from database.models import DatabaseSchema
|
|
|
|
with tempfile.NamedTemporaryFile(suffix='.db', delete=False) as f:
|
|
db_path = f.name
|
|
|
|
# Инициализируем базу данных
|
|
repo = UserRepository(db_path)
|
|
try:
|
|
# Создаем все таблицы
|
|
for table_sql in DatabaseSchema.get_create_tables_sql():
|
|
repo._execute_query(table_sql)
|
|
|
|
# Создаем стандартные достижения
|
|
repo.initialize_achievements()
|
|
|
|
finally:
|
|
repo.close()
|
|
|
|
yield db_path
|
|
|
|
# Очистка
|
|
if os.path.exists(db_path):
|
|
os.unlink(db_path)
|
|
|
|
@pytest.fixture
|
|
def mock_update(self):
|
|
"""Мокированный объект Update для команд"""
|
|
update = Mock()
|
|
|
|
# Мокаем пользователя
|
|
user = Mock()
|
|
user.id = 123456789
|
|
user.username = "test_user"
|
|
user.first_name = "Test"
|
|
user.last_name = "User"
|
|
update.effective_user = user
|
|
|
|
# Мокаем сообщение
|
|
message = Mock()
|
|
message.message_id = 1
|
|
message.reply_text = AsyncMock()
|
|
message.edit_text = AsyncMock()
|
|
update.message = message
|
|
|
|
# Мокаем чат
|
|
chat = Mock()
|
|
chat.id = -1001234567890
|
|
update.effective_chat = chat
|
|
|
|
# Мокаем callback_query
|
|
callback_query = Mock()
|
|
callback_query.id = "test_callback_id"
|
|
callback_query.data = "test_data"
|
|
callback_query.message = message
|
|
callback_query.answer = AsyncMock()
|
|
update.callback_query = callback_query
|
|
|
|
return update
|
|
|
|
@pytest.fixture
|
|
def mock_context(self):
|
|
"""Мокированный контекст бота"""
|
|
context = Mock()
|
|
context.args = []
|
|
|
|
# Мокаем приложение
|
|
app = Mock()
|
|
app._date_time = datetime.now()
|
|
context._application = app
|
|
|
|
# Мокаем бота
|
|
bot = AsyncMock()
|
|
context.bot = bot
|
|
|
|
context.user_data = {}
|
|
|
|
return context
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_complete_new_user_journey(self, temp_config, temp_db, mock_update, mock_context):
|
|
"""Тест полного пути нового пользователя: от первого контакта до активного использования"""
|
|
config = Config(temp_config)
|
|
user_repo = UserRepository(temp_db)
|
|
score_repo = ScoreRepository(temp_db)
|
|
payment_repo = PaymentRepository(temp_db)
|
|
|
|
# Инициализируем все сервисы
|
|
user_service = UserService(user_repo, score_repo)
|
|
game_service = GameService(user_repo, score_repo)
|
|
moderation_service = ModerationService(user_repo, score_repo)
|
|
donation_service = DonationService(payment_repo, config.api_keys)
|
|
|
|
# Инициализируем все хендлеры
|
|
user_handlers = UserHandlers(config, user_service)
|
|
game_handlers = GameHandlers(config, config, game_service, config)
|
|
moderation_handlers = ModerationHandlers(config, config, user_service, moderation_service)
|
|
|
|
try:
|
|
# === ЭТАП 1: Первый контакт - /start ===
|
|
print("Этап 1: Регистрация нового пользователя")
|
|
await user_handlers.handle_start(mock_update, mock_context)
|
|
|
|
# Проверяем создание пользователя
|
|
profile = await user_service.get_or_create_user(
|
|
mock_update.effective_user.id,
|
|
mock_update.effective_user.username,
|
|
mock_update.effective_user.first_name,
|
|
mock_update.effective_user.last_name
|
|
)
|
|
assert profile.user_id == mock_update.effective_user.id
|
|
assert profile.rank == "Новичок"
|
|
assert profile.reputation == 0
|
|
|
|
# === ЭТАП 2: Изучение команд - /help ===
|
|
print("Этап 2: Изучение команд")
|
|
mock_update.message.reply_text.reset_mock()
|
|
await user_handlers.handle_help(mock_update, mock_context)
|
|
|
|
help_response = mock_update.message.reply_text.call_args[0][0]
|
|
assert "Помощь по командам" in help_response or "📋" in help_response
|
|
|
|
# === ЭТАП 3: Проверка ранга - /rank ===
|
|
print("Этап 3: Проверка ранга")
|
|
mock_update.message.reply_text.reset_mock()
|
|
await user_handlers.handle_rank(mock_update, mock_context)
|
|
|
|
rank_response = mock_update.message.reply_text.call_args[0][0]
|
|
assert "🏆" in rank_response or "Ранг" in rank_response
|
|
|
|
# === ЭТАП 4: Игра - камень-ножницы-бумага ===
|
|
print("Этап 4: Первая игра")
|
|
mock_update.message.reply_text.reset_mock()
|
|
await game_handlers._handle_play_game(mock_update, mock_context)
|
|
|
|
# Выбираем камень
|
|
mock_context.args = ['rock']
|
|
await game_handlers.handle_rps_choice(mock_update, mock_context)
|
|
|
|
# Проверяем начисление очков за игру
|
|
game_profile = await user_service.get_or_create_user(
|
|
mock_update.effective_user.id,
|
|
mock_update.effective_user.username,
|
|
mock_update.effective_user.first_name,
|
|
mock_update.effective_user.last_name
|
|
)
|
|
assert game_profile.reputation >= 0 # Очки могли начислиться
|
|
|
|
# === ЭТАП 5: Крестики-нолики ===
|
|
print("Этап 5: Крестики-нолики")
|
|
mock_update.message.reply_text.reset_mock()
|
|
await game_handlers._handle_tic_tac_toe(mock_update, mock_context)
|
|
|
|
# Делаем ход
|
|
mock_context.args = ['4']
|
|
await game_handlers.handle_tictactoe_move(mock_update, mock_context)
|
|
|
|
# === ЭТАП 6: Викторина ===
|
|
print("Этап 6: Викторина")
|
|
mock_update.message.reply_text.reset_mock()
|
|
await game_handlers._handle_quiz(mock_update, mock_context)
|
|
|
|
# Отвечаем на вопрос
|
|
mock_context.args = ['0']
|
|
await game_handlers.handle_quiz_answer(mock_update, mock_context)
|
|
|
|
# === ЭТАП 7: Первый донат ===
|
|
print("Этап 7: Первый донат")
|
|
donation_amount = 500.0
|
|
success = await user_service.add_donation(mock_update.effective_user.id, donation_amount)
|
|
assert success
|
|
|
|
# Проверяем достижения
|
|
achievements = await user_service.get_user_achievements(mock_update.effective_user.id)
|
|
achievement_names = []
|
|
for ach_id, unlocked_at in achievements:
|
|
ach_data = user_repo.get_all_achievements()
|
|
for ach in ach_data:
|
|
if ach['id'] == ach_id:
|
|
achievement_names.append(ach['name'])
|
|
break
|
|
|
|
assert "Первый донат" in achievement_names
|
|
|
|
# Проверяем повышение ранга
|
|
donator_profile = await user_service.get_or_create_user(
|
|
mock_update.effective_user.id,
|
|
mock_update.effective_user.username,
|
|
mock_update.effective_user.first_name,
|
|
mock_update.effective_user.last_name
|
|
)
|
|
assert donator_profile.reputation >= 5 # Минимум 5 очков от доната
|
|
|
|
# === ЭТАП 8: Проверка лидерборда ===
|
|
print("Этап 8: Лидерборд")
|
|
mock_update.message.reply_text.reset_mock()
|
|
await user_handlers.handle_leaderboard(mock_update, mock_context)
|
|
|
|
leaderboard_response = mock_update.message.reply_text.call_args[0][0]
|
|
assert "🥇" in leaderboard_response or "Топ" in leaderboard_response
|
|
|
|
# === ЭТАП 9: Финальная проверка профиля ===
|
|
print("Этап 9: Финальный профиль")
|
|
final_profile = await user_service.get_or_create_user(
|
|
mock_update.effective_user.id,
|
|
mock_update.effective_user.username,
|
|
mock_update.effective_user.first_name,
|
|
mock_update.effective_user.last_name
|
|
)
|
|
|
|
# Проверяем прогресс пользователя
|
|
assert final_profile.reputation > 0
|
|
assert final_profile.user_id == mock_update.effective_user.id
|
|
assert final_profile.username == mock_update.effective_user.username
|
|
|
|
print(f"✅ Пользователь прошел полный путь: {final_profile.reputation} очков, ранг: {final_profile.rank}")
|
|
|
|
finally:
|
|
user_repo.close()
|
|
score_repo.close()
|
|
payment_repo.close()
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_user_progression_scenario(self, temp_config, temp_db, mock_update, mock_context):
|
|
"""Тест сценария прогрессии пользователя: от новичка до опытного игрока"""
|
|
config = Config(temp_config)
|
|
user_repo = UserRepository(temp_db)
|
|
score_repo = ScoreRepository(temp_db)
|
|
payment_repo = PaymentRepository(temp_db)
|
|
|
|
user_service = UserService(user_repo, score_repo)
|
|
game_service = GameService(user_repo, score_repo)
|
|
donation_service = DonationService(payment_repo, config.api_keys)
|
|
|
|
try:
|
|
# === ФАЗА 1: Новичок ===
|
|
print("Фаза 1: Новичок")
|
|
profile = await user_service.get_or_create_user(
|
|
mock_update.effective_user.id,
|
|
mock_update.effective_user.username,
|
|
mock_update.effective_user.first_name,
|
|
mock_update.effective_user.last_name
|
|
)
|
|
assert profile.rank == "Новичок"
|
|
initial_score = profile.reputation
|
|
|
|
# Несколько игр для накопления очков
|
|
for _ in range(5):
|
|
await score_repo.update_score(mock_update.effective_user.id, 2) # +2 за каждую игру
|
|
|
|
# === ФАЗА 2: Первый донат ===
|
|
print("Фаза 2: Первый донат")
|
|
await user_service.add_donation(mock_update.effective_user.id, 300.0) # +3 очка
|
|
|
|
# Проверяем достижения
|
|
achievements = await user_service.get_user_achievements(mock_update.effective_user.id)
|
|
achievement_names = [user_repo.get_all_achievements()[i]['name']
|
|
for i, _ in achievements if i < len(user_repo.get_all_achievements())]
|
|
|
|
# === ФАЗА 3: Активный игрок ===
|
|
print("Фаза 3: Активный игрок")
|
|
# Еще игры и донаты
|
|
for _ in range(10):
|
|
await score_repo.update_score(mock_update.effective_user.id, 1)
|
|
|
|
await user_service.add_donation(mock_update.effective_user.id, 1000.0) # +10 очков
|
|
|
|
# === ФАЗА 4: Опытный пользователь ===
|
|
print("Фаза 4: Опытный пользователь")
|
|
final_profile = await user_service.get_or_create_user(
|
|
mock_update.effective_user.id,
|
|
mock_update.effective_user.username,
|
|
mock_update.effective_user.first_name,
|
|
mock_update.effective_user.last_name
|
|
)
|
|
|
|
# Проверяем значительный прогресс
|
|
total_score = final_profile.reputation
|
|
assert total_score > initial_score + 20 # Минимум 20+ очков прогресса
|
|
|
|
# Проверяем достижения
|
|
final_achievements = await user_service.get_user_achievements(mock_update.effective_user.id)
|
|
assert len(final_achievements) >= 2 # Минимум 2 достижения
|
|
|
|
print(f"✅ Прогрессия завершена: {total_score} очков, {len(final_achievements)} достижений")
|
|
|
|
finally:
|
|
user_repo.close()
|
|
score_repo.close()
|
|
payment_repo.close()
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_user_interaction_with_moderation(self, temp_config, temp_db, mock_update, mock_context):
|
|
"""Тест сценария взаимодействия с системой модерации"""
|
|
config = Config(temp_config)
|
|
user_repo = UserRepository(temp_db)
|
|
score_repo = ScoreRepository(temp_db)
|
|
|
|
user_service = UserService(user_repo, score_repo)
|
|
moderation_service = ModerationService(user_repo, score_repo)
|
|
user_handlers = UserHandlers(config, user_service)
|
|
moderation_handlers = ModerationHandlers(config, config, user_service, moderation_service)
|
|
|
|
try:
|
|
# Создаем обычного пользователя
|
|
regular_user_id = 999999999
|
|
await user_service.get_or_create_user(regular_user_id, "regular", "Regular", "User")
|
|
|
|
# Имитируем нарушение (предупреждение)
|
|
mock_context.args = [str(regular_user_id), "Тестовое нарушение"]
|
|
await moderation_handlers._handle_warn(mock_update, mock_context, mock_context.args)
|
|
|
|
# Проверяем, что предупреждение записано
|
|
user_history = await moderation_service.get_user_moderation_history(regular_user_id)
|
|
assert len(user_history) >= 1
|
|
|
|
# Пользователь должен иметь предупреждения
|
|
regular_profile = await user_service.get_or_create_user(regular_user_id, "regular", "Regular", "User")
|
|
assert regular_profile.warnings >= 1
|
|
|
|
# При повторных нарушениях - мут
|
|
await moderation_service.warn_user(regular_user_id, "Повторное нарушение", mock_update.effective_user.id)
|
|
await moderation_service.warn_user(regular_user_id, "Еще одно нарушение", mock_update.effective_user.id)
|
|
|
|
# Проверяем эскалацию
|
|
is_muted = moderation_service.is_user_muted(regular_user_id)
|
|
# Логика эскалации может быть разной, но система должна реагировать
|
|
|
|
print("✅ Система модерации отработала корректно")
|
|
|
|
finally:
|
|
user_repo.close()
|
|
score_repo.close()
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_community_interaction_scenario(self, temp_config, temp_db, mock_update, mock_context):
|
|
"""Тест сценария взаимодействия в сообществе"""
|
|
config = Config(temp_config)
|
|
user_repo = UserRepository(temp_db)
|
|
score_repo = ScoreRepository(temp_db)
|
|
payment_repo = PaymentRepository(temp_db)
|
|
|
|
user_service = UserService(user_repo, score_repo)
|
|
donation_service = DonationService(payment_repo, config.api_keys)
|
|
user_handlers = UserHandlers(config, user_service)
|
|
|
|
try:
|
|
# Создаем несколько пользователей сообщества
|
|
users_data = [
|
|
(111111111, "alice", "Alice", "Smith"),
|
|
(222222222, "bob", "Bob", "Johnson"),
|
|
(333333333, "charlie", "Charlie", "Brown"),
|
|
(mock_update.effective_user.id, mock_update.effective_user.username,
|
|
mock_update.effective_user.first_name, mock_update.effective_user.last_name)
|
|
]
|
|
|
|
# Регистрируем всех пользователей
|
|
for user_id, username, first_name, last_name in users_data:
|
|
await user_service.get_or_create_user(user_id, username, first_name, last_name)
|
|
|
|
# Каждый делает донат
|
|
await user_service.add_donation(user_id, 200.0) # +2 очка каждому
|
|
|
|
# Каждый играет в игры
|
|
await score_repo.update_score(user_id, 5) # +5 очков каждому
|
|
|
|
# Проверяем лидерборд
|
|
mock_update.message.reply_text.reset_mock()
|
|
await user_handlers.handle_leaderboard(mock_update, mock_context)
|
|
|
|
leaderboard_response = mock_update.message.reply_text.call_args[0][0]
|
|
|
|
# Проверяем, что все пользователи в лидерборде
|
|
top_users = await user_service.get_top_users(10)
|
|
assert len(top_users) >= 4
|
|
|
|
# Проверяем разнообразие рангов
|
|
ranks = set()
|
|
for user_id, username, first_name, score in top_users:
|
|
profile = await user_service.get_or_create_user(user_id, username, first_name, "Test")
|
|
ranks.add(profile.rank)
|
|
|
|
assert len(ranks) >= 1 # Минимум один ранг
|
|
|
|
# Проверяем достижения в сообществе
|
|
total_achievements = 0
|
|
for user_id, _, _, _ in top_users[:3]: # Проверяем топ-3
|
|
user_achievements = await user_service.get_user_achievements(user_id)
|
|
total_achievements += len(user_achievements)
|
|
|
|
assert total_achievements >= 3 # Минимум достижения в сообществе
|
|
|
|
print(f"✅ Сообщество активно: {len(top_users)} участников, {total_achievements} достижений")
|
|
|
|
finally:
|
|
user_repo.close()
|
|
score_repo.close()
|
|
payment_repo.close()
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_user_retention_scenario(self, temp_config, temp_db, mock_update, mock_context):
|
|
"""Тест сценария удержания пользователя: регулярная активность"""
|
|
config = Config(temp_config)
|
|
user_repo = UserRepository(temp_db)
|
|
score_repo = ScoreRepository(temp_db)
|
|
payment_repo = PaymentRepository(temp_db)
|
|
|
|
user_service = UserService(user_repo, score_repo)
|
|
game_service = GameService(user_repo, score_repo)
|
|
donation_service = DonationService(payment_repo, config.api_keys)
|
|
user_handlers = UserHandlers(config, user_service)
|
|
|
|
try:
|
|
# === НЕДЕЛЯ 1: Начало ===
|
|
print("Неделя 1: Регистрация и первые взаимодействия")
|
|
await user_handlers.handle_start(mock_update, mock_context)
|
|
|
|
# Ежедневные игры
|
|
for day in range(7):
|
|
await score_repo.update_score(mock_update.effective_user.id, 3) # 3 игры в день
|
|
|
|
week1_score = score_repo.get_total_score(mock_update.effective_user.id)
|
|
|
|
# === НЕДЕЛЯ 2: Активность ===
|
|
print("Неделя 2: Рост активности")
|
|
# Донат
|
|
await user_service.add_donation(mock_update.effective_user.id, 300.0)
|
|
|
|
# Больше игр
|
|
for day in range(7):
|
|
await score_repo.update_score(mock_update.effective_user.id, 5) # 5 игр в день
|
|
|
|
week2_score = score_repo.get_total_score(mock_update.effective_user.id)
|
|
|
|
# === НЕДЕЛЯ 3: Пик активности ===
|
|
print("Неделя 3: Пик активности")
|
|
# Еще один донат
|
|
await user_service.add_donation(mock_update.effective_user.id, 500.0)
|
|
|
|
# Максимальная активность
|
|
for day in range(7):
|
|
await score_repo.update_score(mock_update.effective_user.id, 8) # 8 игр в день
|
|
|
|
week3_score = score_repo.get_total_score(mock_update.effective_user.id)
|
|
|
|
# === ПРОВЕРКИ ===
|
|
# Прогресс должен расти
|
|
assert week2_score > week1_score
|
|
assert week3_score > week2_score
|
|
|
|
# Финальный профиль
|
|
final_profile = await user_service.get_or_create_user(
|
|
mock_update.effective_user.id,
|
|
mock_update.effective_user.username,
|
|
mock_update.effective_user.first_name,
|
|
mock_update.effective_user.last_name
|
|
)
|
|
|
|
# Проверяем достижения
|
|
achievements = await user_service.get_user_achievements(mock_update.effective_user.id)
|
|
assert len(achievements) >= 2 # Минимум 2 достижения за 3 недели
|
|
|
|
# Проверяем ранг
|
|
assert final_profile.reputation >= 50 # Минимум 50 очков
|
|
|
|
# Проверяем статистику донатов
|
|
total_donations = await user_service.get_total_donations(mock_update.effective_user.id, 2025)
|
|
assert total_donations >= 800.0
|
|
|
|
print(f"✅ Удержание пользователя успешно: {final_profile.reputation} очков, ранг {final_profile.rank}")
|
|
|
|
finally:
|
|
user_repo.close()
|
|
score_repo.close()
|
|
payment_repo.close()
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_error_recovery_scenario(self, temp_config, temp_db, mock_update, mock_context):
|
|
"""Тест сценария восстановления после ошибок"""
|
|
config = Config(temp_config)
|
|
user_repo = UserRepository(temp_db)
|
|
score_repo = ScoreRepository(temp_db)
|
|
|
|
user_service = UserService(user_repo, score_repo)
|
|
user_handlers = UserHandlers(config, user_service)
|
|
|
|
try:
|
|
# Создаем пользователя
|
|
await user_handlers.handle_start(mock_update, mock_context)
|
|
|
|
# Имитируем ошибку в сервисе
|
|
original_get_or_create = user_service.get_or_create_user
|
|
user_service.get_or_create_user = AsyncMock(side_effect=Exception("Temporary service error"))
|
|
|
|
# Пытаемся выполнить команду (должна обработать ошибку)
|
|
await user_handlers.handle_rank(mock_update, mock_context)
|
|
|
|
# Восстанавливаем сервис
|
|
user_service.get_or_create_user = original_get_or_create
|
|
|
|
# Повторяем команду (теперь должна работать)
|
|
mock_update.message.reply_text.reset_mock()
|
|
await user_handlers.handle_rank(mock_update, mock_context)
|
|
|
|
# Проверяем, что команда выполнилась успешно после восстановления
|
|
assert mock_update.message.reply_text.called
|
|
rank_response = mock_update.message.reply_text.call_args[0][0]
|
|
assert "Ранг" in rank_response or "🏆" in rank_response
|
|
|
|
print("✅ Система корректно восстановилась после ошибки")
|
|
|
|
finally:
|
|
user_repo.close()
|
|
score_repo.close()
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_cross_feature_integration_scenario(self, temp_config, temp_db, mock_update, mock_context):
|
|
"""Тест сценария интеграции всех функций"""
|
|
config = Config(temp_config)
|
|
user_repo = UserRepository(temp_db)
|
|
score_repo = ScoreRepository(temp_db)
|
|
payment_repo = PaymentRepository(temp_db)
|
|
|
|
# Инициализируем все компоненты
|
|
user_service = UserService(user_repo, score_repo)
|
|
game_service = GameService(user_repo, score_repo)
|
|
moderation_service = ModerationService(user_repo, score_repo)
|
|
donation_service = DonationService(payment_repo, config.api_keys)
|
|
|
|
user_handlers = UserHandlers(config, user_service)
|
|
game_handlers = GameHandlers(config, config, game_service, config)
|
|
moderation_handlers = ModerationHandlers(config, config, user_service, moderation_service)
|
|
|
|
try:
|
|
# === КОМПЛЕКСНЫЙ СЦЕНАРИЙ ===
|
|
print("Запуск комплексного сценария интеграции всех функций")
|
|
|
|
# 1. Регистрация
|
|
await user_handlers.handle_start(mock_update, mock_context)
|
|
|
|
# 2. Игры
|
|
await game_handlers._handle_play_game(mock_update, mock_context)
|
|
mock_context.args = ['rock']
|
|
await game_handlers.handle_rps_choice(mock_update, mock_context)
|
|
|
|
# 3. Донаты
|
|
await user_service.add_donation(mock_update.effective_user.id, 1000.0)
|
|
|
|
# 4. Статистика модерации (создаем другого пользователя для теста)
|
|
target_user_id = 777777777
|
|
await user_service.get_or_create_user(target_user_id, "target", "Target", "User")
|
|
|
|
mock_context.args = [str(target_user_id), "Тест модерации"]
|
|
await moderation_handlers._handle_warn(mock_update, mock_context, mock_context.args)
|
|
|
|
# === ПРОВЕРКИ ИНТЕГРАЦИИ ===
|
|
|
|
# Проверяем, что все данные сохранены корректно
|
|
final_profile = await user_service.get_or_create_user(
|
|
mock_update.effective_user.id,
|
|
mock_update.effective_user.username,
|
|
mock_update.effective_user.first_name,
|
|
mock_update.effective_user.last_name
|
|
)
|
|
|
|
# Проверяем комплексные данные
|
|
assert final_profile.reputation >= 10 # Минимум от доната
|
|
assert final_profile.user_id == mock_update.effective_user.id
|
|
|
|
# Проверяем достижения
|
|
achievements = await user_service.get_user_achievements(mock_update.effective_user.id)
|
|
assert len(achievements) >= 1
|
|
|
|
# Проверяем игры
|
|
game_stats = game_service.get_game_statistics(mock_update.effective_user.id)
|
|
assert isinstance(game_stats, dict)
|
|
|
|
# Проверяем модерацию
|
|
moderation_stats = await moderation_service.get_moderation_stats()
|
|
assert isinstance(moderation_stats, dict)
|
|
assert moderation_stats['total_warnings'] >= 1
|
|
|
|
# Проверяем платежи
|
|
total_donations = await user_service.get_total_donations(mock_update.effective_user.id, 2025)
|
|
assert total_donations >= 1000.0
|
|
|
|
print("✅ Все компоненты успешно интегрированы и работают вместе")
|
|
|
|
finally:
|
|
user_repo.close()
|
|
score_repo.close()
|
|
payment_repo.close() |