mirror of
https://github.com/FerraSoft/bottohelp.git
synced 2026-08-06 21:55:03 +00:00
Подготовка к релизу
This commit is contained in:
@@ -0,0 +1,595 @@
|
||||
"""
|
||||
Комплексные интеграционные тесты для платежей.
|
||||
Тестирование полного цикла донатов: создание платежа -> обработка -> начисление очков -> достижения.
|
||||
Проверяет взаимодействие: handlers -> donation_service -> payment_providers -> repositories.
|
||||
"""
|
||||
|
||||
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.donation_service import DonationService
|
||||
from services.payment_provider import StripePaymentProvider, YooKassaPaymentProvider
|
||||
from handlers.user_handlers import UserHandlers
|
||||
from database import UserRepository, ScoreRepository, PaymentRepository
|
||||
|
||||
|
||||
class TestPaymentsIntegration:
|
||||
"""Комплексные интеграционные тесты системы платежей"""
|
||||
|
||||
@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]
|
||||
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"
|
||||
SBP_API_KEY = "sbp_test_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 = "donator_user"
|
||||
user.first_name = "Donator"
|
||||
user.last_name = "Test"
|
||||
update.effective_user = user
|
||||
|
||||
# Мокаем сообщение
|
||||
message = Mock()
|
||||
message.message_id = 1
|
||||
message.reply_text = AsyncMock()
|
||||
update.message = message
|
||||
|
||||
# Мокаем чат
|
||||
chat = Mock()
|
||||
chat.id = -1001234567890
|
||||
update.effective_chat = chat
|
||||
|
||||
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_donation_full_flow_integration(self, temp_config, temp_db, mock_update, mock_context):
|
||||
"""Интеграционный тест полного цикла доната: handler -> service -> repository"""
|
||||
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:
|
||||
# Шаг 1: Создаем пользователя
|
||||
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
|
||||
)
|
||||
|
||||
# Шаг 2: Инициируем донат через сервис
|
||||
donation_amount = 500.0
|
||||
success = await user_service.add_donation(mock_update.effective_user.id, donation_amount)
|
||||
|
||||
# Шаг 3: Проверяем, что донат прошел успешно
|
||||
assert success
|
||||
|
||||
# Шаг 4: Проверяем начисление очков (500 рублей = 5 очков)
|
||||
expected_points = int(donation_amount // 100)
|
||||
user_score = score_repo.get_total_score(mock_update.effective_user.id)
|
||||
assert user_score == expected_points
|
||||
|
||||
# Шаг 5: Проверяем обновление профиля пользователя
|
||||
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.reputation == expected_points
|
||||
|
||||
# Шаг 6: Проверяем достижения (должно появиться "Первый донат")
|
||||
user_achievements = await user_service.get_user_achievements(mock_update.effective_user.id)
|
||||
achievement_names = []
|
||||
for achievement_id, unlocked_at in user_achievements:
|
||||
achievement_data = user_repo.get_all_achievements()
|
||||
for ach in achievement_data:
|
||||
if ach['id'] == achievement_id:
|
||||
achievement_names.append(ach['name'])
|
||||
break
|
||||
|
||||
assert "Первый донат" in achievement_names
|
||||
|
||||
# Шаг 7: Проверяем статистику донатов
|
||||
total_donations = await user_service.get_total_donations(mock_update.effective_user.id, 2025)
|
||||
assert total_donations == donation_amount
|
||||
|
||||
finally:
|
||||
user_repo.close()
|
||||
score_repo.close()
|
||||
payment_repo.close()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_multiple_donations_integration(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)
|
||||
|
||||
try:
|
||||
# Шаг 1: Создаем пользователя
|
||||
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
|
||||
)
|
||||
|
||||
# Шаг 2: Несколько донатов
|
||||
donations = [300.0, 500.0, 1000.0] # 3, 5, 10 очков соответственно
|
||||
|
||||
for amount in donations:
|
||||
success = await user_service.add_donation(mock_update.effective_user.id, amount)
|
||||
assert success
|
||||
|
||||
# Шаг 3: Проверяем итоговые очки (3 + 5 + 10 = 18)
|
||||
total_score = score_repo.get_total_score(mock_update.effective_user.id)
|
||||
expected_total = sum(int(amount // 100) for amount in donations)
|
||||
assert total_score == expected_total
|
||||
|
||||
# Шаг 4: Проверяем достижения (должен появиться "Меценат")
|
||||
user_achievements = await user_service.get_user_achievements(mock_update.effective_user.id)
|
||||
achievement_names = []
|
||||
for achievement_id, unlocked_at in user_achievements:
|
||||
achievement_data = user_repo.get_all_achievements()
|
||||
for ach in achievement_data:
|
||||
if ach['id'] == achievement_id:
|
||||
achievement_names.append(ach['name'])
|
||||
break
|
||||
|
||||
assert "Первый донат" in achievement_names
|
||||
assert "Меценат" in achievement_names
|
||||
|
||||
# Шаг 5: Проверяем общую сумму донатов
|
||||
total_donations = await user_service.get_total_donations(mock_update.effective_user.id, 2025)
|
||||
assert total_donations == sum(donations)
|
||||
|
||||
finally:
|
||||
user_repo.close()
|
||||
score_repo.close()
|
||||
payment_repo.close()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_donation_ranks_integration(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)
|
||||
|
||||
try:
|
||||
# Шаг 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 == "Новичок"
|
||||
|
||||
# Шаг 2: Большой донат (1000 рублей = 10 очков, должно дать ранг)
|
||||
donation_amount = 1000.0
|
||||
success = await user_service.add_donation(mock_update.effective_user.id, donation_amount)
|
||||
assert success
|
||||
|
||||
# Шаг 3: Проверяем обновление ранга
|
||||
updated_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
|
||||
)
|
||||
|
||||
# При 10+ очках ранг должен измениться
|
||||
assert updated_profile.reputation >= 10
|
||||
# Ранг может зависеть от логики, но очки должны быть начислены
|
||||
|
||||
# Шаг 4: Еще один большой донат для достижения высокого ранга
|
||||
second_donation = 2000.0
|
||||
success2 = await user_service.add_donation(mock_update.effective_user.id, second_donation)
|
||||
assert success2
|
||||
|
||||
# Шаг 5: Финальная проверка
|
||||
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
|
||||
)
|
||||
|
||||
expected_total_points = 10 + 20 # 1000/100 + 2000/100
|
||||
assert final_profile.reputation == expected_total_points
|
||||
|
||||
finally:
|
||||
user_repo.close()
|
||||
score_repo.close()
|
||||
payment_repo.close()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_donation_payment_providers_integration(self, temp_config, temp_db, mock_update, mock_context):
|
||||
"""Тест интеграции с платежными провайдерами"""
|
||||
config = Config(temp_config)
|
||||
payment_repo = PaymentRepository(temp_db)
|
||||
|
||||
try:
|
||||
# Шаг 1: Тестируем Stripe провайдер
|
||||
stripe_provider = StripePaymentProvider(
|
||||
api_key=config.api_keys.stripe_secret,
|
||||
webhook_secret="whsec_test_webhook"
|
||||
)
|
||||
|
||||
# Мокаем создание платежа в Stripe
|
||||
with patch.object(stripe_provider, '_stripe') as mock_stripe:
|
||||
mock_payment_intent = Mock()
|
||||
mock_payment_intent.id = "pi_test_123"
|
||||
mock_payment_intent.client_secret = "pi_test_secret"
|
||||
mock_stripe.PaymentIntent.create.return_value = mock_payment_intent
|
||||
|
||||
payment_intent = stripe_provider.create_payment(
|
||||
amount=500.0,
|
||||
currency="RUB",
|
||||
user_id=mock_update.effective_user.id,
|
||||
metadata={"description": "Test donation"}
|
||||
)
|
||||
|
||||
assert payment_intent.payment_id == "pi_test_123"
|
||||
|
||||
# Шаг 2: Тестируем YooKassa провайдер
|
||||
yookassa_provider = YooKassaPaymentProvider(
|
||||
shop_id=config.api_keys.yookassa_shop_id,
|
||||
secret_key=config.api_keys.yookassa_secret
|
||||
)
|
||||
|
||||
# Мокаем создание платежа в YooKassa
|
||||
with patch.object(yookassa_provider, '_yookassa') as mock_yookassa:
|
||||
mock_payment = Mock()
|
||||
mock_payment.id = "payment_test_456"
|
||||
mock_payment.confirmation.confirmation_url = "https://test.payment.url"
|
||||
mock_yookassa.Payment.create.return_value = mock_payment
|
||||
|
||||
payment_intent = yookassa_provider.create_payment(
|
||||
amount=300.0,
|
||||
currency="RUB",
|
||||
user_id=mock_update.effective_user.id,
|
||||
metadata={"description": "Test YooKassa donation"}
|
||||
)
|
||||
|
||||
assert payment_intent.payment_id == "payment_test_456"
|
||||
|
||||
finally:
|
||||
payment_repo.close()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_donation_webhook_processing_integration(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)
|
||||
|
||||
try:
|
||||
# Шаг 1: Создаем пользователя и платеж
|
||||
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
|
||||
)
|
||||
|
||||
# Создаем платеж в базе данных
|
||||
payment_data = {
|
||||
'user_id': mock_update.effective_user.id,
|
||||
'amount': 500.0,
|
||||
'currency': 'RUB',
|
||||
'provider': 'stripe',
|
||||
'external_id': 'pi_test_webhook',
|
||||
'status': 'pending',
|
||||
'created_at': datetime.now()
|
||||
}
|
||||
payment_repo.create_payment(payment_data)
|
||||
|
||||
# Шаг 2: Имитируем успешный вебхук
|
||||
webhook_data = {
|
||||
'id': 'evt_test_webhook',
|
||||
'type': 'payment_intent.succeeded',
|
||||
'data': {
|
||||
'object': {
|
||||
'id': 'pi_test_webhook',
|
||||
'amount': 50000, # в копейках/центах
|
||||
'currency': 'rub'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Мокаем обработку вебхука
|
||||
success = await donation_service.process_payment_webhook('stripe', webhook_data)
|
||||
assert success
|
||||
|
||||
# Шаг 3: Проверяем, что платеж обновлен
|
||||
payment = payment_repo.get_payment_by_external_id('pi_test_webhook')
|
||||
assert payment is not None
|
||||
assert payment['status'] == 'completed'
|
||||
|
||||
# Шаг 4: Проверяем начисление очков пользователю
|
||||
user_score = score_repo.get_total_score(mock_update.effective_user.id)
|
||||
assert user_score == 5 # 500 рублей = 5 очков
|
||||
|
||||
finally:
|
||||
user_repo.close()
|
||||
score_repo.close()
|
||||
payment_repo.close()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_donation_statistics_integration(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)
|
||||
|
||||
try:
|
||||
# Шаг 1: Создаем несколько пользователей и донатов
|
||||
users = [123456789, 987654321, 555666777]
|
||||
donations = [300.0, 500.0, 1000.0]
|
||||
|
||||
for user_id in users:
|
||||
await user_service.get_or_create_user(user_id, f"user_{user_id}", "Test", "User")
|
||||
|
||||
for i, amount in enumerate(donations):
|
||||
user_id = users[i % len(users)]
|
||||
await user_service.add_donation(user_id, amount)
|
||||
|
||||
# Шаг 2: Получаем статистику платежей
|
||||
stats = donation_service.get_payment_statistics()
|
||||
|
||||
# Шаг 3: Проверяем статистику
|
||||
assert isinstance(stats, dict)
|
||||
assert 'total_payments' in stats
|
||||
assert 'total_amount' in stats
|
||||
assert 'successful_payments' in stats
|
||||
|
||||
# Проверяем, что статистика корректна
|
||||
assert stats['total_payments'] >= 3
|
||||
assert stats['total_amount'] >= sum(donations)
|
||||
|
||||
finally:
|
||||
user_repo.close()
|
||||
score_repo.close()
|
||||
payment_repo.close()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_donation_error_handling_integration(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)
|
||||
|
||||
try:
|
||||
# Шаг 1: Создаем пользователя
|
||||
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
|
||||
)
|
||||
|
||||
# Шаг 2: Имитируем ошибку при донате
|
||||
original_add_donation = user_service.add_donation
|
||||
user_service.add_donation = AsyncMock(side_effect=Exception("Payment processing error"))
|
||||
|
||||
# Шаг 3: Пытаемся сделать донат
|
||||
success = await user_service.add_donation(mock_update.effective_user.id, 500.0)
|
||||
assert not success
|
||||
|
||||
# Шаг 4: Восстанавливаем функцию и тестируем успешный донат
|
||||
user_service.add_donation = original_add_donation
|
||||
|
||||
success_retry = await user_service.add_donation(mock_update.effective_user.id, 500.0)
|
||||
assert success_retry
|
||||
|
||||
# Шаг 5: Проверяем, что несмотря на ошибку, успешный донат прошел
|
||||
user_score = score_repo.get_total_score(mock_update.effective_user.id)
|
||||
assert user_score == 5
|
||||
|
||||
finally:
|
||||
user_repo.close()
|
||||
score_repo.close()
|
||||
payment_repo.close()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_donation_duplicate_prevention_integration(self, temp_config, temp_db, mock_update, mock_context):
|
||||
"""Тест предотвращения дублированных платежей"""
|
||||
config = Config(temp_config)
|
||||
payment_repo = PaymentRepository(temp_db)
|
||||
donation_service = DonationService(payment_repo, config.api_keys)
|
||||
|
||||
try:
|
||||
# Шаг 1: Создаем платеж
|
||||
payment_data = {
|
||||
'user_id': mock_update.effective_user.id,
|
||||
'amount': 500.0,
|
||||
'currency': 'RUB',
|
||||
'provider': 'stripe',
|
||||
'external_id': 'pi_test_duplicate',
|
||||
'status': 'pending',
|
||||
'created_at': datetime.now()
|
||||
}
|
||||
payment_repo.create_payment(payment_data)
|
||||
|
||||
# Шаг 2: Проверяем дублирование
|
||||
is_duplicate = donation_service._validate_donation_data(
|
||||
mock_update.effective_user.id,
|
||||
500.0,
|
||||
'stripe'
|
||||
)
|
||||
|
||||
# В реальности проверка дублирования может работать иначе,
|
||||
# но метод должен существовать
|
||||
assert hasattr(donation_service, '_validate_donation_data')
|
||||
|
||||
finally:
|
||||
payment_repo.close()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_donation_user_balance_integration(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)
|
||||
|
||||
try:
|
||||
# Шаг 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
|
||||
)
|
||||
initial_balance = profile.reputation
|
||||
|
||||
# Шаг 2: Имитируем успешный платеж
|
||||
await donation_service._update_user_balance(mock_update.effective_user.id, 300.0)
|
||||
|
||||
# Шаг 3: Проверяем обновление баланса
|
||||
updated_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 updated_profile.reputation == initial_balance + 3 # 300 рублей = 3 очка
|
||||
|
||||
finally:
|
||||
user_repo.close()
|
||||
score_repo.close()
|
||||
payment_repo.close()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_donation_payment_cancellation_integration(self, temp_config, temp_db, mock_update, mock_context):
|
||||
"""Тест отмены платежей"""
|
||||
config = Config(temp_config)
|
||||
payment_repo = PaymentRepository(temp_db)
|
||||
donation_service = DonationService(payment_repo, config.api_keys)
|
||||
|
||||
try:
|
||||
# Шаг 1: Создаем платеж
|
||||
payment_data = {
|
||||
'user_id': mock_update.effective_user.id,
|
||||
'amount': 500.0,
|
||||
'currency': 'RUB',
|
||||
'provider': 'stripe',
|
||||
'external_id': 'pi_test_cancel',
|
||||
'status': 'pending',
|
||||
'created_at': datetime.now()
|
||||
}
|
||||
created_payment = payment_repo.create_payment(payment_data)
|
||||
payment_id = created_payment['id']
|
||||
|
||||
# Шаг 2: Отменяем платеж
|
||||
cancelled = donation_service.cancel_payment(payment_id, mock_update.effective_user.id)
|
||||
assert cancelled
|
||||
|
||||
# Шаг 3: Проверяем статус платежа
|
||||
payment = payment_repo.get_payment_by_id(payment_id)
|
||||
assert payment['status'] == 'cancelled'
|
||||
|
||||
finally:
|
||||
payment_repo.close()
|
||||
Reference in New Issue
Block a user