From 6716221a6a4b1faddc6793b4608ecdbe99e8b678 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Mon, 28 Sep 2026 23:49:00 +0200 Subject: [PATCH] Abort Harmony options flow when the entry is not loaded (#182622) --- .../components/harmony/config_flow.py | 4 ++++ homeassistant/components/harmony/strings.json | 3 +++ tests/components/harmony/test_config_flow.py | 15 ++++++++++++ tests/components/harmony/test_init.py | 23 +++++++++++++++++++ 4 files changed, 45 insertions(+) diff --git a/homeassistant/components/harmony/config_flow.py b/homeassistant/components/harmony/config_flow.py index 589c1bd4e6bb..17c4fcca1b8c 100644 --- a/homeassistant/components/harmony/config_flow.py +++ b/homeassistant/components/harmony/config_flow.py @@ -16,6 +16,7 @@ from homeassistant.components.remote import ( ) from homeassistant.config_entries import ( ConfigEntry, + ConfigEntryState, ConfigFlow, ConfigFlowResult, OptionsFlow, @@ -197,6 +198,9 @@ class OptionsFlowHandler(OptionsFlow): if user_input is not None: return self.async_create_entry(title="", data=user_input) + if self.config_entry.state is not ConfigEntryState.LOADED: + return self.async_abort(reason="entry_not_loaded") + remote = self.config_entry.runtime_data data_schema = probatio.Schema( { diff --git a/homeassistant/components/harmony/strings.json b/homeassistant/components/harmony/strings.json index 7ac6250ef39e..cf167acecad1 100644 --- a/homeassistant/components/harmony/strings.json +++ b/homeassistant/components/harmony/strings.json @@ -35,6 +35,9 @@ } }, "options": { + "abort": { + "entry_not_loaded": "The options can be changed once the hub has been set up." + }, "step": { "init": { "data": { diff --git a/tests/components/harmony/test_config_flow.py b/tests/components/harmony/test_config_flow.py index 437ba63c8315..8fb4e18fb548 100644 --- a/tests/components/harmony/test_config_flow.py +++ b/tests/components/harmony/test_config_flow.py @@ -233,6 +233,21 @@ async def test_form_errors( assert result2["errors"] == {"base": error} +async def test_options_flow_entry_not_loaded(hass: HomeAssistant) -> None: + """Test the options flow aborts while the entry is not set up.""" + config_entry = MockConfigEntry( + domain=DOMAIN, + unique_id="abcde12345", + data={CONF_HOST: "1.2.3.4", CONF_NAME: "Guest Room"}, + ) + config_entry.add_to_hass(hass) + + result = await hass.config_entries.options.async_init(config_entry.entry_id) + + assert result["type"] is FlowResultType.ABORT + assert result["reason"] == "entry_not_loaded" + + async def test_options_flow(hass: HomeAssistant, mock_hc, mock_write_config) -> None: """Test config flow options.""" config_entry = MockConfigEntry( diff --git a/tests/components/harmony/test_init.py b/tests/components/harmony/test_init.py index c833c63a8867..bfe301f79828 100644 --- a/tests/components/harmony/test_init.py +++ b/tests/components/harmony/test_init.py @@ -1,11 +1,18 @@ """Test init of Logitch Harmony Hub integration.""" +from unittest.mock import AsyncMock + +from aioharmony.exceptions import TimeOut +import pytest + from homeassistant.components.harmony.const import DOMAIN +from homeassistant.config_entries import ConfigEntryState from homeassistant.const import CONF_HOST, CONF_NAME from homeassistant.core import HomeAssistant from homeassistant.helpers import entity_registry as er from homeassistant.setup import async_setup_component +from .conftest import FakeHarmonyClient from .const import ( ENTITY_NILE_TV, ENTITY_PLAY_MUSIC, @@ -85,3 +92,19 @@ async def test_unique_id_migration( select_activities = ent_reg.async_get(ENTITY_SELECT) assert select_activities.unique_id == f"{HUB_NAME}_activities" + + +@pytest.mark.usefixtures("mock_hc") +async def test_connect_timeout_retries_setup( + hass: HomeAssistant, + harmony_client: FakeHarmonyClient, + mock_config_entry: MockConfigEntry, +) -> None: + """Test a hub that times out on connect closes the client and retries setup.""" + harmony_client.connect = AsyncMock(side_effect=TimeOut) + mock_config_entry.add_to_hass(hass) + + assert not await hass.config_entries.async_setup(mock_config_entry.entry_id) + + assert mock_config_entry.state is ConfigEntryState.SETUP_RETRY + harmony_client.close.assert_awaited_once()