From ca67fd9faaef454ee0e455417e8effc3b35c20d4 Mon Sep 17 00:00:00 2001 From: Raman Gupta <7243222+raman325@users.noreply.github.com> Date: Thu, 16 Apr 2020 17:53:34 -0400 Subject: [PATCH] Skip ignored hosts when checking existing config entries in config flow (#34280) --- homeassistant/components/vizio/config_flow.py | 20 ++++- tests/components/vizio/test_config_flow.py | 73 ++++++++++++++++++- 2 files changed, 91 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/vizio/config_flow.py b/homeassistant/components/vizio/config_flow.py index 51f00ad98bbf..eac6df85f437 100644 --- a/homeassistant/components/vizio/config_flow.py +++ b/homeassistant/components/vizio/config_flow.py @@ -8,7 +8,12 @@ import voluptuous as vol from homeassistant import config_entries from homeassistant.components.media_player import DEVICE_CLASS_SPEAKER, DEVICE_CLASS_TV -from homeassistant.config_entries import SOURCE_IMPORT, SOURCE_ZEROCONF, ConfigEntry +from homeassistant.config_entries import ( + SOURCE_IGNORE, + SOURCE_IMPORT, + SOURCE_ZEROCONF, + ConfigEntry, +) from homeassistant.const import ( CONF_ACCESS_TOKEN, CONF_DEVICE_CLASS, @@ -198,8 +203,13 @@ class VizioConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): # Check if new config entry matches any existing config entries for entry in self.hass.config_entries.async_entries(DOMAIN): + # If source is ignore bypass host and name check and continue through loop + if entry.source == SOURCE_IGNORE: + continue + if _host_is_same(entry.data[CONF_HOST], user_input[CONF_HOST]): errors[CONF_HOST] = "host_exists" + if entry.data[CONF_NAME] == user_input[CONF_NAME]: errors[CONF_NAME] = "name_exists" @@ -270,6 +280,10 @@ class VizioConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): """Import a config entry from configuration.yaml.""" # Check if new config entry matches any existing config entries for entry in self.hass.config_entries.async_entries(DOMAIN): + # If source is ignore bypass host check and continue through loop + if entry.source == SOURCE_IGNORE: + continue + if _host_is_same(entry.data[CONF_HOST], import_config[CONF_HOST]): updated_options = {} updated_data = {} @@ -334,6 +348,10 @@ class VizioConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): # Check if new config entry matches any existing config entries and abort if so for entry in self.hass.config_entries.async_entries(DOMAIN): + # If source is ignore bypass host check and continue through loop + if entry.source == SOURCE_IGNORE: + continue + if _host_is_same(entry.data[CONF_HOST], discovery_info[CONF_HOST]): return self.async_abort(reason="already_setup") diff --git a/tests/components/vizio/test_config_flow.py b/tests/components/vizio/test_config_flow.py index b5b10534759f..3cb22a225417 100644 --- a/tests/components/vizio/test_config_flow.py +++ b/tests/components/vizio/test_config_flow.py @@ -17,7 +17,12 @@ from homeassistant.components.vizio.const import ( DOMAIN, VIZIO_SCHEMA, ) -from homeassistant.config_entries import SOURCE_IMPORT, SOURCE_USER, SOURCE_ZEROCONF +from homeassistant.config_entries import ( + SOURCE_IGNORE, + SOURCE_IMPORT, + SOURCE_USER, + SOURCE_ZEROCONF, +) from homeassistant.const import ( CONF_ACCESS_TOKEN, CONF_DEVICE_CLASS, @@ -383,6 +388,26 @@ async def test_user_invalid_pin( assert result["errors"] == {CONF_PIN: "complete_pairing_failed"} +async def test_user_ignore( + hass: HomeAssistantType, + vizio_connect: pytest.fixture, + vizio_bypass_setup: pytest.fixture, +) -> None: + """Test user config flow doesn't throw an error when there's an existing ignored source.""" + entry = MockConfigEntry( + domain=DOMAIN, + data=MOCK_SPEAKER_CONFIG, + options={CONF_VOLUME_STEP: VOLUME_STEP}, + source=SOURCE_IGNORE, + ) + entry.add_to_hass(hass) + + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": SOURCE_USER}, data=MOCK_SPEAKER_CONFIG + ) + assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY + + async def test_import_flow_minimum_fields( hass: HomeAssistantType, vizio_connect: pytest.fixture, @@ -679,6 +704,29 @@ async def test_import_error( assert len(vizio_log_list) == 1 +async def test_import_ignore( + hass: HomeAssistantType, + vizio_connect: pytest.fixture, + vizio_bypass_setup: pytest.fixture, +) -> None: + """Test import config flow doesn't throw an error when there's an existing ignored source.""" + entry = MockConfigEntry( + domain=DOMAIN, + data=MOCK_SPEAKER_CONFIG, + options={CONF_VOLUME_STEP: VOLUME_STEP}, + source=SOURCE_IGNORE, + ) + entry.add_to_hass(hass) + + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": SOURCE_IMPORT}, + data=vol.Schema(VIZIO_SCHEMA)(MOCK_SPEAKER_CONFIG), + ) + + assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY + + async def test_zeroconf_flow( hass: HomeAssistantType, vizio_connect: pytest.fixture, @@ -756,3 +804,26 @@ async def test_zeroconf_dupe_fail( # Flow should abort because device is already setup assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT assert result["reason"] == "already_in_progress" + + +async def test_zeroconf_ignore( + hass: HomeAssistantType, + vizio_connect: pytest.fixture, + vizio_bypass_setup: pytest.fixture, + vizio_guess_device_type: pytest.fixture, +) -> None: + """Test zeroconf discovery doesn't throw an error when there's an existing ignored source.""" + entry = MockConfigEntry( + domain=DOMAIN, + data=MOCK_SPEAKER_CONFIG, + options={CONF_VOLUME_STEP: VOLUME_STEP}, + source=SOURCE_IGNORE, + ) + entry.add_to_hass(hass) + + discovery_info = MOCK_ZEROCONF_SERVICE_INFO.copy() + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": SOURCE_ZEROCONF}, data=discovery_info + ) + + assert result["type"] == data_entry_flow.RESULT_TYPE_FORM