From abf065ed7672f90f92aa183fd3122d4ae75ce680 Mon Sep 17 00:00:00 2001 From: Diogo Gomes Date: Wed, 16 Aug 2023 11:56:47 +0100 Subject: [PATCH] Fix checks for duplicated config entries in IPMA (#98319) * fix unique_id * old unique id detection * update tests * match entry not unique_id * address review --- homeassistant/components/ipma/config_flow.py | 14 +- homeassistant/components/ipma/strings.json | 4 +- tests/components/ipma/conftest.py | 36 +++++ tests/components/ipma/test_config_flow.py | 145 ++++++------------- 4 files changed, 93 insertions(+), 106 deletions(-) create mode 100644 tests/components/ipma/conftest.py diff --git a/homeassistant/components/ipma/config_flow.py b/homeassistant/components/ipma/config_flow.py index 9434aed3097..d7b8b8cc003 100644 --- a/homeassistant/components/ipma/config_flow.py +++ b/homeassistant/components/ipma/config_flow.py @@ -22,14 +22,14 @@ class IpmaFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): self._errors = {} if user_input is not None: - if user_input[CONF_NAME] not in self.hass.config_entries.async_entries( - DOMAIN - ): - return self.async_create_entry( - title=user_input[CONF_NAME], data=user_input - ) + self._async_abort_entries_match( + { + CONF_LATITUDE: user_input[CONF_LATITUDE], + CONF_LONGITUDE: user_input[CONF_LONGITUDE], + } + ) - self._errors[CONF_NAME] = "name_exists" + return self.async_create_entry(title=user_input[CONF_NAME], data=user_input) # default location is set hass configuration return await self._show_config_form( diff --git a/homeassistant/components/ipma/strings.json b/homeassistant/components/ipma/strings.json index b9f50c66f9e..012550d8bd1 100644 --- a/homeassistant/components/ipma/strings.json +++ b/homeassistant/components/ipma/strings.json @@ -12,7 +12,9 @@ } } }, - "error": { "name_exists": "Name already exists" } + "abort": { + "already_configured": "[%key:common::config_flow::abort::already_configured_location%]" + } }, "system_health": { "info": { diff --git a/tests/components/ipma/conftest.py b/tests/components/ipma/conftest.py new file mode 100644 index 00000000000..dda0e69d118 --- /dev/null +++ b/tests/components/ipma/conftest.py @@ -0,0 +1,36 @@ +"""Define test fixtures for IPMA.""" + +import pytest + +from homeassistant.components.ipma import DOMAIN +from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE, CONF_NAME + +from tests.common import MockConfigEntry + + +@pytest.fixture(name="config_entry") +def config_entry_fixture(hass, config): + """Define a config entry fixture.""" + entry = MockConfigEntry( + domain=DOMAIN, + data=config, + ) + entry.add_to_hass(hass) + return entry + + +@pytest.fixture(name="config") +def config_fixture(): + """Define a config entry data fixture.""" + return { + CONF_NAME: "Home", + CONF_LATITUDE: 0, + CONF_LONGITUDE: 0, + } + + +@pytest.fixture(name="setup_config_entry") +async def setup_config_entry_fixture(hass, config_entry): + """Define a fixture to set up ipma.""" + assert await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() diff --git a/tests/components/ipma/test_config_flow.py b/tests/components/ipma/test_config_flow.py index 5bb1d8b8364..18b68a5a44d 100644 --- a/tests/components/ipma/test_config_flow.py +++ b/tests/components/ipma/test_config_flow.py @@ -1,116 +1,65 @@ """Tests for IPMA config flow.""" -from unittest.mock import Mock, patch +from unittest.mock import patch -from homeassistant.components.ipma import config_flow -from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE +import pytest + +from homeassistant import config_entries, data_entry_flow +from homeassistant.components.ipma.const import DOMAIN +from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE, CONF_NAME from homeassistant.core import HomeAssistant -async def test_show_config_form() -> None: - """Test show configuration form.""" - hass = Mock() - flow = config_flow.IpmaFlowHandler() - flow.hass = hass +@pytest.fixture(name="ipma_setup", autouse=True) +def ipma_setup_fixture(request): + """Patch ipma setup entry.""" + with patch("homeassistant.components.ipma.async_setup_entry", return_value=True): + yield - result = await flow._show_config_form() + +async def test_config_flow(hass: HomeAssistant) -> None: + """Test configuration form.""" + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": config_entries.SOURCE_USER} + ) assert result["type"] == "form" assert result["step_id"] == "user" + test_data = { + CONF_LONGITUDE: 0, + CONF_LATITUDE: 0, + } -async def test_show_config_form_default_values() -> None: - """Test show configuration form.""" - hass = Mock() - flow = config_flow.IpmaFlowHandler() - flow.hass = hass + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + test_data, + ) - result = await flow._show_config_form(name="test", latitude="0", longitude="0") - - assert result["type"] == "form" - assert result["step_id"] == "user" + assert result["type"] is data_entry_flow.FlowResultType.CREATE_ENTRY + assert result["title"] == "Home" + assert result["data"] == { + CONF_NAME: "Home", + CONF_LONGITUDE: 0, + CONF_LATITUDE: 0, + } -async def test_flow_with_home_location(hass: HomeAssistant) -> None: - """Test config flow . +async def test_flow_entry_already_exists(hass: HomeAssistant, config_entry) -> None: + """Test user input for config_entry that already exists. - Tests the flow when a default location is configured - then it should return a form with default values + Test when the form should show when user puts existing location + in the config gui. Then the form should show with error. """ - flow = config_flow.IpmaFlowHandler() - flow.hass = hass + test_data = { + CONF_NAME: "Home", + CONF_LONGITUDE: 0, + CONF_LATITUDE: 0, + } - hass.config.location_name = "Home" - hass.config.latitude = 1 - hass.config.longitude = 1 + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": config_entries.SOURCE_USER}, data=test_data + ) + await hass.async_block_till_done() - result = await flow.async_step_user() - assert result["type"] == "form" - assert result["step_id"] == "user" - - -async def test_flow_show_form() -> None: - """Test show form scenarios first time. - - Test when the form should show when no configurations exists - """ - hass = Mock() - flow = config_flow.IpmaFlowHandler() - flow.hass = hass - - with patch( - "homeassistant.components.ipma.config_flow.IpmaFlowHandler._show_config_form" - ) as config_form: - await flow.async_step_user() - assert len(config_form.mock_calls) == 1 - - -async def test_flow_entry_created_from_user_input() -> None: - """Test that create data from user input. - - Test when the form should show when no configurations exists - """ - hass = Mock() - flow = config_flow.IpmaFlowHandler() - flow.hass = hass - - test_data = {"name": "home", CONF_LONGITUDE: "0", CONF_LATITUDE: "0"} - - # Test that entry created when user_input name not exists - with patch( - "homeassistant.components.ipma.config_flow.IpmaFlowHandler._show_config_form" - ) as config_form, patch.object( - flow.hass.config_entries, - "async_entries", - return_value=[], - ) as config_entries: - result = await flow.async_step_user(user_input=test_data) - - assert result["type"] == "create_entry" - assert result["data"] == test_data - assert len(config_entries.mock_calls) == 1 - assert not config_form.mock_calls - - -async def test_flow_entry_config_entry_already_exists() -> None: - """Test that create data from user input and config_entry already exists. - - Test when the form should show when user puts existing name - in the config gui. Then the form should show with error - """ - hass = Mock() - flow = config_flow.IpmaFlowHandler() - flow.hass = hass - - test_data = {"name": "home", CONF_LONGITUDE: "0", CONF_LATITUDE: "0"} - - # Test that entry created when user_input name not exists - with patch( - "homeassistant.components.ipma.config_flow.IpmaFlowHandler._show_config_form" - ) as config_form, patch.object( - flow.hass.config_entries, "async_entries", return_value={"home": test_data} - ) as config_entries: - await flow.async_step_user(user_input=test_data) - - assert len(config_form.mock_calls) == 1 - assert len(config_entries.mock_calls) == 1 - assert len(flow._errors) == 1 + assert result["type"] == "abort" + assert result["reason"] == "already_configured"