146 lines
4.9 KiB
Python
146 lines
4.9 KiB
Python
import asyncio
|
|
from collections.abc import Awaitable, Callable
|
|
from typing import Any
|
|
|
|
import pytest
|
|
from sqlalchemy import select
|
|
from sqlalchemy.exc import IntegrityError
|
|
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker
|
|
from sqlalchemy.ext.asyncio import create_async_engine
|
|
|
|
from app.repositories.order import OrderData, OrderRepository
|
|
from app.repositories.order.models import Base, Order
|
|
|
|
|
|
def _make_order_data(**overrides: object) -> OrderData:
|
|
payload: dict[str, Any] = {
|
|
"order_uuid": "order-uuid-1",
|
|
"payment_url": "https://pay.test/payment/1",
|
|
"price": 125000,
|
|
"delivery_type": 2,
|
|
"tariff_code": 535,
|
|
"comment": "Test payment",
|
|
"sender": {
|
|
"name": "Petr Petrov",
|
|
"email": "sender@example.com",
|
|
"phone": {"number": "+79009876543"},
|
|
},
|
|
"recipient": {
|
|
"name": "Ivan Ivanov",
|
|
"email": "ivan@example.com",
|
|
"phone": {"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": 1,
|
|
"length": 20,
|
|
"width": 15,
|
|
"height": 10,
|
|
"comment": "Package 1",
|
|
}
|
|
],
|
|
}
|
|
payload.update(overrides)
|
|
return OrderData(**payload)
|
|
|
|
|
|
async def _with_repository(
|
|
test_fn: Callable[
|
|
[OrderRepository, async_sessionmaker[AsyncSession]],
|
|
Awaitable[None],
|
|
],
|
|
) -> None:
|
|
engine = create_async_engine("sqlite+aiosqlite:///:memory:")
|
|
try:
|
|
async with engine.begin() as connection:
|
|
await connection.run_sync(Base.metadata.create_all)
|
|
session_factory = async_sessionmaker(engine, expire_on_commit=False)
|
|
await test_fn(OrderRepository(session_factory=session_factory), session_factory)
|
|
finally:
|
|
await engine.dispose()
|
|
|
|
|
|
def test_create_order_persists_all_required_fields() -> None:
|
|
async def run(
|
|
repository: OrderRepository,
|
|
session_factory: async_sessionmaker[AsyncSession],
|
|
) -> None:
|
|
order_data = _make_order_data()
|
|
|
|
async with repository.session() as session:
|
|
order = await repository.create_order(session, order_data)
|
|
|
|
async with session_factory() as session:
|
|
result = await session.execute(
|
|
select(Order).where(Order.order_uuid == "order-uuid-1")
|
|
)
|
|
persisted_order = result.scalar_one()
|
|
|
|
assert order.id == persisted_order.id
|
|
assert persisted_order.order_uuid == "order-uuid-1"
|
|
assert persisted_order.payment_url == "https://pay.test/payment/1"
|
|
assert persisted_order.price == 125000
|
|
assert persisted_order.delivery_type == 2
|
|
assert persisted_order.tariff_code == 535
|
|
assert persisted_order.sender == order_data.sender
|
|
assert persisted_order.recipient == order_data.recipient
|
|
assert persisted_order.from_location == order_data.from_location
|
|
assert persisted_order.to_location == order_data.to_location
|
|
assert persisted_order.packages == order_data.packages
|
|
assert persisted_order.services == order_data.services
|
|
assert persisted_order.comment == "Test payment"
|
|
assert persisted_order.created_at is not None
|
|
|
|
asyncio.run(_with_repository(run))
|
|
|
|
|
|
def test_create_order_persists_nullable_services_and_comment() -> None:
|
|
async def run(
|
|
repository: OrderRepository,
|
|
session_factory: async_sessionmaker[AsyncSession],
|
|
) -> None:
|
|
order_data = _make_order_data(services=None, comment=None)
|
|
|
|
async with repository.session() as session:
|
|
await repository.create_order(session, order_data)
|
|
|
|
async with session_factory() as session:
|
|
result = await session.execute(
|
|
select(Order).where(Order.order_uuid == "order-uuid-1")
|
|
)
|
|
persisted_order = result.scalar_one()
|
|
|
|
assert persisted_order.services is None
|
|
assert persisted_order.comment is None
|
|
|
|
asyncio.run(_with_repository(run))
|
|
|
|
|
|
def test_create_order_rejects_duplicate_order_uuid() -> None:
|
|
async def run(
|
|
repository: OrderRepository,
|
|
_session_factory: async_sessionmaker[AsyncSession],
|
|
) -> None:
|
|
order_data = _make_order_data()
|
|
|
|
async with repository.session() as session:
|
|
await repository.create_order(session, order_data)
|
|
|
|
with pytest.raises(IntegrityError):
|
|
async with repository.session() as session:
|
|
await repository.create_order(session, order_data)
|
|
|
|
asyncio.run(_with_repository(run))
|