"""Тесты низкоуровневого сервиса YooKassaService.""" from __future__ import annotations import asyncio from datetime import datetime from pathlib import Path import sys 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 # noqa: E402 from app.config import settings # noqa: E402 from app.services.yookassa_service import YooKassaService # noqa: E402 @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), 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), 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"