diff --git a/homeassistant/components/doorbird/config_flow.py b/homeassistant/components/doorbird/config_flow.py index aa712a63ed0..52f94116344 100644 --- a/homeassistant/components/doorbird/config_flow.py +++ b/homeassistant/components/doorbird/config_flow.py @@ -68,17 +68,8 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): """Handle the initial step.""" errors = {} if user_input is not None: - try: - info = await validate_input(self.hass, user_input) - except CannotConnect: - errors["base"] = "cannot_connect" - except InvalidAuth: - errors["base"] = "invalid_auth" - except Exception: # pylint: disable=broad-except - _LOGGER.exception("Unexpected exception") - errors["base"] = "unknown" - - if "base" not in errors: + info, errors = await self._async_validate_or_error(user_input) + if not errors: await self.async_set_unique_id(info["mac_addr"]) self._abort_if_unique_id_configured() return self.async_create_entry(title=info["title"], data=user_input) @@ -119,8 +110,31 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): async def async_step_import(self, user_input): """Handle import.""" + if user_input: + info, errors = await self._async_validate_or_error(user_input) + if not errors: + await self.async_set_unique_id( + info["mac_addr"], raise_on_progress=False + ) + self._abort_if_unique_id_configured() + return self.async_create_entry(title=info["title"], data=user_input) return await self.async_step_user(user_input) + async def _async_validate_or_error(self, user_input): + """Validate doorbird or error.""" + errors = {} + info = {} + try: + info = await validate_input(self.hass, user_input) + except CannotConnect: + errors["base"] = "cannot_connect" + except InvalidAuth: + errors["base"] = "invalid_auth" + except Exception: # pylint: disable=broad-except + _LOGGER.exception("Unexpected exception") + errors["base"] = "unknown" + return info, errors + @staticmethod @callback def async_get_options_flow(config_entry): diff --git a/tests/components/doorbird/test_config_flow.py b/tests/components/doorbird/test_config_flow.py index f911787c1c3..8b49f87bd0b 100644 --- a/tests/components/doorbird/test_config_flow.py +++ b/tests/components/doorbird/test_config_flow.py @@ -127,6 +127,73 @@ async def test_form_import(hass): assert len(mock_setup_entry.mock_calls) == 1 +async def test_form_import_with_zeroconf_already_discovered(hass): + """Test we get the form with import source.""" + await hass.async_add_executor_job( + init_recorder_component, hass + ) # force in memory db + + await setup.async_setup_component(hass, "persistent_notification", {}) + + # Running the zeroconf init will make the unique id + # in progress + zero_conf = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": config_entries.SOURCE_ZEROCONF}, + data={ + "properties": {"macaddress": "1CCAE3DOORBIRD"}, + "name": "Doorstation - abc123._axis-video._tcp.local.", + "host": "192.168.1.5", + }, + ) + assert zero_conf["type"] == data_entry_flow.RESULT_TYPE_FORM + assert zero_conf["step_id"] == "user" + assert zero_conf["errors"] == {} + + import_config = VALID_CONFIG.copy() + import_config[CONF_EVENTS] = ["event1", "event2", "event3"] + import_config[CONF_TOKEN] = "imported_token" + import_config[ + CONF_CUSTOM_URL + ] = "http://legacy.custom.url/should/only/come/in/from/yaml" + + doorbirdapi = _get_mock_doorbirdapi_return_values( + ready=[True], info={"WIFI_MAC_ADDR": "1CCAE3DOORBIRD"} + ) + with patch( + "homeassistant.components.doorbird.config_flow.DoorBird", + return_value=doorbirdapi, + ), patch("homeassistant.components.logbook.async_setup", return_value=True), patch( + "homeassistant.components.doorbird.async_setup", return_value=True + ) as mock_setup, patch( + "homeassistant.components.doorbird.async_setup_entry", return_value=True, + ) as mock_setup_entry: + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": config_entries.SOURCE_IMPORT}, + data=import_config, + ) + + assert result["type"] == "create_entry" + assert result["title"] == "1.2.3.4" + assert result["data"] == { + "host": "1.2.3.4", + "name": "mydoorbird", + "password": "password", + "username": "friend", + "events": ["event1", "event2", "event3"], + "token": "imported_token", + # This will go away once we convert to cloud hooks + "hass_url_override": "http://legacy.custom.url/should/only/come/in/from/yaml", + } + # It is not possible to import options at this time + # so they end up in the config entry data and are + # used a fallback when they are not in options + await hass.async_block_till_done() + assert len(mock_setup.mock_calls) == 1 + assert len(mock_setup_entry.mock_calls) == 1 + + async def test_form_zeroconf_wrong_oui(hass): """Test we abort when we get the wrong OUI via zeroconf.""" await hass.async_add_executor_job(