From 906e1ce9609ea9aad45a47ea76b137a2fca706a0 Mon Sep 17 00:00:00 2001 From: nivnoach Date: Mon, 7 Dec 2020 10:25:04 +0200 Subject: [PATCH] Allow manual configuration of ignored config entries (#43947) --- homeassistant/config_entries.py | 3 ++ tests/components/shelly/test_config_flow.py | 32 ++++++++++++++- tests/test_config_entries.py | 45 +++++++++++++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) diff --git a/homeassistant/config_entries.py b/homeassistant/config_entries.py index af82db0ffbb..c42a53b2dae 100644 --- a/homeassistant/config_entries.py +++ b/homeassistant/config_entries.py @@ -911,6 +911,9 @@ class ConfigFlow(data_entry_flow.FlowHandler): self.hass.async_create_task( self.hass.config_entries.async_reload(entry.entry_id) ) + # Allow ignored entries to be configured on manual user step + if entry.source == SOURCE_IGNORE and self.source == SOURCE_USER: + continue raise data_entry_flow.AbortFlow("already_configured") async def async_set_unique_id( diff --git a/tests/components/shelly/test_config_flow.py b/tests/components/shelly/test_config_flow.py index 1796847bd74..75ac015b83b 100644 --- a/tests/components/shelly/test_config_flow.py +++ b/tests/components/shelly/test_config_flow.py @@ -5,7 +5,7 @@ import aiohttp import aioshelly import pytest -from homeassistant import config_entries, setup +from homeassistant import config_entries, data_entry_flow, setup from homeassistant.components.shelly.const import DOMAIN from tests.async_mock import AsyncMock, Mock, patch @@ -231,6 +231,36 @@ async def test_form_already_configured(hass): assert entry.data["host"] == "1.1.1.1" +async def test_user_setup_ignored_device(hass): + """Test user can successfully setup an ignored device.""" + await setup.async_setup_component(hass, "persistent_notification", {}) + entry = MockConfigEntry( + domain="shelly", + unique_id="test-mac", + data={"host": "0.0.0.0"}, + source=config_entries.SOURCE_IGNORE, + ) + entry.add_to_hass(hass) + + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": config_entries.SOURCE_USER} + ) + + with patch( + "aioshelly.get_info", + return_value={"mac": "test-mac", "type": "SHSW-1", "auth": False}, + ): + result2 = await hass.config_entries.flow.async_configure( + result["flow_id"], + {"host": "1.1.1.1"}, + ) + + assert result2["type"] == data_entry_flow.RESULT_TYPE_FORM + + # Test config entry got updated with latest IP + assert entry.data["host"] == "1.1.1.1" + + async def test_form_firmware_unsupported(hass): """Test we abort if device firmware is unsupported.""" result = await hass.config_entries.flow.async_init( diff --git a/tests/test_config_entries.py b/tests/test_config_entries.py index 59e1b0754c0..0be89af4810 100644 --- a/tests/test_config_entries.py +++ b/tests/test_config_entries.py @@ -1539,6 +1539,51 @@ async def test_unique_id_ignore(hass, manager): assert entry.unique_id == "mock-unique-id" +async def test_manual_add_overrides_ignored_entry(hass, manager): + """Test that we can ignore manually add entry, overriding ignored entry.""" + hass.config.components.add("comp") + entry = MockConfigEntry( + domain="comp", + data={"additional": "data", "host": "0.0.0.0"}, + unique_id="mock-unique-id", + state=config_entries.ENTRY_STATE_LOADED, + source=config_entries.SOURCE_IGNORE, + ) + entry.add_to_hass(hass) + + mock_integration( + hass, + MockModule("comp"), + ) + mock_entity_platform(hass, "config_flow.comp", None) + + class TestFlow(config_entries.ConfigFlow): + """Test flow.""" + + VERSION = 1 + + async def async_step_user(self, user_input=None): + """Test user step.""" + await self.async_set_unique_id("mock-unique-id") + self._abort_if_unique_id_configured( + updates={"host": "1.1.1.1"}, reload_on_update=False + ) + return self.async_show_form(step_id="step2") + + with patch.dict(config_entries.HANDLERS, {"comp": TestFlow}), patch( + "homeassistant.config_entries.ConfigEntries.async_reload" + ) as async_reload: + result = await manager.flow.async_init( + "comp", context={"source": config_entries.SOURCE_USER} + ) + await hass.async_block_till_done() + + assert result["type"] == data_entry_flow.RESULT_TYPE_FORM + assert entry.data["host"] == "1.1.1.1" + assert entry.data["additional"] == "data" + assert len(async_reload.mock_calls) == 0 + + async def test_unignore_step_form(hass, manager): """Test that we can ignore flows that are in progress and have a unique ID, then rediscover them.""" async_setup_entry = AsyncMock(return_value=True)