Fix ETTN creation on live Checkbox
- prepayment as DISCOUNT: live API rejects PRE_PAYMENT with 400 third_party.generic - normalize lowercase ETTN statuses returned by the live API - show Checkbox error code instead of bare 'Internal Server Error' - page size 50 for ETTN list, 429 rate limit is retryable, pause polling on it - phone in 380XXXXXXXXX format like portal receipts Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -148,3 +148,35 @@ async def test_bad_pin_raises() -> None:
|
||||
)
|
||||
with pytest.raises(CheckboxError, match="Невірний пін-код"):
|
||||
await _client().sign_in(CREDS)
|
||||
|
||||
|
||||
@respx.mock
|
||||
async def test_lowercase_status_from_live_api_is_normalized() -> None:
|
||||
_signin()
|
||||
respx.get(f"{BASE}/api/v1/ettn/e-1").mock(
|
||||
return_value=Response(200, json={**ETTN, "status": "done"})
|
||||
)
|
||||
ettn = await _client().get_ettn(CREDS, "e-1")
|
||||
assert ettn.status == "DONE"
|
||||
|
||||
|
||||
@respx.mock
|
||||
async def test_third_party_error_code_is_shown() -> None:
|
||||
_signin()
|
||||
respx.post(f"{BASE}/api/v1/ettn").mock(
|
||||
return_value=Response(
|
||||
400, json={"code": "third_party.generic", "message": "Internal Server Error"}
|
||||
)
|
||||
)
|
||||
with pytest.raises(CheckboxError, match=r"third_party\.generic"):
|
||||
await _client().create_ettn(CREDS, {})
|
||||
|
||||
|
||||
@respx.mock
|
||||
async def test_rate_limit_is_retryable() -> None:
|
||||
_signin()
|
||||
respx.post(f"{BASE}/api/v1/ettn").mock(
|
||||
return_value=Response(429, json={"message": "Занадто часто виконуються запити"})
|
||||
)
|
||||
with pytest.raises(CheckboxUnavailableError):
|
||||
await _client().create_ettn(CREDS, {})
|
||||
|
||||
@@ -117,7 +117,7 @@ class TestBuildBody:
|
||||
}
|
||||
]
|
||||
assert "discounts" not in rb
|
||||
assert rb["delivery"] == {"phone": "+380501112233", "emails": ["a@b.ua"]}
|
||||
assert rb["delivery"] == {"phone": "380501112233", "emails": ["a@b.ua"]}
|
||||
|
||||
def test_prepayment_line_and_order_discounts_and_tax(self) -> None:
|
||||
order = _order(
|
||||
@@ -132,10 +132,8 @@ class TestBuildBody:
|
||||
assert rb["goods"][0]["discounts"] == [
|
||||
{"type": "DISCOUNT", "mode": "VALUE", "value": 10000}
|
||||
]
|
||||
assert [(d["type"], d["value"]) for d in rb["discounts"]] == [
|
||||
("DISCOUNT", 5000),
|
||||
("PRE_PAYMENT", 20000),
|
||||
]
|
||||
# Скидка заказа 50 ₴ + предоплата 200 ₴ — одной «Знижкой», без PRE_PAYMENT.
|
||||
assert [(d["type"], d["value"]) for d in rb["discounts"]] == [("DISCOUNT", 25000)]
|
||||
assert rb["payments"][0]["value"] == 85000
|
||||
|
||||
def test_all_goods_with_prices_quantities_and_sums(self) -> None:
|
||||
@@ -166,7 +164,7 @@ class TestBuildBody:
|
||||
goods_total = sum(svc._line_sum(g["good"]["price"], g["quantity"]) for g in rb["goods"])
|
||||
assert goods_total - 20000 == rb["payments"][0]["value"] == 130049
|
||||
assert rb["discounts"] == [
|
||||
{"type": "PRE_PAYMENT", "mode": "VALUE", "value": 20000, "name": "Передоплата"}
|
||||
{"type": "DISCOUNT", "mode": "VALUE", "value": 20000, "name": "Знижка"}
|
||||
]
|
||||
|
||||
def test_fractional_quantity(self) -> None:
|
||||
|
||||
Reference in New Issue
Block a user