From 7b3f100efb456d700e0b1d183060b21918f4f8d8 Mon Sep 17 00:00:00 2001 From: Maciej Bieniek Date: Wed, 14 Jun 2023 21:00:21 +0000 Subject: [PATCH] Catch InvalidAuthError in `shutdown()` method for Shelly gen2 devices (#94563) * Catch InvalidAuthError in shutdown() method * Add test * Revert unwanted change in tests --- .../components/shelly/coordinator.py | 5 +- tests/components/shelly/test_coordinator.py | 55 ++++++++++++++++++- 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/shelly/coordinator.py b/homeassistant/components/shelly/coordinator.py index 85207ee4475..6d7b3496880 100644 --- a/homeassistant/components/shelly/coordinator.py +++ b/homeassistant/components/shelly/coordinator.py @@ -535,7 +535,10 @@ class ShellyRpcCoordinator(ShellyCoordinatorBase[RpcDevice]): async def shutdown(self) -> None: """Shutdown the coordinator.""" if self.device.connected: - await async_stop_scanner(self.device) + try: + await async_stop_scanner(self.device) + except InvalidAuthError: + self.entry.async_start_reauth(self.hass) await self.device.shutdown() await self._async_disconnected() diff --git a/tests/components/shelly/test_coordinator.py b/tests/components/shelly/test_coordinator.py index 2f267a208ca..9039893999d 100644 --- a/tests/components/shelly/test_coordinator.py +++ b/tests/components/shelly/test_coordinator.py @@ -1,6 +1,6 @@ """Tests for Shelly coordinator.""" from datetime import timedelta -from unittest.mock import AsyncMock +from unittest.mock import AsyncMock, patch from aioshelly.exceptions import DeviceConnectionError, InvalidAuthError @@ -335,6 +335,59 @@ async def test_rpc_reload_on_cfg_change( assert hass.states.get("switch.test_switch_0") is None +async def test_rpc_reload_with_invalid_auth( + hass: HomeAssistant, mock_rpc_device, monkeypatch +) -> None: + """Test RPC when InvalidAuthError is raising during config entry reload.""" + with patch( + "homeassistant.components.shelly.coordinator.async_stop_scanner", + side_effect=[None, InvalidAuthError, None], + ): + entry = await init_integration(hass, 2) + + inject_rpc_device_event( + monkeypatch, + mock_rpc_device, + { + "events": [ + { + "data": [], + "event": "config_changed", + "id": 1, + "ts": 1668522399.2, + }, + { + "data": [], + "id": 2, + "ts": 1668522399.2, + }, + ], + "ts": 1668522399.2, + }, + ) + + await hass.async_block_till_done() + + # Move time to generate reconnect + async_fire_time_changed( + hass, dt_util.utcnow() + timedelta(seconds=RPC_RECONNECT_INTERVAL) + ) + await hass.async_block_till_done() + + assert entry.state == ConfigEntryState.LOADED + + flows = hass.config_entries.flow.async_progress() + assert len(flows) == 1 + + flow = flows[0] + assert flow.get("step_id") == "reauth_confirm" + assert flow.get("handler") == DOMAIN + + assert "context" in flow + assert flow["context"].get("source") == SOURCE_REAUTH + assert flow["context"].get("entry_id") == entry.entry_id + + async def test_rpc_click_event( hass: HomeAssistant, mock_rpc_device, events, monkeypatch ) -> None: