diff --git a/homeassistant/config_entries.py b/homeassistant/config_entries.py index 6fb5595dac48..793e8be00456 100644 --- a/homeassistant/config_entries.py +++ b/homeassistant/config_entries.py @@ -817,13 +817,19 @@ class ConfigFlow(data_entry_flow.FlowHandler): raise data_entry_flow.UnknownHandler @callback - def _abort_if_unique_id_configured(self) -> None: + def _abort_if_unique_id_configured(self, updates: Dict[Any, Any] = None) -> None: """Abort if the unique ID is already configured.""" + assert self.hass if self.unique_id is None: return - if self.unique_id in self._async_current_ids(): - raise data_entry_flow.AbortFlow("already_configured") + for entry in self._async_current_entries(): + if entry.unique_id == self.unique_id: + if updates is not None and not updates.items() <= entry.data.items(): + self.hass.config_entries.async_update_entry( + entry, data={**entry.data, **updates} + ) + raise data_entry_flow.AbortFlow("already_configured") async def async_set_unique_id( self, unique_id: str, *, raise_on_progress: bool = True diff --git a/tests/test_config_entries.py b/tests/test_config_entries.py index d2519a495e26..da3fb7406949 100644 --- a/tests/test_config_entries.py +++ b/tests/test_config_entries.py @@ -1080,6 +1080,77 @@ async def test_unique_id_existing_entry(hass, manager): assert len(async_remove_entry.mock_calls) == 1 +async def test_unique_id_update_existing_entry(hass, manager): + """Test that we update an entry if there already is an entry with unique ID.""" + hass.config.components.add("comp") + entry = MockConfigEntry( + domain="comp", + data={"additional": "data", "host": "0.0.0.0"}, + unique_id="mock-unique-id", + ) + entry.add_to_hass(hass) + + mock_integration( + hass, MockModule("comp"), + ) + mock_entity_platform(hass, "config_flow.comp", None) + + class TestFlow(config_entries.ConfigFlow): + + VERSION = 1 + + async def async_step_user(self, user_input=None): + await self.async_set_unique_id("mock-unique-id") + await self._abort_if_unique_id_configured(updates={"host": "1.1.1.1"}) + + with patch.dict(config_entries.HANDLERS, {"comp": TestFlow}): + result = await manager.flow.async_init( + "comp", context={"source": config_entries.SOURCE_USER} + ) + + assert result["type"] == "abort" + assert result["reason"] == "already_configured" + assert entry.data["host"] == "1.1.1.1" + assert entry.data["additional"] == "data" + + +async def test_unique_id_not_update_existing_entry(hass, manager): + """Test that we do not update an entry if existing entry has the data.""" + hass.config.components.add("comp") + entry = MockConfigEntry( + domain="comp", + data={"additional": "data", "host": "0.0.0.0"}, + unique_id="mock-unique-id", + ) + entry.add_to_hass(hass) + + mock_integration( + hass, MockModule("comp"), + ) + mock_entity_platform(hass, "config_flow.comp", None) + + class TestFlow(config_entries.ConfigFlow): + + VERSION = 1 + + async def async_step_user(self, user_input=None): + await self.async_set_unique_id("mock-unique-id") + await self._abort_if_unique_id_configured(updates={"host": "0.0.0.0"}) + + with patch.dict(config_entries.HANDLERS, {"comp": TestFlow}), patch( + "homeassistant.config_entries.ConfigEntries.async_update_entry" + ) as async_update_entry: + result = await manager.flow.async_init( + "comp", context={"source": config_entries.SOURCE_USER} + ) + + assert result["type"] == "abort" + assert result["reason"] == "already_configured" + assert entry.data["host"] == "0.0.0.0" + assert entry.data["additional"] == "data" + assert len(async_update_entry.mock_calls) == 0 + + async def test_unique_id_in_progress(hass, manager): """Test that we abort if there is already a flow in progress with same unique id.""" mock_integration(hass, MockModule("comp"))