017 fix returning all tariffs
This commit is contained in:
@@ -17,7 +17,7 @@ class StubProvider:
|
||||
self,
|
||||
name: str,
|
||||
*,
|
||||
response: DeliveryPrice | None = None,
|
||||
response: list[DeliveryPrice] | None = None,
|
||||
error: Exception | None = None,
|
||||
cache_ttl_seconds: int = 900,
|
||||
) -> None:
|
||||
@@ -27,7 +27,7 @@ class StubProvider:
|
||||
self.cache_ttl_seconds = cache_ttl_seconds
|
||||
self.calls: list[DeliveryRequest] = []
|
||||
|
||||
async def get_price(self, request: DeliveryRequest) -> DeliveryPrice:
|
||||
async def get_prices(self, request: DeliveryRequest) -> list[DeliveryPrice]:
|
||||
self.calls.append(request)
|
||||
if self._error is not None:
|
||||
raise self._error
|
||||
@@ -73,10 +73,10 @@ def _make_request(**overrides: object) -> DeliveryRequest:
|
||||
return DeliveryRequest(**payload)
|
||||
|
||||
|
||||
def _make_price(provider: str, price: str) -> DeliveryPrice:
|
||||
def _make_price(provider: str, price: str, *, service_name: str = "standard") -> DeliveryPrice:
|
||||
return DeliveryPrice(
|
||||
provider=provider,
|
||||
service_name="standard",
|
||||
service_name=service_name,
|
||||
price=Decimal(price),
|
||||
currency="RUB",
|
||||
delivery_days_min=2,
|
||||
@@ -85,8 +85,19 @@ def _make_price(provider: str, price: str) -> DeliveryPrice:
|
||||
|
||||
|
||||
def test_get_all_prices_full_success_returns_sorted_and_updates_cache() -> None:
|
||||
provider_a = StubProvider(name="a", response=_make_price("a", "300.49"), cache_ttl_seconds=111)
|
||||
provider_b = StubProvider(name="b", response=_make_price("b", "100.40"), cache_ttl_seconds=222)
|
||||
provider_a = StubProvider(
|
||||
name="a",
|
||||
response=[
|
||||
_make_price("a", "300.49", service_name="economy"),
|
||||
_make_price("a", "200.49", service_name="express"),
|
||||
],
|
||||
cache_ttl_seconds=111,
|
||||
)
|
||||
provider_b = StubProvider(
|
||||
name="b",
|
||||
response=[_make_price("b", "100.40")],
|
||||
cache_ttl_seconds=222,
|
||||
)
|
||||
cache = StubCache()
|
||||
service = AggregatorService(
|
||||
[provider_a, provider_b],
|
||||
@@ -96,16 +107,18 @@ def test_get_all_prices_full_success_returns_sorted_and_updates_cache() -> None:
|
||||
|
||||
result = asyncio.run(service.get_all_prices(_make_request()))
|
||||
|
||||
assert [price.provider for price in result] == ["b", "a"]
|
||||
assert [price.price for price in result] == [Decimal("110"), Decimal("331")]
|
||||
assert [price.provider for price in result] == ["b", "a", "a"]
|
||||
assert [price.service_name for price in result] == ["standard", "express", "economy"]
|
||||
assert [price.price for price in result] == [Decimal("110"), Decimal("221"), Decimal("331")]
|
||||
assert len(provider_a.calls) == 1
|
||||
assert len(provider_b.calls) == 1
|
||||
assert len(cache.get_calls) == 2
|
||||
assert [len(payload) for _, payload, _ in cache.set_calls] == [2, 1]
|
||||
assert [ttl for _, _, ttl in cache.set_calls] == [111, 222]
|
||||
|
||||
|
||||
def test_get_all_prices_normalizes_and_forwards_country_code_to_providers() -> None:
|
||||
provider = StubProvider(name="cdek", response=_make_price("cdek", "150.00"))
|
||||
provider = StubProvider(name="cdek", response=[_make_price("cdek", "150.00")])
|
||||
service = AggregatorService([provider], cache=StubCache())
|
||||
|
||||
result = asyncio.run(service.get_all_prices(_make_request(country_code=" kz ")))
|
||||
@@ -116,13 +129,20 @@ def test_get_all_prices_normalizes_and_forwards_country_code_to_providers() -> N
|
||||
|
||||
|
||||
def test_get_all_prices_partial_failure_excludes_failed_provider() -> None:
|
||||
provider_ok = StubProvider(name="ok", response=_make_price("ok", "150.00"))
|
||||
provider_ok = StubProvider(
|
||||
name="ok",
|
||||
response=[
|
||||
_make_price("ok", "150.00", service_name="economy"),
|
||||
_make_price("ok", "120.00", service_name="express"),
|
||||
],
|
||||
)
|
||||
provider_failed = StubProvider(name="failed", error=RuntimeError("provider unavailable"))
|
||||
service = AggregatorService([provider_ok, provider_failed], cache=StubCache())
|
||||
|
||||
result = asyncio.run(service.get_all_prices(_make_request()))
|
||||
|
||||
assert [price.provider for price in result] == ["ok"]
|
||||
assert [price.provider for price in result] == ["ok", "ok"]
|
||||
assert [price.service_name for price in result] == ["express", "economy"]
|
||||
assert len(provider_ok.calls) == 1
|
||||
assert len(provider_failed.calls) == 1
|
||||
|
||||
@@ -153,9 +173,12 @@ def test_get_all_prices_raises_invalid_request_for_provider_request_errors() ->
|
||||
|
||||
|
||||
def test_get_all_prices_cache_hit_skips_provider_call() -> None:
|
||||
cached_payload = _make_price("cdek", "100.40").model_dump(mode="json")
|
||||
cached_payload = [
|
||||
_make_price("cdek", "100.40", service_name="express").model_dump(mode="json"),
|
||||
_make_price("cdek", "200.40", service_name="economy").model_dump(mode="json"),
|
||||
]
|
||||
cache = StubCache(forced_get_value=cached_payload)
|
||||
provider = StubProvider(name="cdek", response=_make_price("cdek", "150.00"))
|
||||
provider = StubProvider(name="cdek", response=[_make_price("cdek", "150.00")])
|
||||
service = AggregatorService(
|
||||
[provider],
|
||||
cache=cache,
|
||||
@@ -164,16 +187,23 @@ def test_get_all_prices_cache_hit_skips_provider_call() -> None:
|
||||
|
||||
result = asyncio.run(service.get_all_prices(_make_request()))
|
||||
|
||||
assert [price.provider for price in result] == ["cdek"]
|
||||
assert result[0].price == Decimal("110")
|
||||
assert [price.provider for price in result] == ["cdek", "cdek"]
|
||||
assert [price.service_name for price in result] == ["express", "economy"]
|
||||
assert [price.price for price in result] == [Decimal("110"), Decimal("220")]
|
||||
assert provider.calls == []
|
||||
assert len(cache.get_calls) == 1
|
||||
assert cache.set_calls == []
|
||||
|
||||
|
||||
def test_get_all_prices_delegates_filtering_and_sorting_to_domain_logic() -> None:
|
||||
provider_a = StubProvider(name="a", response=_make_price("a", "300.00"))
|
||||
provider_b = StubProvider(name="b", response=_make_price("b", "100.00"))
|
||||
provider_a = StubProvider(
|
||||
name="a",
|
||||
response=[
|
||||
_make_price("a", "300.00", service_name="economy"),
|
||||
_make_price("a", "200.00", service_name="express"),
|
||||
],
|
||||
)
|
||||
provider_b = StubProvider(name="b", response=[_make_price("b", "100.00")])
|
||||
delegated_inputs: list[list[DeliveryPrice]] = []
|
||||
delegated_multipliers: list[Decimal] = []
|
||||
|
||||
@@ -192,6 +222,11 @@ def test_get_all_prices_delegates_filtering_and_sorting_to_domain_logic() -> Non
|
||||
|
||||
result = asyncio.run(service.get_all_prices(_make_request()))
|
||||
|
||||
assert [price.provider for price in delegated_inputs[0]] == ["a", "b"]
|
||||
assert [price.provider for price in delegated_inputs[0]] == ["a", "a", "b"]
|
||||
assert [price.service_name for price in delegated_inputs[0]] == [
|
||||
"economy",
|
||||
"express",
|
||||
"standard",
|
||||
]
|
||||
assert delegated_multipliers == [Decimal("1.23")]
|
||||
assert [price.provider for price in result] == ["a"]
|
||||
|
||||
Reference in New Issue
Block a user