From 7fc56056395d8ff41f23010bfc3f962f94174276 Mon Sep 17 00:00:00 2001 From: corneyl Date: Mon, 27 Dec 2021 20:31:35 +0100 Subject: [PATCH] Fix keyerror when no previous Picnic orders exist (#62870) --- homeassistant/components/picnic/coordinator.py | 13 +++++++------ tests/components/picnic/test_sensor.py | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/picnic/coordinator.py b/homeassistant/components/picnic/coordinator.py index bcd4e79a098..71a6559975c 100644 --- a/homeassistant/components/picnic/coordinator.py +++ b/homeassistant/components/picnic/coordinator.py @@ -60,11 +60,11 @@ class PicnicUpdateCoordinator(DataUpdateCoordinator): """Fetch the data from the Picnic API and return a flat dict with only needed sensor data.""" # Fetch from the API and pre-process the data cart = self.picnic_api_client.get_cart() - last_order = self._get_last_order() - if not cart or not last_order: + if not cart: raise UpdateFailed("API response doesn't contain expected data.") + last_order = self._get_last_order() slot_data = self._get_slot_data(cart) return { @@ -102,11 +102,12 @@ class PicnicUpdateCoordinator(DataUpdateCoordinator): """Get data of the last order from the list of deliveries.""" # Get the deliveries deliveries = self.picnic_api_client.get_deliveries(summary=True) - if not deliveries: - return {} - # Determine the last order - last_order = copy.deepcopy(deliveries[0]) + # Determine the last order and return an empty dict if there is none + try: + last_order = copy.deepcopy(deliveries[0]) + except KeyError: + return {} # Get the position details if the order is not delivered yet delivery_position = {} diff --git a/tests/components/picnic/test_sensor.py b/tests/components/picnic/test_sensor.py index f1882bfa098..7ade1e38d09 100644 --- a/tests/components/picnic/test_sensor.py +++ b/tests/components/picnic/test_sensor.py @@ -387,6 +387,21 @@ class TestPicnicSensor(unittest.IsolatedAsyncioTestCase): self._assert_sensor("sensor.picnic_last_order_eta_end", STATE_UNAVAILABLE) self._assert_sensor("sensor.picnic_last_order_delivery_time", STATE_UNAVAILABLE) + async def test_sensors_malformed_delivery_data(self): + """Test sensor states when the delivery api returns not a list.""" + # Setup platform with default responses + await self._setup_platform(use_default_responses=True) + + # Change mock responses to empty data and refresh the coordinator + self.picnic_mock().get_deliveries.return_value = {"error": "message"} + await self._coordinator.async_refresh() + + # Assert all last-order sensors have STATE_UNAVAILABLE because the delivery info fetch failed + assert self._coordinator.last_update_success is True + self._assert_sensor("sensor.picnic_last_order_eta_start", STATE_UNKNOWN) + self._assert_sensor("sensor.picnic_last_order_eta_end", STATE_UNKNOWN) + self._assert_sensor("sensor.picnic_last_order_delivery_time", STATE_UNKNOWN) + async def test_sensors_malformed_response(self): """Test coordinator update fails when API yields ValueError.""" # Setup platform with default responses