Files
remnawave-bedolaga-telegram…/tests/services/test_yookassa_service_adapter.py
T
Fringg eb18994b7d fix: complete datetime.utcnow() → datetime.now(UTC) migration
- Migrate 660+ datetime.utcnow() across 153 files to datetime.now(UTC)
- Migrate 30+ datetime.now() without UTC to datetime.now(UTC)
- Convert all 170 DateTime columns to DateTime(timezone=True)
- Add migrate_datetime_to_timestamptz() in universal_migration with SET LOCAL timezone='UTC' safety
- Remove 70+ .replace(tzinfo=None) workarounds
- Fix utcfromtimestamp → fromtimestamp(..., tz=UTC)
- Fix fromtimestamp() without tz= (system_logs, backup_service, referral_diagnostics)
- Fix fromisoformat/isoparse to ensure aware output (platega, yookassa, wata, miniapp, nalogo)
- Fix strptime() to add .replace(tzinfo=UTC) (backup_service, referral_diagnostics)
- Fix datetime.combine() to include tzinfo=UTC (remnawave_sync, traffic_monitoring)
- Fix datetime.max/datetime.min sentinels with .replace(tzinfo=UTC)
- Rename panel_datetime_to_naive_utc → panel_datetime_to_utc
- Remove DTZ003 from ruff ignore list
2026-02-17 04:45:40 +03:00

182 lines
6.1 KiB
Python

"""Тесты низкоуровневого сервиса YooKassaService."""
from __future__ import annotations
import asyncio
import sys
from datetime import UTC, datetime
from pathlib import Path
from types import SimpleNamespace
import pytest
ROOT_DIR = Path(__file__).resolve().parents[2]
if str(ROOT_DIR) not in sys.path:
sys.path.insert(0, str(ROOT_DIR))
from yookassa import Configuration, Payment as YooKassaPayment # type: ignore
from app.config import settings
from app.services.yookassa_service import YooKassaService
@pytest.fixture
def anyio_backend() -> str:
return 'asyncio'
class DummyLoop:
async def run_in_executor(self, _executor, func):
return func()
def _prepare_config(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(settings, 'YOOKASSA_SHOP_ID', 'shop123', raising=False)
monkeypatch.setattr(settings, 'YOOKASSA_SECRET_KEY', 'secret123', raising=False)
monkeypatch.setattr(settings, 'YOOKASSA_RETURN_URL', 'https://example.com/return', raising=False)
monkeypatch.setattr(settings, 'YOOKASSA_VAT_CODE', 1, raising=False)
monkeypatch.setattr(settings, 'YOOKASSA_PAYMENT_MODE', 'full_payment', raising=False)
monkeypatch.setattr(settings, 'YOOKASSA_PAYMENT_SUBJECT', 'service', raising=False)
def test_init_without_credentials(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(settings, 'YOOKASSA_SHOP_ID', '', raising=False)
monkeypatch.setattr(settings, 'YOOKASSA_SECRET_KEY', '', raising=False)
service = YooKassaService()
assert service.configured is False
assert service.return_url == 'https://t.me/'
@pytest.mark.anyio('asyncio')
async def test_create_payment_success(monkeypatch: pytest.MonkeyPatch) -> None:
_prepare_config(monkeypatch)
monkeypatch.setattr(settings, 'YOOKASSA_DEFAULT_RECEIPT_EMAIL', None, raising=False)
monkeypatch.setattr(asyncio, 'get_running_loop', lambda: DummyLoop(), raising=False)
captured_config: dict[str, tuple[str, str]] = {}
def fake_configure(shop_id: str, secret_key: str) -> None:
captured_config['values'] = (shop_id, secret_key)
monkeypatch.setattr(Configuration, 'configure', fake_configure, raising=False)
response_obj = SimpleNamespace(
id='yk_1',
status='pending',
paid=False,
confirmation=SimpleNamespace(confirmation_url='https://yk/confirm'),
metadata={'meta': 'value'},
amount=SimpleNamespace(value='140.00', currency='RUB'),
refundable=True,
created_at=datetime(2024, 1, 1, 12, 0, 0, tzinfo=UTC),
description='Desc',
test=False,
)
monkeypatch.setattr(
YooKassaPayment,
'create',
staticmethod(lambda payload, key: response_obj),
raising=False,
)
service = YooKassaService()
monkeypatch.setattr(settings, 'YOOKASSA_DEFAULT_RECEIPT_EMAIL', 'fallback@example.com', raising=False)
result = await service.create_payment(
amount=140.0,
currency='RUB',
description='Пополнение',
metadata={'order': '1'},
receipt_email='user@example.com',
)
assert service.configured is True
assert captured_config['values'] == ('shop123', 'secret123')
assert result is not None
assert result['id'] == 'yk_1'
assert result['confirmation_url'] == 'https://yk/confirm'
assert result['amount_value'] == 140.0
assert result['status'] == 'pending'
@pytest.mark.anyio('asyncio')
async def test_create_payment_without_contacts(monkeypatch: pytest.MonkeyPatch) -> None:
_prepare_config(monkeypatch)
monkeypatch.setattr(settings, 'YOOKASSA_DEFAULT_RECEIPT_EMAIL', None, raising=False)
monkeypatch.setattr(Configuration, 'configure', lambda *args, **kwargs: None, raising=False)
monkeypatch.setattr(asyncio, 'get_running_loop', lambda: DummyLoop(), raising=False)
monkeypatch.setattr(
YooKassaPayment,
'create',
staticmethod(lambda payload, key: SimpleNamespace()),
raising=False,
)
service = YooKassaService()
result = await service.create_payment(
amount=10,
currency='RUB',
description='desc',
metadata={},
)
assert result is not None
assert result.get('error') is True
@pytest.mark.anyio('asyncio')
async def test_create_payment_returns_none_when_not_configured(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(settings, 'YOOKASSA_SHOP_ID', '', raising=False)
monkeypatch.setattr(settings, 'YOOKASSA_SECRET_KEY', '', raising=False)
service = YooKassaService()
result = await service.create_payment(
amount=10,
currency='RUB',
description='desc',
metadata={},
)
assert result is None
@pytest.mark.anyio('asyncio')
async def test_create_sbp_payment_success(monkeypatch: pytest.MonkeyPatch) -> None:
_prepare_config(monkeypatch)
monkeypatch.setattr(asyncio, 'get_running_loop', lambda: DummyLoop(), raising=False)
monkeypatch.setattr(Configuration, 'configure', lambda *args, **kwargs: None, raising=False)
monkeypatch.setattr(settings, 'YOOKASSA_DEFAULT_RECEIPT_EMAIL', 'fallback@example.com', raising=False)
response_obj = SimpleNamespace(
id='sbp_001',
status='pending',
paid=False,
confirmation=SimpleNamespace(confirmation_url='https://sbp/confirm'),
metadata={'meta': 'value'},
amount=SimpleNamespace(value='200.00', currency='RUB'),
refundable=False,
created_at=datetime(2024, 2, 1, 9, 0, 0, tzinfo=UTC),
description='SBP payment',
test=True,
)
monkeypatch.setattr(
YooKassaPayment,
'create',
staticmethod(lambda payload, key: response_obj),
raising=False,
)
service = YooKassaService()
result = await service.create_sbp_payment(
amount=200.0,
currency='rub',
description='Оплата',
metadata={'type': 'sbp'},
receipt_phone='+70000000000',
)
assert result is not None
assert result['id'] == 'sbp_001'
assert result['confirmation_url'] == 'https://sbp/confirm'
assert result['status'] == 'pending'