import json import uuid from datetime import UTC, datetime from decimal import Decimal import httpx2 import pytest from app.config import Settings from app.models import Currency, PaymentStatus from app.processing import PaymentGateway, WebhookClient from app.schemas import PaymentWebhook @pytest.mark.parametrize( ("success_rate", "expected"), [ (1.0, PaymentStatus.SUCCEEDED), (0.0, PaymentStatus.FAILED), ], ) async def test_gateway_returns_configured_result( success_rate: float, expected: PaymentStatus, ) -> None: gateway = PaymentGateway( Settings( processing_min_seconds=0, processing_max_seconds=0, processing_success_rate=success_rate, ) ) assert await gateway.charge() is expected async def test_webhook_client_posts_serialized_payload( monkeypatch: pytest.MonkeyPatch, ) -> None: requests: list[httpx2.Request] = [] def handler(request: httpx2.Request) -> httpx2.Response: requests.append(request) return httpx2.Response(204) transport = httpx2.MockTransport(handler) async_client = httpx2.AsyncClient monkeypatch.setattr( "app.processing.httpx2.AsyncClient", lambda **kwargs: async_client(transport=transport, **kwargs), ) payload = PaymentWebhook( payment_id=uuid.uuid4(), amount=Decimal("10.25"), currency=Currency.USD, status=PaymentStatus.SUCCEEDED, processed_at=datetime.now(UTC), metadata={"order_id": 42}, ) await WebhookClient(timeout=1).send("https://example.com/hook", payload) assert len(requests) == 1 assert json.loads(requests[0].content) == payload.model_dump(mode="json") async def test_webhook_client_raises_for_server_error( monkeypatch: pytest.MonkeyPatch, ) -> None: transport = httpx2.MockTransport(lambda _: httpx2.Response(500)) async_client = httpx2.AsyncClient monkeypatch.setattr( "app.processing.httpx2.AsyncClient", lambda **kwargs: async_client(transport=transport, **kwargs), ) payload = PaymentWebhook( payment_id=uuid.uuid4(), amount=Decimal("1.00"), currency=Currency.EUR, status=PaymentStatus.FAILED, processed_at=datetime.now(UTC), metadata={}, ) with pytest.raises(httpx2.HTTPStatusError): await WebhookClient(timeout=1).send("https://example.com/hook", payload)