Files
lux_fiscal/backend/tests/test_nova_poshta_client.py
T
lauadminandClaude Opus 5.5 b8f2fe6b6e Translate UI and user-facing messages to Ukrainian (#5)
- All frontend pages, labels, notices and errors; html lang=uk, uk-UA money format
- Brand "Assistant System" in the top bar and page title
- Backend error details returned to the UI (auth, orders, receipts,
  cash registers, Checkbox/CRM/NP errors) and CLI output
- Tests updated for the new messages

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 15:27:39 +03:00

117 lines
4.4 KiB
Python

"""Тесты NpTrackingClient. Сеть замокана через respx — реальных запросов не делает."""
from __future__ import annotations
import json
import pytest
import respx
from httpx import Response
from app.schemas.tracking import TrackingStatusOut
from app.services.nova_poshta.client import NovaPoshtaError
from app.services.nova_poshta.np_client import _API_URL, NpTrackingClient
STATUS_PAYLOAD = {
"Number": "20451540916703",
"Status": "Відправник самостійно вказав цю накладну, але ще не надав до відправки",
"StatusCode": "1",
"PaymentMethod": "Cash",
"ScheduledDeliveryDate": "22-09-2026 18:00:00",
"ActualDeliveryDate": "",
"AmountToPay": "",
"ExpressWaybillAmountToPay": "827.48",
"AfterpaymentOnGoodsCost": 699,
"PaymentStatus": "",
"ExpressWaybillPaymentStatus": "NeedPayment",
}
API_KEY = "np-apikey-123"
class TestNpTrackingClientGetStatuses:
@respx.mock
async def test_sends_expected_request_body(self) -> None:
route = respx.post(_API_URL).mock(
return_value=Response(200, json={"success": True, "data": [], "errors": []})
)
client = NpTrackingClient()
await client.get_statuses(api_key=API_KEY, waybill_numbers=["20451540916703"])
sent = route.calls.last.request
body = json.loads(sent.content)
assert body["apiKey"] == API_KEY
assert body["modelName"] == "TrackingDocument"
assert body["calledMethod"] == "getStatusDocuments"
assert body["methodProperties"]["Documents"] == [
{"DocumentNumber": "20451540916703", "Phone": ""}
]
@respx.mock
async def test_parses_successful_response_and_prefers_afterpayment_on_goods_cost(
self,
) -> None:
respx.post(_API_URL).mock(
return_value=Response(
200, json={"success": True, "data": [STATUS_PAYLOAD], "errors": []}
)
)
client = NpTrackingClient()
statuses = await client.get_statuses(api_key=API_KEY, waybill_numbers=["20451540916703"])
assert len(statuses) == 1
status = statuses[0]
assert status.number == "20451540916703"
assert status.status_code == "1"
# "Контроль оплати" — сумма за товар без стоимости доставки и комиссии НП,
# не "сколько заплатить сейчас" (`ExpressWaybillAmountToPay` = 827.48).
assert status.cod_amount == "699"
assert status.payment_status == "NeedPayment"
assert not status.is_own # в STATUS_PAYLOAD нет PhoneSender
def test_is_own_by_sender_phone(self) -> None:
own = TrackingStatusOut.model_validate({**STATUS_PAYLOAD, "PhoneSender": "380961112233"})
foreign = TrackingStatusOut.model_validate({**STATUS_PAYLOAD, "PhoneSender": ""})
assert own.is_own
assert not foreign.is_own
@respx.mock
async def test_falls_back_to_amount_to_pay_when_afterpayment_missing(self) -> None:
payload = {**STATUS_PAYLOAD, "AfterpaymentOnGoodsCost": 0}
respx.post(_API_URL).mock(
return_value=Response(200, json={"success": True, "data": [payload], "errors": []})
)
client = NpTrackingClient()
statuses = await client.get_statuses(api_key=API_KEY, waybill_numbers=["20451540916703"])
assert statuses[0].cod_amount == "827.48"
@respx.mock
async def test_raises_nova_poshta_error_on_failure(self) -> None:
respx.post(_API_URL).mock(
return_value=Response(
200, json={"success": False, "data": [], "errors": ["Invalid apiKey"]}
)
)
client = NpTrackingClient()
with pytest.raises(NovaPoshtaError, match="Invalid apiKey"):
await client.get_statuses(api_key=API_KEY, waybill_numbers=["20451540916703"])
async def test_returns_empty_list_for_no_documents(self) -> None:
client = NpTrackingClient()
assert await client.get_statuses(api_key=API_KEY, waybill_numbers=[]) == []
async def test_rejects_too_many_documents(self) -> None:
client = NpTrackingClient()
with pytest.raises(NovaPoshtaError, match="Забагато"):
await client.get_statuses(
api_key=API_KEY, waybill_numbers=[str(i) for i in range(101)]
)