diff --git a/homeassistant/components/rainmachine/.translations/en.json b/homeassistant/components/rainmachine/.translations/en.json index 54b67066f2b..4ad5bfd7c0d 100644 --- a/homeassistant/components/rainmachine/.translations/en.json +++ b/homeassistant/components/rainmachine/.translations/en.json @@ -1,5 +1,8 @@ { "config": { + "abort": { + "already_configured": "This RainMachine controller is already configured." + }, "error": { "identifier_exists": "Account already registered", "invalid_credentials": "Invalid credentials" diff --git a/homeassistant/components/rainmachine/config_flow.py b/homeassistant/components/rainmachine/config_flow.py index 4753335da78..4b93fc64159 100644 --- a/homeassistant/components/rainmachine/config_flow.py +++ b/homeassistant/components/rainmachine/config_flow.py @@ -1,7 +1,4 @@ """Config flow to configure the RainMachine component.""" - -from collections import OrderedDict - from regenmaschine import login from regenmaschine.errors import RainMachineError import voluptuous as vol @@ -29,8 +26,7 @@ def configured_instances(hass): ) -@config_entries.HANDLERS.register(DOMAIN) -class RainMachineFlowHandler(config_entries.ConfigFlow): +class RainMachineFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): """Handle a RainMachine config flow.""" VERSION = 1 @@ -38,16 +34,19 @@ class RainMachineFlowHandler(config_entries.ConfigFlow): def __init__(self): """Initialize the config flow.""" - self.data_schema = OrderedDict() - self.data_schema[vol.Required(CONF_IP_ADDRESS)] = str - self.data_schema[vol.Required(CONF_PASSWORD)] = str - self.data_schema[vol.Optional(CONF_PORT, default=DEFAULT_PORT)] = int + self.data_schema = vol.Schema( + { + vol.Required(CONF_IP_ADDRESS): str, + vol.Required(CONF_PASSWORD): str, + vol.Optional(CONF_PORT, default=DEFAULT_PORT): int, + } + ) async def _show_form(self, errors=None): """Show the form to the user.""" return self.async_show_form( step_id="user", - data_schema=vol.Schema(self.data_schema), + data_schema=self.data_schema, errors=errors if errors else {}, ) @@ -57,12 +56,11 @@ class RainMachineFlowHandler(config_entries.ConfigFlow): async def async_step_user(self, user_input=None): """Handle the start of the config flow.""" - if not user_input: return await self._show_form() - if user_input[CONF_IP_ADDRESS] in configured_instances(self.hass): - return await self._show_form({CONF_IP_ADDRESS: "identifier_exists"}) + await self.async_set_unique_id(user_input[CONF_IP_ADDRESS]) + self._abort_if_unique_id_configured() websession = aiohttp_client.async_get_clientsession(self.hass) diff --git a/homeassistant/components/rainmachine/strings.json b/homeassistant/components/rainmachine/strings.json index 6e26192ec82..7195cce2e31 100644 --- a/homeassistant/components/rainmachine/strings.json +++ b/homeassistant/components/rainmachine/strings.json @@ -14,6 +14,9 @@ "error": { "identifier_exists": "Account already registered", "invalid_credentials": "Invalid credentials" + }, + "abort": { + "already_configured": "This RainMachine controller is already configured." } } } diff --git a/tests/components/rainmachine/test_config_flow.py b/tests/components/rainmachine/test_config_flow.py index 9e43f647301..435e8fb33b5 100644 --- a/tests/components/rainmachine/test_config_flow.py +++ b/tests/components/rainmachine/test_config_flow.py @@ -5,6 +5,7 @@ from regenmaschine.errors import RainMachineError from homeassistant import data_entry_flow from homeassistant.components.rainmachine import DOMAIN, config_flow +from homeassistant.config_entries import SOURCE_USER from homeassistant.const import ( CONF_IP_ADDRESS, CONF_PASSWORD, @@ -25,12 +26,33 @@ async def test_duplicate_error(hass): CONF_SSL: True, } - MockConfigEntry(domain=DOMAIN, data=conf).add_to_hass(hass) + MockConfigEntry(domain=DOMAIN, unique_id="192.168.1.100", data=conf).add_to_hass( + hass + ) flow = config_flow.RainMachineFlowHandler() flow.hass = hass - result = await flow.async_step_user(user_input=conf) - assert result["errors"] == {CONF_IP_ADDRESS: "identifier_exists"} + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": SOURCE_USER}, data=conf + ) + assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT + assert result["reason"] == "already_configured" + + +async def test_get_configured_instances(hass): + """Test retrieving all configured instances.""" + conf = { + CONF_IP_ADDRESS: "192.168.1.100", + CONF_PASSWORD: "password", + CONF_PORT: 8080, + CONF_SSL: True, + } + + MockConfigEntry(domain=DOMAIN, unique_id="192.168.1.100", data=conf).add_to_hass( + hass + ) + + assert len(config_flow.configured_instances(hass)) == 1 async def test_invalid_password(hass): @@ -44,6 +66,7 @@ async def test_invalid_password(hass): flow = config_flow.RainMachineFlowHandler() flow.hass = hass + flow.context = {"source": SOURCE_USER} with patch( "homeassistant.components.rainmachine.config_flow.login", @@ -57,6 +80,7 @@ async def test_show_form(hass): """Test that the form is served with no input.""" flow = config_flow.RainMachineFlowHandler() flow.hass = hass + flow.context = {"source": SOURCE_USER} result = await flow.async_step_user(user_input=None) @@ -75,6 +99,7 @@ async def test_step_import(hass): flow = config_flow.RainMachineFlowHandler() flow.hass = hass + flow.context = {"source": SOURCE_USER} with patch( "homeassistant.components.rainmachine.config_flow.login", @@ -104,6 +129,7 @@ async def test_step_user(hass): flow = config_flow.RainMachineFlowHandler() flow.hass = hass + flow.context = {"source": SOURCE_USER} with patch( "homeassistant.components.rainmachine.config_flow.login",