"""Тесты ExoCrmClient. Сеть замокана через respx — реальных запросов не делает.""" from __future__ import annotations import pytest import respx from httpx import Response from app.core.config import Settings from app.services.crm.client import CrmError from app.services.crm.exo_client import ExoCrmClient BASE_URL = "https://crm.example.test/api/1.1/" def _settings() -> Settings: return Settings( secret_key="test-secret-key", encryption_key="dGVzdC1lbmNyeXB0aW9uLWtleS0zMi1ieXRlcyEh", crm_base_url=BASE_URL, crm_api_key="apikey123", crm_secret_key="secret123", crm_shop_key="shopkey123", crm_sid=1, ) # type: ignore[arg-type] ORDER_PAYLOAD = { "ID": "1", "CreateDateTime": "2026-09-20 10:00:00", "RecipientDName": "Іван Іванов", "RecipientPhone": "+380501112233", "RecipientEmail": None, "Waybill_Number": "", "Notes": None, "Total": { "Cost": "0.00", "Quantity": 1, "Weight": 0, "DiscountAmount": "0.00", "DiscountPercent": "0.00", "Amount": "100.00", }, "Goods": [ { "ID": "10", "SKU": "SKU-1", "Name": "Товар", "Price": "100.00", "Quantity": "1.000", "DiscountAmount": "0.00", "DiscountPercent": "0.00", "Amount": "100.00", } ], } class TestExoCrmClientGetOrders: @respx.mock async def test_sends_expected_request_body(self) -> None: route = respx.post(BASE_URL).mock( return_value=Response(200, json={"status": "OK", "result": []}) ) client = ExoCrmClient(_settings()) await client.get_orders(status="APPROVED") sent = route.calls.last.request body = sent.content import json parsed = json.loads(body) assert parsed["apikey"] == "apikey123" assert parsed["object"] == "Orders" assert parsed["method"] == "GetOrders" assert parsed["params"]["sid"] == 1 assert parsed["params"]["key"] == "shopkey123" assert parsed["params"]["Status"] == "APPROVED" assert "md5sum" in parsed @respx.mock async def test_parses_successful_response_into_order_out(self) -> None: respx.post(BASE_URL).mock( return_value=Response(200, json={"status": "OK", "result": [ORDER_PAYLOAD]}) ) client = ExoCrmClient(_settings()) orders = await client.get_orders(status="APPROVED") assert len(orders) == 1 order = orders[0] assert order.id == "1" assert order.recipient_name == "Іван Іванов" assert order.total.quantity == "1" assert order.goods[0].sku == "SKU-1" @respx.mock async def test_raises_crm_error_on_error_status(self) -> None: respx.post(BASE_URL).mock( return_value=Response( 200, json={"status": "ERROR", "errors": {"1005": "Checksum Error"}} ) ) client = ExoCrmClient(_settings()) with pytest.raises(CrmError, match="Checksum Error"): await client.get_orders(status="APPROVED")