Files
g2s-aggregator/tests/controllers/v1/test_order.py
T
Раис Юсупалиев 2b68d050a9 017 add creating order router
2026-03-14 04:12:59 +03:00

168 lines
5.3 KiB
Python

import asyncio
import httpx
from app.controllers.v1.delivery import get_aggregator_service
from app.main import create_app
from app.schemas.order import OrderCreateRequest, OrderCreateResponse
from app.services.aggregator import (
AggregatorServiceError,
InvalidOrderCreateRequestError,
)
class StubAggregatorService:
def __init__(self, *, response: object, error: Exception | None = None) -> None:
self._response = response
self._error = error
self.calls: list[OrderCreateRequest] = []
async def create_order(self, request: OrderCreateRequest) -> object:
self.calls.append(request)
if self._error is not None:
raise self._error
return self._response
def _install_service_override(app, service: StubAggregatorService) -> None:
async def override_service() -> StubAggregatorService:
return service
app.dependency_overrides[get_aggregator_service] = override_service
def _valid_payload() -> dict[str, object]:
return {
"type": 2,
"tariff_code": 535,
"comment": "Test order",
"sender": {
"company": "Romashka LLC",
"name": "Petr Petrov",
"email": "sender@example.com",
"phones": [{"number": "+79009876543"}],
},
"recipient": {
"name": "Ivan Ivanov",
"email": "ivan@example.com",
"phones": [{"number": "+79001234567"}],
},
"from_location": {
"address": "Lenina 1",
"city": "Moscow",
"country_code": "RU",
},
"to_location": {
"address": "Pushkina 10",
"city": "Novosibirsk",
"country_code": "RU",
},
"services": [{"code": "INSURANCE", "parameter": "1000"}],
"packages": [
{
"number": "1",
"weight": 1000,
"length": 20,
"width": 15,
"height": 10,
"comment": "Package 1",
}
],
}
def test_post_delivery_order_returns_response_and_delegates_to_service() -> None:
expected_response = OrderCreateResponse(provider="cdek", order_uuid="order-uuid-1")
service = StubAggregatorService(response=expected_response)
app = create_app()
_install_service_override(app, service)
async def run_request() -> httpx.Response:
transport = httpx.ASGITransport(app=app)
async with httpx.AsyncClient(
transport=transport,
base_url="http://testserver",
) as client:
return await client.post("/api/v1/delivery/order", json=_valid_payload())
response = asyncio.run(run_request())
assert response.status_code == 200
assert response.json() == expected_response.model_dump(mode="json")
assert service.calls == [OrderCreateRequest(**_valid_payload())]
def test_post_delivery_order_rejects_invalid_payload() -> None:
service = StubAggregatorService(response=None)
app = create_app()
_install_service_override(app, service)
invalid_payload = _valid_payload()
invalid_payload["tariff_code"] = 136
async def run_request() -> httpx.Response:
transport = httpx.ASGITransport(app=app)
async with httpx.AsyncClient(
transport=transport,
base_url="http://testserver",
) as client:
return await client.post("/api/v1/delivery/order", json=invalid_payload)
response = asyncio.run(run_request())
assert response.status_code == 422
assert service.calls == []
def test_post_delivery_order_maps_invalid_request_to_400() -> None:
service = StubAggregatorService(
response=None,
error=InvalidOrderCreateRequestError("invalid payload"),
)
app = create_app()
_install_service_override(app, service)
async def run_request() -> httpx.Response:
transport = httpx.ASGITransport(app=app, raise_app_exceptions=False)
async with httpx.AsyncClient(
transport=transport,
base_url="http://testserver",
) as client:
return await client.post("/api/v1/delivery/order", json=_valid_payload())
response = asyncio.run(run_request())
assert response.status_code == 400
assert response.json() == {
"detail": {
"code": "invalid_order_create_request",
"message": "Order request contains invalid or unsupported CDEK data.",
}
}
def test_post_delivery_order_maps_service_exception_to_503() -> None:
service = StubAggregatorService(
response=None,
error=AggregatorServiceError("service unavailable"),
)
app = create_app()
_install_service_override(app, service)
async def run_request() -> httpx.Response:
transport = httpx.ASGITransport(app=app, raise_app_exceptions=False)
async with httpx.AsyncClient(
transport=transport,
base_url="http://testserver",
) as client:
return await client.post("/api/v1/delivery/order", json=_valid_payload())
response = asyncio.run(run_request())
assert response.status_code == 503
assert response.json() == {
"detail": {
"code": "order_creation_unavailable",
"message": "CDEK order creation is temporarily unavailable.",
}
}