From 177317a345878fb7d6b3ebd9b6db3304d1bf1d5e Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Thu, 6 May 2021 07:14:01 +0200 Subject: [PATCH] Allow passing options in config flow entry creation (#49912) --- homeassistant/config_entries.py | 26 +++++++++- homeassistant/data_entry_flow.py | 1 + .../components/config/test_config_entries.py | 2 + .../components/philips_js/test_config_flow.py | 1 + tests/components/ps4/test_init.py | 1 + tests/components/subaru/test_config_flow.py | 2 + tests/test_config_entries.py | 50 +++++++++++++++++++ 7 files changed, 81 insertions(+), 2 deletions(-) diff --git a/homeassistant/config_entries.py b/homeassistant/config_entries.py index 7275d3101a9..8c9ad8da4c5 100644 --- a/homeassistant/config_entries.py +++ b/homeassistant/config_entries.py @@ -153,7 +153,7 @@ class ConfigEntry: data: Mapping[str, Any], source: str, system_options: dict, - options: dict | None = None, + options: Mapping[str, Any] | None = None, unique_id: str | None = None, entry_id: str | None = None, state: str = ENTRY_STATE_NOT_LOADED, @@ -631,7 +631,7 @@ class ConfigEntriesFlowManager(data_entry_flow.FlowManager): domain=result["handler"], title=result["title"], data=result["data"], - options={}, + options=result["options"], system_options={}, source=flow.context["source"], unique_id=flow.unique_id, @@ -1297,6 +1297,28 @@ class ConfigFlow(data_entry_flow.FlowHandler): """Handle a flow initialized by DHCP discovery.""" return await self.async_step_discovery(discovery_info) + @callback + def async_create_entry( # pylint: disable=arguments-differ + self, + *, + title: str, + data: Mapping[str, Any], + description: str | None = None, + description_placeholders: dict | None = None, + options: Mapping[str, Any] | None = None, + ) -> data_entry_flow.FlowResult: + """Finish config flow and create a config entry.""" + result = super().async_create_entry( + title=title, + data=data, + description=description, + description_placeholders=description_placeholders, + ) + + result["options"] = options or {} + + return result + class OptionsFlowManager(data_entry_flow.FlowManager): """Flow to set options for a configuration entry.""" diff --git a/homeassistant/data_entry_flow.py b/homeassistant/data_entry_flow.py index 720711e07e3..dd8b1c53a68 100644 --- a/homeassistant/data_entry_flow.py +++ b/homeassistant/data_entry_flow.py @@ -73,6 +73,7 @@ class FlowResult(TypedDict, total=False): context: dict[str, Any] result: Any last_step: bool | None + options: Mapping[str, Any] class FlowManager(abc.ABC): diff --git a/tests/components/config/test_config_entries.py b/tests/components/config/test_config_entries.py index 8cd86ce6df2..2763e5912fa 100644 --- a/tests/components/config/test_config_entries.py +++ b/tests/components/config/test_config_entries.py @@ -333,6 +333,7 @@ async def test_create_account(hass, client): }, "description": None, "description_placeholders": None, + "options": {}, } @@ -403,6 +404,7 @@ async def test_two_step_flow(hass, client): }, "description": None, "description_placeholders": None, + "options": {}, } diff --git a/tests/components/philips_js/test_config_flow.py b/tests/components/philips_js/test_config_flow.py index 48230c72dc9..4841cd5a940 100644 --- a/tests/components/philips_js/test_config_flow.py +++ b/tests/components/philips_js/test_config_flow.py @@ -152,6 +152,7 @@ async def test_pairing(hass, mock_tv_pairable, mock_setup_entry): "title": "55PUS7181/12 (ABCDEFGHIJKLF)", "data": MOCK_CONFIG_PAIRED, "version": 1, + "options": {}, } await hass.async_block_till_done() diff --git a/tests/components/ps4/test_init.py b/tests/components/ps4/test_init.py index cfe2f4b8e87..94167528b21 100644 --- a/tests/components/ps4/test_init.py +++ b/tests/components/ps4/test_init.py @@ -46,6 +46,7 @@ MOCK_FLOW_RESULT = { "type": data_entry_flow.RESULT_TYPE_CREATE_ENTRY, "title": "test_ps4", "data": MOCK_DATA, + "options": {}, } MOCK_ENTRY_ID = "SomeID" diff --git a/tests/components/subaru/test_config_flow.py b/tests/components/subaru/test_config_flow.py index 031b9c29d09..aed15150619 100644 --- a/tests/components/subaru/test_config_flow.py +++ b/tests/components/subaru/test_config_flow.py @@ -115,6 +115,7 @@ async def test_user_form_pin_not_required(hass, user_form): "type": "create_entry", "version": 1, "data": deepcopy(TEST_CONFIG), + "options": {}, } expected["data"][CONF_PIN] = None result["data"][CONF_DEVICE_ID] = TEST_DEVICE_ID @@ -176,6 +177,7 @@ async def test_pin_form_success(hass, pin_form): "type": "create_entry", "version": 1, "data": TEST_CONFIG, + "options": {}, } result["data"][CONF_DEVICE_ID] = TEST_DEVICE_ID assert result == expected diff --git a/tests/test_config_entries.py b/tests/test_config_entries.py index 9c6e469291e..0c12e69364c 100644 --- a/tests/test_config_entries.py +++ b/tests/test_config_entries.py @@ -941,6 +941,56 @@ async def test_setup_retrying_during_unload_before_started(hass): ) +async def test_create_entry_options(hass): + """Test a config entry being created with options.""" + + async def mock_async_setup(hass, config): + """Mock setup.""" + hass.async_create_task( + hass.config_entries.flow.async_init( + "comp", + context={"source": config_entries.SOURCE_IMPORT}, + data={"data": "data", "option": "option"}, + ) + ) + return True + + async_setup_entry = AsyncMock(return_value=True) + mock_integration( + hass, + MockModule( + "comp", async_setup=mock_async_setup, async_setup_entry=async_setup_entry + ), + ) + mock_entity_platform(hass, "config_flow.comp", None) + await async_setup_component(hass, "persistent_notification", {}) + + class TestFlow(config_entries.ConfigFlow): + """Test flow.""" + + VERSION = 1 + + async def async_step_import(self, user_input): + """Test import step creating entry, with options.""" + return self.async_create_entry( + title="title", + data={"example": user_input["data"]}, + options={"example": user_input["option"]}, + ) + + with patch.dict(config_entries.HANDLERS, {"comp": TestFlow}): + assert await async_setup_component(hass, "comp", {}) + + await hass.async_block_till_done() + + assert len(async_setup_entry.mock_calls) == 1 + + entries = hass.config_entries.async_entries("comp") + assert len(entries) == 1 + assert entries[0].data == {"example": "data"} + assert entries[0].options == {"example": "option"} + + async def test_entry_options(hass, manager): """Test that we can set options on an entry.""" entry = MockConfigEntry(domain="test", data={"first": True}, options=None)