From b2721d659676859e6a7207c930f444eb3cf4e208 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 7 May 2022 16:18:40 -0500 Subject: [PATCH] Ensure sql sensors keep working after using the options flow (#71453) * Ensure sql sensors keep working after using the options flow Fixes ``` 2022-05-06 16:17:57 ERROR (MainThread) [homeassistant.components.sensor] Error while setting up sql platform for sensor Traceback (most recent call last): File "/Users/bdraco/home-assistant/homeassistant/helpers/entity_platform.py", line 249, in _async_setup_platform await asyncio.shield(task) File "/Users/bdraco/home-assistant/homeassistant/components/sql/sensor.py", line 97, in async_setup_entry name: str = entry.options[CONF_NAME] KeyError: name ``` * ensure saving the options flow fixes the broken config entry * ensure options changes take effect right away * Add cover to validate the reload --- homeassistant/components/sql/__init__.py | 6 +++ homeassistant/components/sql/config_flow.py | 9 +++- tests/components/sql/test_config_flow.py | 55 +++++++++++++++++++++ 3 files changed, 69 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/sql/__init__.py b/homeassistant/components/sql/__init__.py index 3c83b01b284..2917056b5d4 100644 --- a/homeassistant/components/sql/__init__.py +++ b/homeassistant/components/sql/__init__.py @@ -7,8 +7,14 @@ from homeassistant.core import HomeAssistant from .const import PLATFORMS +async def async_update_listener(hass: HomeAssistant, entry: ConfigEntry) -> None: + """Update listener for options.""" + await hass.config_entries.async_reload(entry.entry_id) + + async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Set up SQL from a config entry.""" + entry.async_on_unload(entry.add_update_listener(async_update_listener)) hass.config_entries.async_setup_platforms(entry, PLATFORMS) diff --git a/homeassistant/components/sql/config_flow.py b/homeassistant/components/sql/config_flow.py index b18ea406618..ba9a5f7e4dd 100644 --- a/homeassistant/components/sql/config_flow.py +++ b/homeassistant/components/sql/config_flow.py @@ -167,7 +167,14 @@ class SQLOptionsFlowHandler(config_entries.OptionsFlow): except ValueError: errors["query"] = "query_invalid" else: - return self.async_create_entry(title="", data=user_input) + return self.async_create_entry( + title="", + data={ + CONF_NAME: self.entry.title, + **self.entry.options, + **user_input, + }, + ) return self.async_show_form( step_id="init", diff --git a/tests/components/sql/test_config_flow.py b/tests/components/sql/test_config_flow.py index ec851b491b7..3e065df0ebd 100644 --- a/tests/components/sql/test_config_flow.py +++ b/tests/components/sql/test_config_flow.py @@ -214,9 +214,62 @@ async def test_options_flow(hass: HomeAssistant) -> None: assert result["type"] == RESULT_TYPE_CREATE_ENTRY assert result["data"] == { + "name": "Get Value", "db_url": "sqlite://", "query": "SELECT 5 as size", "column": "size", + "value_template": None, + "unit_of_measurement": "MiB", + } + + +async def test_options_flow_name_previously_removed(hass: HomeAssistant) -> None: + """Test options config flow where the name was missing.""" + entry = MockConfigEntry( + domain=DOMAIN, + data={}, + options={ + "db_url": "sqlite://", + "query": "SELECT 5 as value", + "column": "value", + "unit_of_measurement": "MiB", + "value_template": None, + }, + title="Get Value Title", + ) + entry.add_to_hass(hass) + + assert await hass.config_entries.async_setup(entry.entry_id) + await hass.async_block_till_done() + + result = await hass.config_entries.options.async_init(entry.entry_id) + + assert result["type"] == RESULT_TYPE_FORM + assert result["step_id"] == "init" + + with patch( + "homeassistant.components.sql.async_setup_entry", + return_value=True, + ) as mock_setup_entry: + result = await hass.config_entries.options.async_configure( + result["flow_id"], + user_input={ + "db_url": "sqlite://", + "query": "SELECT 5 as size", + "column": "size", + "unit_of_measurement": "MiB", + }, + ) + await hass.async_block_till_done() + + assert len(mock_setup_entry.mock_calls) == 1 + assert result["type"] == RESULT_TYPE_CREATE_ENTRY + assert result["data"] == { + "name": "Get Value Title", + "db_url": "sqlite://", + "query": "SELECT 5 as size", + "column": "size", + "value_template": None, "unit_of_measurement": "MiB", } @@ -312,6 +365,8 @@ async def test_options_flow_fails_invalid_query( assert result4["type"] == RESULT_TYPE_CREATE_ENTRY assert result4["data"] == { + "name": "Get Value", + "value_template": None, "db_url": "sqlite://", "query": "SELECT 5 as size", "column": "size",