From 5657bd11b874c7ea354a4c8f158d5673eedc0ec4 Mon Sep 17 00:00:00 2001 From: Allen Porter Date: Thu, 25 Dec 2025 12:47:42 -0800 Subject: [PATCH] Start reauth when roborock notices the MQTT session is unauthorized (#159719) --- homeassistant/components/roborock/__init__.py | 1 + tests/components/roborock/test_init.py | 38 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/homeassistant/components/roborock/__init__.py b/homeassistant/components/roborock/__init__.py index 3c419873b66..c582d00a1af 100644 --- a/homeassistant/components/roborock/__init__.py +++ b/homeassistant/components/roborock/__init__.py @@ -78,6 +78,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: RoborockConfigEntry) -> show_background=entry.options.get(CONF_SHOW_BACKGROUND, False), map_scale=MAP_SCALE, ), + mqtt_session_unauthorized_hook=lambda: entry.async_start_reauth(hass), ) except RoborockInvalidCredentials as err: raise ConfigEntryAuthFailed( diff --git a/tests/components/roborock/test_init.py b/tests/components/roborock/test_init.py index 8aad5fde10e..352c121e5b4 100644 --- a/tests/components/roborock/test_init.py +++ b/tests/components/roborock/test_init.py @@ -92,6 +92,44 @@ async def test_reauth_started( assert flows[0]["step_id"] == "reauth_confirm" +async def test_mqtt_session_unauthorized_hook_called( + hass: HomeAssistant, + mock_roborock_entry: MockConfigEntry, + device_manager: AsyncMock, +) -> None: + """Test that the mqtt session unauthorized hook is called on unauthorized event.""" + device_manager_kwargs = {} + + def create_device_manager(*args: Any, **kwargs: Any) -> AsyncMock: + nonlocal device_manager_kwargs + device_manager_kwargs = kwargs + return device_manager + + with patch( + "homeassistant.components.roborock.create_device_manager", + side_effect=create_device_manager, + ): + await hass.config_entries.async_setup(mock_roborock_entry.entry_id) + await hass.async_block_till_done() + assert mock_roborock_entry.state is ConfigEntryState.LOADED + + flows = hass.config_entries.flow.async_progress() + assert not flows + + # Simulate an unauthorized event by calling the captured hook + assert device_manager_kwargs + mqtt_session_unauthorized_hook = device_manager_kwargs.get( + "mqtt_session_unauthorized_hook" + ) + assert mqtt_session_unauthorized_hook + mqtt_session_unauthorized_hook() + + # Verify that reauth flow is started + flows = hass.config_entries.flow.async_progress() + assert len(flows) == 1 + assert flows[0]["step_id"] == "reauth_confirm" + + @pytest.mark.parametrize("platforms", [[Platform.IMAGE]]) @pytest.mark.parametrize( ("exists", "is_dir", "rmtree_called"),