Files
remnawave-bedolaga-telegram…/tests/services/test_payment_service_cryptobot.py
c0mrade 9a2aea038a chore: add uv package manager and ruff linter configuration
- Add pyproject.toml with uv and ruff configuration
- Pin Python version to 3.13 via .python-version
- Add Makefile commands: lint, format, fix
- Apply ruff formatting to entire codebase
- Remove unused imports (base64 in yookassa/simple_subscription)
- Update .gitignore for new config files
2026-01-24 17:45:27 +03:00

154 lines
4.2 KiB
Python

"""Тесты сценариев CryptoBot в PaymentService."""
import sys
from datetime import datetime
from pathlib import Path
from typing import Any
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 app.config import settings
from app.database.crud import cryptobot as cryptobot_crud
from app.services.payment_service import PaymentService
@pytest.fixture
def anyio_backend() -> str:
return 'asyncio'
class DummySession:
def __init__(self) -> None:
self.added_objects: list[Any] = []
async def commit(self) -> None: # pragma: no cover
return None
def add(self, obj: Any) -> None: # pragma: no cover
self.added_objects.append(obj)
async def flush(self) -> None: # pragma: no cover
return None
class DummyLocalPayment:
def __init__(self, payment_id: int = 888) -> None:
self.id = payment_id
self.created_at = datetime(2024, 3, 1, 9, 0, 0)
class StubCryptoBotService:
def __init__(self, response: dict[str, Any] | None) -> None:
self.response = response
self.calls: list[dict[str, Any]] = []
async def create_invoice(self, **kwargs: Any) -> dict[str, Any] | None:
self.calls.append(kwargs)
return self.response
def _make_service(stub: StubCryptoBotService | None) -> PaymentService:
service = PaymentService.__new__(PaymentService) # type: ignore[call-arg]
service.bot = None
service.cryptobot_service = stub
service.mulenpay_service = None
service.pal24_service = None
service.yookassa_service = None
service.stars_service = None
return service
@pytest.mark.anyio('asyncio')
async def test_create_cryptobot_payment_success(monkeypatch: pytest.MonkeyPatch) -> None:
response = {
'invoice_id': 12345,
'bot_invoice_url': 'https://t.me/invoice',
'mini_app_invoice_url': 'https://mini.app/invoice',
'web_app_invoice_url': 'https://web.app/invoice',
}
stub = StubCryptoBotService(response)
service = _make_service(stub)
db = DummySession()
captured_args: dict[str, Any] = {}
async def fake_create_cryptobot_payment(**kwargs: Any) -> DummyLocalPayment:
captured_args.update(kwargs)
return DummyLocalPayment(payment_id=555)
monkeypatch.setattr(
cryptobot_crud,
'create_cryptobot_payment',
fake_create_cryptobot_payment,
raising=False,
)
monkeypatch.setattr(
type(settings),
'get_cryptobot_invoice_expires_seconds',
lambda self: 600,
raising=False,
)
result = await service.create_cryptobot_payment(
db=db,
user_id=9,
amount_usd=12.5,
asset='USDT',
description='Пополнение',
payload='custom',
)
assert result is not None
assert result['local_payment_id'] == 555
assert result['invoice_id'] == '12345'
assert result['bot_invoice_url'] == 'https://t.me/invoice'
assert stub.calls and stub.calls[0]['expires_in'] == 600
assert captured_args['invoice_id'] == '12345'
assert captured_args['amount'] == '12.50'
@pytest.mark.anyio('asyncio')
async def test_create_cryptobot_payment_returns_none_when_service_missing() -> None:
service = _make_service(None)
db = DummySession()
result = await service.create_cryptobot_payment(
db=db,
user_id=1,
amount_usd=10,
)
assert result is None
@pytest.mark.anyio('asyncio')
async def test_create_cryptobot_payment_handles_empty_response(monkeypatch: pytest.MonkeyPatch) -> None:
stub = StubCryptoBotService(response=None)
service = _make_service(stub)
db = DummySession()
called = False
async def fake_create_cryptobot_payment(**kwargs: Any) -> DummyLocalPayment:
nonlocal called
called = True
return DummyLocalPayment()
monkeypatch.setattr(
cryptobot_crud,
'create_cryptobot_payment',
fake_create_cryptobot_payment,
raising=False,
)
result = await service.create_cryptobot_payment(
db=db,
user_id=1,
amount_usd=5,
)
assert result is None
assert called is False