From d35f06ac156603b7a77aa5b96f52742ef047d630 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Sat, 19 Sep 2020 22:10:01 +0200 Subject: [PATCH 01/11] Get option flow defaults from yaml for non configured MQTT options (#40177) --- homeassistant/components/mqtt/__init__.py | 2 +- homeassistant/components/mqtt/config_flow.py | 41 +++++++++++++------- homeassistant/components/mqtt/const.py | 2 + 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/homeassistant/components/mqtt/__init__.py b/homeassistant/components/mqtt/__init__.py index d9bf1bbadfa..bafbead96d6 100644 --- a/homeassistant/components/mqtt/__init__.py +++ b/homeassistant/components/mqtt/__init__.py @@ -60,6 +60,7 @@ from .const import ( CONF_RETAIN, CONF_STATE_TOPIC, CONF_WILL_MESSAGE, + DATA_MQTT_CONFIG, DEFAULT_BIRTH, DEFAULT_DISCOVERY, DEFAULT_PAYLOAD_AVAILABLE, @@ -88,7 +89,6 @@ _LOGGER = logging.getLogger(__name__) DOMAIN = "mqtt" DATA_MQTT = "mqtt" -DATA_MQTT_CONFIG = "mqtt_config" SERVICE_PUBLISH = "publish" SERVICE_DUMP = "dump" diff --git a/homeassistant/components/mqtt/config_flow.py b/homeassistant/components/mqtt/config_flow.py index 8b1c350323c..5c4016437a6 100644 --- a/homeassistant/components/mqtt/config_flow.py +++ b/homeassistant/components/mqtt/config_flow.py @@ -24,6 +24,7 @@ from .const import ( CONF_BROKER, CONF_DISCOVERY, CONF_WILL_MESSAGE, + DATA_MQTT_CONFIG, DEFAULT_BIRTH, DEFAULT_DISCOVERY, DEFAULT_WILL, @@ -162,6 +163,7 @@ class MQTTOptionsFlowHandler(config_entries.OptionsFlow): """Manage the MQTT options.""" errors = {} current_config = self.config_entry.data + yaml_config = self.hass.data.get(DATA_MQTT_CONFIG, {}) if user_input is not None: can_connect = await self.hass.async_add_executor_job( try_connection, @@ -178,20 +180,22 @@ class MQTTOptionsFlowHandler(config_entries.OptionsFlow): errors["base"] = "cannot_connect" fields = OrderedDict() - fields[vol.Required(CONF_BROKER, default=current_config[CONF_BROKER])] = str - fields[vol.Required(CONF_PORT, default=current_config[CONF_PORT])] = vol.Coerce( - int - ) + current_broker = current_config.get(CONF_BROKER, yaml_config.get(CONF_BROKER)) + current_port = current_config.get(CONF_PORT, yaml_config.get(CONF_PORT)) + current_user = current_config.get(CONF_USERNAME, yaml_config.get(CONF_USERNAME)) + current_pass = current_config.get(CONF_PASSWORD, yaml_config.get(CONF_PASSWORD)) + fields[vol.Required(CONF_BROKER, default=current_broker)] = str + fields[vol.Required(CONF_PORT, default=current_port)] = vol.Coerce(int) fields[ vol.Optional( CONF_USERNAME, - description={"suggested_value": current_config.get(CONF_USERNAME)}, + description={"suggested_value": current_user}, ) ] = str fields[ vol.Optional( CONF_PASSWORD, - description={"suggested_value": current_config.get(CONF_PASSWORD)}, + description={"suggested_value": current_pass}, ) ] = str @@ -205,6 +209,7 @@ class MQTTOptionsFlowHandler(config_entries.OptionsFlow): """Manage the MQTT options.""" errors = {} current_config = self.config_entry.data + yaml_config = self.hass.data.get(DATA_MQTT_CONFIG, {}) options_config = {} if user_input is not None: bad_birth = False @@ -253,16 +258,24 @@ class MQTTOptionsFlowHandler(config_entries.OptionsFlow): ) return self.async_create_entry(title="", data=None) - birth = {**DEFAULT_BIRTH, **current_config.get(CONF_BIRTH_MESSAGE, {})} - will = {**DEFAULT_WILL, **current_config.get(CONF_WILL_MESSAGE, {})} + birth = { + **DEFAULT_BIRTH, + **current_config.get( + CONF_BIRTH_MESSAGE, yaml_config.get(CONF_BIRTH_MESSAGE, {}) + ), + } + will = { + **DEFAULT_WILL, + **current_config.get( + CONF_WILL_MESSAGE, yaml_config.get(CONF_WILL_MESSAGE, {}) + ), + } + discovery = current_config.get( + CONF_DISCOVERY, yaml_config.get(CONF_DISCOVERY, DEFAULT_DISCOVERY) + ) fields = OrderedDict() - fields[ - vol.Optional( - CONF_DISCOVERY, - default=current_config.get(CONF_DISCOVERY, DEFAULT_DISCOVERY), - ) - ] = bool + fields[vol.Optional(CONF_DISCOVERY, default=discovery)] = bool # Birth message is disabled if CONF_BIRTH_MESSAGE = {} fields[ diff --git a/homeassistant/components/mqtt/const.py b/homeassistant/components/mqtt/const.py index 7ea6d9d348b..5ab3f756311 100644 --- a/homeassistant/components/mqtt/const.py +++ b/homeassistant/components/mqtt/const.py @@ -17,6 +17,8 @@ CONF_RETAIN = ATTR_RETAIN CONF_STATE_TOPIC = "state_topic" CONF_WILL_MESSAGE = "will_message" +DATA_MQTT_CONFIG = "mqtt_config" + DEFAULT_PREFIX = "homeassistant" DEFAULT_BIRTH_WILL_TOPIC = DEFAULT_PREFIX + "/status" DEFAULT_DISCOVERY = False From 57b7ed6a07b1adb4c520181e7717da5597f32973 Mon Sep 17 00:00:00 2001 From: jan iversen Date: Sat, 19 Sep 2020 12:14:51 +0200 Subject: [PATCH 02/11] Correct modbus switch to return correct coil (#40190) --- homeassistant/components/modbus/switch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/modbus/switch.py b/homeassistant/components/modbus/switch.py index 8037d926ef1..c238e105659 100644 --- a/homeassistant/components/modbus/switch.py +++ b/homeassistant/components/modbus/switch.py @@ -171,7 +171,7 @@ class ModbusCoilSwitch(ToggleEntity, RestoreEntity): return self._available = True - return bool(result.bits[0]) + return bool(result.bits[coil]) def _write_coil(self, coil, value): """Write coil using the Modbus hub slave.""" From 1eb8035122c170beb0d144980b5688e35ab54984 Mon Sep 17 00:00:00 2001 From: Felipe Martins Diel <41558831+felipediel@users.noreply.github.com> Date: Fri, 18 Sep 2020 10:29:26 -0300 Subject: [PATCH 03/11] Handle an unsupported device in the Broadlink config flow (#40242) --- .../components/broadlink/config_flow.py | 16 ++++++++- .../components/broadlink/strings.json | 1 + .../components/broadlink/translations/en.json | 1 + tests/components/broadlink/__init__.py | 10 ++++++ .../components/broadlink/test_config_flow.py | 35 +++++++++++++++++++ 5 files changed, 62 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/broadlink/config_flow.py b/homeassistant/components/broadlink/config_flow.py index 284a9bffe19..4dfc80c6fe9 100644 --- a/homeassistant/components/broadlink/config_flow.py +++ b/homeassistant/components/broadlink/config_flow.py @@ -11,7 +11,7 @@ from broadlink.exceptions import ( ) import voluptuous as vol -from homeassistant import config_entries +from homeassistant import config_entries, data_entry_flow from homeassistant.const import CONF_HOST, CONF_MAC, CONF_NAME, CONF_TIMEOUT, CONF_TYPE from homeassistant.helpers import config_validation as cv @@ -20,6 +20,7 @@ from .const import ( # pylint: disable=unused-import DEFAULT_PORT, DEFAULT_TIMEOUT, DOMAIN, + DOMAINS_AND_TYPES, ) from .helpers import format_mac @@ -36,6 +37,19 @@ class BroadlinkFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): async def async_set_device(self, device, raise_on_progress=True): """Define a device for the config flow.""" + supported_types = { + device_type + for _, device_types in DOMAINS_AND_TYPES + for device_type in device_types + } + if device.type not in supported_types: + LOGGER.error( + "Unsupported device: %s. If it worked before, please open " + "an issue at https://github.com/home-assistant/core/issues", + hex(device.devtype), + ) + raise data_entry_flow.AbortFlow("not_supported") + await self.async_set_unique_id( device.mac.hex(), raise_on_progress=raise_on_progress ) diff --git a/homeassistant/components/broadlink/strings.json b/homeassistant/components/broadlink/strings.json index 44cb1801ede..d17c639469a 100644 --- a/homeassistant/components/broadlink/strings.json +++ b/homeassistant/components/broadlink/strings.json @@ -35,6 +35,7 @@ "already_in_progress": "There is already a configuration flow in progress for this device", "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", "invalid_host": "Invalid hostname or IP address", + "not_supported": "Device not supported", "unknown": "[%key:common::config_flow::error::unknown%]" }, "error": { diff --git a/homeassistant/components/broadlink/translations/en.json b/homeassistant/components/broadlink/translations/en.json index fa3feb88008..bd8dfd0c403 100644 --- a/homeassistant/components/broadlink/translations/en.json +++ b/homeassistant/components/broadlink/translations/en.json @@ -5,6 +5,7 @@ "already_in_progress": "There is already a configuration flow in progress for this device", "cannot_connect": "Failed to connect", "invalid_host": "Invalid hostname or IP address", + "not_supported": "Device not supported", "unknown": "Unexpected error" }, "error": { diff --git a/tests/components/broadlink/__init__.py b/tests/components/broadlink/__init__.py index 95a2ef97c6f..86756c922f1 100644 --- a/tests/components/broadlink/__init__.py +++ b/tests/components/broadlink/__init__.py @@ -56,6 +56,16 @@ BROADLINK_DEVICES = { 20025, 5, ), + "Kitchen": ( # Not supported. + "192.168.0.64", + "34ea34b61d2c", + "LB1", + "Broadlink", + "SmartBulb", + 0x504E, + 57, + 5, + ), } diff --git a/tests/components/broadlink/test_config_flow.py b/tests/components/broadlink/test_config_flow.py index 4089c551ff5..920ff8be1a6 100644 --- a/tests/components/broadlink/test_config_flow.py +++ b/tests/components/broadlink/test_config_flow.py @@ -172,6 +172,25 @@ async def test_flow_user_device_not_found(hass): assert result["errors"] == {"base": "cannot_connect"} +async def test_flow_user_device_not_supported(hass): + """Test we handle a device not supported in the user step.""" + device = get_device("Kitchen") + mock_api = device.get_mock_api() + + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": config_entries.SOURCE_USER} + ) + + with patch(DEVICE_DISCOVERY, return_value=[mock_api]): + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + {"host": device.host}, + ) + + assert result["type"] == "abort" + assert result["reason"] == "not_supported" + + async def test_flow_user_network_unreachable(hass): """Test we handle a network unreachable in the user step.""" result = await hass.config_entries.flow.async_init( @@ -631,6 +650,22 @@ async def test_flow_import_device_not_found(hass): assert result["reason"] == "cannot_connect" +async def test_flow_import_device_not_supported(hass): + """Test we handle a device not supported in the import step.""" + device = get_device("Kitchen") + mock_api = device.get_mock_api() + + with patch(DEVICE_DISCOVERY, return_value=[mock_api]): + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": config_entries.SOURCE_IMPORT}, + data={"host": device.host}, + ) + + assert result["type"] == "abort" + assert result["reason"] == "not_supported" + + async def test_flow_import_invalid_ip_address(hass): """Test we handle an invalid IP address in the import step.""" with patch("broadlink.discover", side_effect=OSError(errno.EINVAL, None)): From e582caccc999fa56885dca80d2267ab20755d403 Mon Sep 17 00:00:00 2001 From: On Freund Date: Fri, 18 Sep 2020 18:30:46 +0300 Subject: [PATCH 04/11] Fix Kodi discovery title (#40247) --- homeassistant/components/kodi/config_flow.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/kodi/config_flow.py b/homeassistant/components/kodi/config_flow.py index f10dcbb2d28..067ee8be476 100644 --- a/homeassistant/components/kodi/config_flow.py +++ b/homeassistant/components/kodi/config_flow.py @@ -116,6 +116,9 @@ class KodiConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): } ) + # pylint: disable=no-member # https://github.com/PyCQA/pylint/issues/3167 + self.context.update({"title_placeholders": {CONF_NAME: self._name}}) + try: await validate_http(self.hass, self._get_data()) await validate_ws(self.hass, self._get_data()) @@ -129,8 +132,6 @@ class KodiConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): _LOGGER.exception("Unexpected exception") return self.async_abort(reason="unknown") - # pylint: disable=no-member # https://github.com/PyCQA/pylint/issues/3167 - self.context.update({"title_placeholders": {CONF_NAME: self._name}}) return await self.async_step_discovery_confirm() async def async_step_discovery_confirm(self, user_input=None): From 7e6d64a24ccff7ec23cdb60c3eefb2c46daf81cd Mon Sep 17 00:00:00 2001 From: Robert Van Gorkom Date: Fri, 18 Sep 2020 08:39:12 -0700 Subject: [PATCH 05/11] Fix high CPU usage in vera integration. (#40249) --- homeassistant/components/vera/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/vera/manifest.json b/homeassistant/components/vera/manifest.json index a6afcce65b3..b41d289e6b3 100644 --- a/homeassistant/components/vera/manifest.json +++ b/homeassistant/components/vera/manifest.json @@ -3,6 +3,6 @@ "name": "Vera", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/vera", - "requirements": ["pyvera==0.3.9"], + "requirements": ["pyvera==0.3.10"], "codeowners": ["@vangorra"] } diff --git a/requirements_all.txt b/requirements_all.txt index cc83c47950f..dee5b04c41c 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1825,7 +1825,7 @@ pyuptimerobot==0.0.5 # pyuserinput==0.1.11 # homeassistant.components.vera -pyvera==0.3.9 +pyvera==0.3.10 # homeassistant.components.versasense pyversasense==0.0.6 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 84f2f0c9a64..b581c2b6597 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -854,7 +854,7 @@ pytraccar==0.9.0 pytradfri[async]==7.0.2 # homeassistant.components.vera -pyvera==0.3.9 +pyvera==0.3.10 # homeassistant.components.vesync pyvesync==1.1.0 From ab8ef1c9e1c14208daa50f453bacdb9c25b24631 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Fri, 18 Sep 2020 19:12:10 +0200 Subject: [PATCH 06/11] Updated frontend to 20200918.0 (#40253) --- homeassistant/components/frontend/manifest.json | 2 +- homeassistant/package_constraints.txt | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/frontend/manifest.json b/homeassistant/components/frontend/manifest.json index 96d2a51cb09..4368bff8d0f 100644 --- a/homeassistant/components/frontend/manifest.json +++ b/homeassistant/components/frontend/manifest.json @@ -2,7 +2,7 @@ "domain": "frontend", "name": "Home Assistant Frontend", "documentation": "https://www.home-assistant.io/integrations/frontend", - "requirements": ["home-assistant-frontend==20200917.1"], + "requirements": ["home-assistant-frontend==20200918.0"], "dependencies": [ "api", "auth", diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index e5978245bac..0f88f88469b 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -13,7 +13,7 @@ defusedxml==0.6.0 distro==1.5.0 emoji==0.5.4 hass-nabucasa==0.37.0 -home-assistant-frontend==20200917.1 +home-assistant-frontend==20200918.0 importlib-metadata==1.6.0;python_version<'3.8' jinja2>=2.11.2 netdisco==2.8.2 diff --git a/requirements_all.txt b/requirements_all.txt index dee5b04c41c..bb75fe2dc67 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -747,7 +747,7 @@ hole==0.5.1 holidays==0.10.3 # homeassistant.components.frontend -home-assistant-frontend==20200917.1 +home-assistant-frontend==20200918.0 # homeassistant.components.zwave homeassistant-pyozw==0.1.10 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index b581c2b6597..7862baba5f4 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -370,7 +370,7 @@ hole==0.5.1 holidays==0.10.3 # homeassistant.components.frontend -home-assistant-frontend==20200917.1 +home-assistant-frontend==20200918.0 # homeassistant.components.zwave homeassistant-pyozw==0.1.10 From 9955e7e5e18e71f9d080e3cfb9670fd047d72cbe Mon Sep 17 00:00:00 2001 From: Daniel Shokouhi Date: Fri, 18 Sep 2020 11:43:36 -0700 Subject: [PATCH 07/11] Bump hangups to 0.4.11 (#40258) --- homeassistant/components/hangouts/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/hangouts/manifest.json b/homeassistant/components/hangouts/manifest.json index 80eed48cde9..a2605124dc4 100644 --- a/homeassistant/components/hangouts/manifest.json +++ b/homeassistant/components/hangouts/manifest.json @@ -4,7 +4,7 @@ "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/hangouts", "requirements": [ - "hangups==0.4.10" + "hangups==0.4.11" ], "codeowners": [] } diff --git a/requirements_all.txt b/requirements_all.txt index bb75fe2dc67..79d18146703 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -717,7 +717,7 @@ ha-philipsjs==0.0.8 habitipy==0.2.0 # homeassistant.components.hangouts -hangups==0.4.10 +hangups==0.4.11 # homeassistant.components.cloud hass-nabucasa==0.37.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 7862baba5f4..ce76b34c595 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -349,7 +349,7 @@ griddypower==0.1.0 ha-ffmpeg==2.0 # homeassistant.components.hangouts -hangups==0.4.10 +hangups==0.4.11 # homeassistant.components.cloud hass-nabucasa==0.37.0 From 68cc34df6faac0e32a5338d8b35ac8b4cebc7ef9 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Sat, 19 Sep 2020 12:39:02 -0400 Subject: [PATCH 08/11] Update ZHA dependencies (#40283) --- homeassistant/components/zha/manifest.json | 4 ++-- requirements_all.txt | 4 ++-- requirements_test_all.txt | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/zha/manifest.json b/homeassistant/components/zha/manifest.json index c6b0fa78799..b03d4afd971 100644 --- a/homeassistant/components/zha/manifest.json +++ b/homeassistant/components/zha/manifest.json @@ -8,8 +8,8 @@ "pyserial==3.4", "zha-quirks==0.0.44", "zigpy-cc==0.5.2", - "zigpy-deconz==0.9.2", - "zigpy==0.23.2", + "zigpy-deconz==0.10.0", + "zigpy==0.24.1", "zigpy-xbee==0.13.0", "zigpy-zigate==0.6.2", "zigpy-znp==0.1.1" diff --git a/requirements_all.txt b/requirements_all.txt index 79d18146703..6aea10a43cf 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2302,7 +2302,7 @@ ziggo-mediabox-xl==1.1.0 zigpy-cc==0.5.2 # homeassistant.components.zha -zigpy-deconz==0.9.2 +zigpy-deconz==0.10.0 # homeassistant.components.zha zigpy-xbee==0.13.0 @@ -2314,7 +2314,7 @@ zigpy-zigate==0.6.2 zigpy-znp==0.1.1 # homeassistant.components.zha -zigpy==0.23.2 +zigpy==0.24.1 # homeassistant.components.zoneminder zm-py==0.4.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index ce76b34c595..d5bd1f036b2 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1062,7 +1062,7 @@ zha-quirks==0.0.44 zigpy-cc==0.5.2 # homeassistant.components.zha -zigpy-deconz==0.9.2 +zigpy-deconz==0.10.0 # homeassistant.components.zha zigpy-xbee==0.13.0 @@ -1074,4 +1074,4 @@ zigpy-zigate==0.6.2 zigpy-znp==0.1.1 # homeassistant.components.zha -zigpy==0.23.2 +zigpy==0.24.1 From 85ae63c6560923f73f149e94a03cb2b38fa14992 Mon Sep 17 00:00:00 2001 From: Rob Bierbooms Date: Sat, 19 Sep 2020 13:08:14 +0200 Subject: [PATCH 09/11] Fix error creating duplicate ConfigEntry upon import for rfxtrx (#40296) --- homeassistant/components/rfxtrx/config_flow.py | 1 + 1 file changed, 1 insertion(+) diff --git a/homeassistant/components/rfxtrx/config_flow.py b/homeassistant/components/rfxtrx/config_flow.py index 287e1ec4baf..596f1d0b5e9 100644 --- a/homeassistant/components/rfxtrx/config_flow.py +++ b/homeassistant/components/rfxtrx/config_flow.py @@ -20,4 +20,5 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): if entry and import_config.items() != entry.data.items(): self.hass.config_entries.async_update_entry(entry, data=import_config) return self.async_abort(reason="already_configured") + self._abort_if_unique_id_configured() return self.async_create_entry(title="RFXTRX", data=import_config) From a8b6464d7f90bd478ae2059bebe5d7aa258c7a88 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 19 Sep 2020 20:13:52 +0000 Subject: [PATCH 10/11] Bumped version to 0.115.2 --- homeassistant/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index 79d91ef7cb2..818f4a715a4 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -1,7 +1,7 @@ """Constants used by Home Assistant components.""" MAJOR_VERSION = 0 MINOR_VERSION = 115 -PATCH_VERSION = "1" +PATCH_VERSION = "2" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" REQUIRED_PYTHON_VER = (3, 7, 1) From cf81a5c09ac5456bb9fb1b0815689df07ee6c427 Mon Sep 17 00:00:00 2001 From: Felipe Martins Diel <41558831+felipediel@users.noreply.github.com> Date: Fri, 11 Sep 2020 22:00:28 -0300 Subject: [PATCH 11/11] Improve tests for Broadlink config flow (#39894) --- .../components/broadlink/test_config_flow.py | 83 ++++++++++--------- 1 file changed, 43 insertions(+), 40 deletions(-) diff --git a/tests/components/broadlink/test_config_flow.py b/tests/components/broadlink/test_config_flow.py index 920ff8be1a6..a7660b03da5 100644 --- a/tests/components/broadlink/test_config_flow.py +++ b/tests/components/broadlink/test_config_flow.py @@ -12,13 +12,16 @@ from . import get_device from tests.async_mock import call, patch +DEVICE_DISCOVERY = "homeassistant.components.broadlink.config_flow.blk.discover" +DEVICE_FACTORY = "homeassistant.components.broadlink.config_flow.blk.gendevice" + @pytest.fixture(autouse=True) def broadlink_setup_fixture(): """Mock broadlink entry setup.""" with patch( - "homeassistant.components.broadlink.async_setup_entry", return_value=True - ): + "homeassistant.components.broadlink.async_setup", return_value=True + ), patch("homeassistant.components.broadlink.async_setup_entry", return_value=True): yield @@ -38,7 +41,7 @@ async def test_flow_user_works(hass): assert result["step_id"] == "user" assert result["errors"] == {} - with patch("broadlink.discover", return_value=[mock_api]) as mock_discover: + with patch(DEVICE_DISCOVERY, return_value=[mock_api]) as mock_discover: result = await hass.config_entries.flow.async_configure( result["flow_id"], {"host": device.host, "timeout": device.timeout}, @@ -69,7 +72,7 @@ async def test_flow_user_already_in_progress(hass): DOMAIN, context={"source": config_entries.SOURCE_USER} ) - with patch("broadlink.discover", return_value=[device.get_mock_api()]): + with patch(DEVICE_DISCOVERY, return_value=[device.get_mock_api()]): result = await hass.config_entries.flow.async_configure( result["flow_id"], {"host": device.host, "timeout": device.timeout}, @@ -79,7 +82,7 @@ async def test_flow_user_already_in_progress(hass): DOMAIN, context={"source": config_entries.SOURCE_USER} ) - with patch("broadlink.discover", return_value=[device.get_mock_api()]): + with patch(DEVICE_DISCOVERY, return_value=[device.get_mock_api()]): result = await hass.config_entries.flow.async_configure( result["flow_id"], {"host": device.host, "timeout": device.timeout}, @@ -106,7 +109,7 @@ async def test_flow_user_mac_already_configured(hass): device.timeout = 20 mock_api = device.get_mock_api() - with patch("broadlink.discover", return_value=[mock_api]): + with patch(DEVICE_DISCOVERY, return_value=[mock_api]): result = await hass.config_entries.flow.async_configure( result["flow_id"], {"host": device.host, "timeout": device.timeout}, @@ -125,7 +128,7 @@ async def test_flow_user_invalid_ip_address(hass): DOMAIN, context={"source": config_entries.SOURCE_USER} ) - with patch("broadlink.discover", side_effect=OSError(errno.EINVAL, None)): + with patch(DEVICE_DISCOVERY, side_effect=OSError(errno.EINVAL, None)): result = await hass.config_entries.flow.async_configure( result["flow_id"], {"host": "0.0.0.1"}, @@ -142,7 +145,7 @@ async def test_flow_user_invalid_hostname(hass): DOMAIN, context={"source": config_entries.SOURCE_USER} ) - with patch("broadlink.discover", side_effect=OSError(socket.EAI_NONAME, None)): + with patch(DEVICE_DISCOVERY, side_effect=OSError(socket.EAI_NONAME, None)): result = await hass.config_entries.flow.async_configure( result["flow_id"], {"host": "pancakemaster.local"}, @@ -161,7 +164,7 @@ async def test_flow_user_device_not_found(hass): DOMAIN, context={"source": config_entries.SOURCE_USER} ) - with patch("broadlink.discover", return_value=[]): + with patch(DEVICE_DISCOVERY, return_value=[]): result = await hass.config_entries.flow.async_configure( result["flow_id"], {"host": device.host}, @@ -197,7 +200,7 @@ async def test_flow_user_network_unreachable(hass): DOMAIN, context={"source": config_entries.SOURCE_USER} ) - with patch("broadlink.discover", side_effect=OSError(errno.ENETUNREACH, None)): + with patch(DEVICE_DISCOVERY, side_effect=OSError(errno.ENETUNREACH, None)): result = await hass.config_entries.flow.async_configure( result["flow_id"], {"host": "192.168.1.32"}, @@ -214,7 +217,7 @@ async def test_flow_user_os_error(hass): DOMAIN, context={"source": config_entries.SOURCE_USER} ) - with patch("broadlink.discover", side_effect=OSError()): + with patch(DEVICE_DISCOVERY, side_effect=OSError()): result = await hass.config_entries.flow.async_configure( result["flow_id"], {"host": "192.168.1.32"}, @@ -235,7 +238,7 @@ async def test_flow_auth_authentication_error(hass): DOMAIN, context={"source": config_entries.SOURCE_USER} ) - with patch("broadlink.discover", return_value=[mock_api]): + with patch(DEVICE_DISCOVERY, return_value=[mock_api]): result = await hass.config_entries.flow.async_configure( result["flow_id"], {"host": device.host, "timeout": device.timeout}, @@ -256,7 +259,7 @@ async def test_flow_auth_device_offline(hass): DOMAIN, context={"source": config_entries.SOURCE_USER} ) - with patch("broadlink.discover", return_value=[mock_api]): + with patch(DEVICE_DISCOVERY, return_value=[mock_api]): result = await hass.config_entries.flow.async_configure( result["flow_id"], {"host": device.host}, @@ -277,7 +280,7 @@ async def test_flow_auth_firmware_error(hass): DOMAIN, context={"source": config_entries.SOURCE_USER} ) - with patch("broadlink.discover", return_value=[mock_api]): + with patch(DEVICE_DISCOVERY, return_value=[mock_api]): result = await hass.config_entries.flow.async_configure( result["flow_id"], {"host": device.host}, @@ -298,7 +301,7 @@ async def test_flow_auth_network_unreachable(hass): DOMAIN, context={"source": config_entries.SOURCE_USER} ) - with patch("broadlink.discover", return_value=[mock_api]): + with patch(DEVICE_DISCOVERY, return_value=[mock_api]): result = await hass.config_entries.flow.async_configure( result["flow_id"], {"host": device.host}, @@ -319,7 +322,7 @@ async def test_flow_auth_os_error(hass): DOMAIN, context={"source": config_entries.SOURCE_USER} ) - with patch("broadlink.discover", return_value=[mock_api]): + with patch(DEVICE_DISCOVERY, return_value=[mock_api]): result = await hass.config_entries.flow.async_configure( result["flow_id"], {"host": device.host}, @@ -340,13 +343,13 @@ async def test_flow_reset_works(hass): DOMAIN, context={"source": config_entries.SOURCE_USER} ) - with patch("broadlink.discover", return_value=[mock_api]): + with patch(DEVICE_DISCOVERY, return_value=[mock_api]): result = await hass.config_entries.flow.async_configure( result["flow_id"], {"host": device.host, "timeout": device.timeout}, ) - with patch("broadlink.discover", return_value=[device.get_mock_api()]): + with patch(DEVICE_DISCOVERY, return_value=[device.get_mock_api()]): result = await hass.config_entries.flow.async_configure( result["flow_id"], {"host": device.host, "timeout": device.timeout}, @@ -372,7 +375,7 @@ async def test_flow_unlock_works(hass): DOMAIN, context={"source": config_entries.SOURCE_USER} ) - with patch("broadlink.discover", return_value=[mock_api]): + with patch(DEVICE_DISCOVERY, return_value=[mock_api]): result = await hass.config_entries.flow.async_configure( result["flow_id"], {"host": device.host, "timeout": device.timeout}, @@ -411,7 +414,7 @@ async def test_flow_unlock_device_offline(hass): DOMAIN, context={"source": config_entries.SOURCE_USER} ) - with patch("broadlink.discover", return_value=[mock_api]): + with patch(DEVICE_DISCOVERY, return_value=[mock_api]): result = await hass.config_entries.flow.async_configure( result["flow_id"], {"host": device.host, "timeout": device.timeout}, @@ -438,7 +441,7 @@ async def test_flow_unlock_firmware_error(hass): DOMAIN, context={"source": config_entries.SOURCE_USER} ) - with patch("broadlink.discover", return_value=[mock_api]): + with patch(DEVICE_DISCOVERY, return_value=[mock_api]): result = await hass.config_entries.flow.async_configure( result["flow_id"], {"host": device.host, "timeout": device.timeout}, @@ -465,7 +468,7 @@ async def test_flow_unlock_network_unreachable(hass): DOMAIN, context={"source": config_entries.SOURCE_USER} ) - with patch("broadlink.discover", return_value=[mock_api]): + with patch(DEVICE_DISCOVERY, return_value=[mock_api]): result = await hass.config_entries.flow.async_configure( result["flow_id"], {"host": device.host, "timeout": device.timeout}, @@ -492,7 +495,7 @@ async def test_flow_unlock_os_error(hass): DOMAIN, context={"source": config_entries.SOURCE_USER} ) - with patch("broadlink.discover", return_value=[mock_api]): + with patch(DEVICE_DISCOVERY, return_value=[mock_api]): result = await hass.config_entries.flow.async_configure( result["flow_id"], {"host": device.host, "timeout": device.timeout}, @@ -518,7 +521,7 @@ async def test_flow_do_not_unlock(hass): DOMAIN, context={"source": config_entries.SOURCE_USER} ) - with patch("broadlink.discover", return_value=[mock_api]): + with patch(DEVICE_DISCOVERY, return_value=[mock_api]): result = await hass.config_entries.flow.async_configure( result["flow_id"], {"host": device.host, "timeout": device.timeout}, @@ -546,7 +549,7 @@ async def test_flow_import_works(hass): device = get_device("Living Room") mock_api = device.get_mock_api() - with patch("broadlink.discover", return_value=[mock_api]) as mock_discover: + with patch(DEVICE_DISCOVERY, return_value=[mock_api]) as mock_discover: result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_IMPORT}, @@ -577,12 +580,12 @@ async def test_flow_import_already_in_progress(hass): device = get_device("Living Room") data = {"host": device.host} - with patch("broadlink.discover", return_value=[device.get_mock_api()]): + with patch(DEVICE_DISCOVERY, return_value=[device.get_mock_api()]): result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_IMPORT}, data=data ) - with patch("broadlink.discover", return_value=[device.get_mock_api()]): + with patch(DEVICE_DISCOVERY, return_value=[device.get_mock_api()]): result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_IMPORT}, data=data ) @@ -598,7 +601,7 @@ async def test_flow_import_host_already_configured(hass): mock_entry.add_to_hass(hass) mock_api = device.get_mock_api() - with patch("broadlink.discover", return_value=[mock_api]): + with patch(DEVICE_DISCOVERY, return_value=[mock_api]): result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_IMPORT}, @@ -621,7 +624,7 @@ async def test_flow_import_mac_already_configured(hass): device.host = "192.168.1.16" mock_api = device.get_mock_api() - with patch("broadlink.discover", return_value=[mock_api]): + with patch(DEVICE_DISCOVERY, return_value=[mock_api]): result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_IMPORT}, @@ -639,7 +642,7 @@ async def test_flow_import_mac_already_configured(hass): async def test_flow_import_device_not_found(hass): """Test we handle a device not found in the import step.""" - with patch("broadlink.discover", return_value=[]): + with patch(DEVICE_DISCOVERY, return_value=[]): result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_IMPORT}, @@ -668,7 +671,7 @@ async def test_flow_import_device_not_supported(hass): async def test_flow_import_invalid_ip_address(hass): """Test we handle an invalid IP address in the import step.""" - with patch("broadlink.discover", side_effect=OSError(errno.EINVAL, None)): + with patch(DEVICE_DISCOVERY, side_effect=OSError(errno.EINVAL, None)): result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_IMPORT}, @@ -681,7 +684,7 @@ async def test_flow_import_invalid_ip_address(hass): async def test_flow_import_invalid_hostname(hass): """Test we handle an invalid hostname in the import step.""" - with patch("broadlink.discover", side_effect=OSError(socket.EAI_NONAME, None)): + with patch(DEVICE_DISCOVERY, side_effect=OSError(socket.EAI_NONAME, None)): result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_IMPORT}, @@ -694,7 +697,7 @@ async def test_flow_import_invalid_hostname(hass): async def test_flow_import_network_unreachable(hass): """Test we handle a network unreachable in the import step.""" - with patch("broadlink.discover", side_effect=OSError(errno.ENETUNREACH, None)): + with patch(DEVICE_DISCOVERY, side_effect=OSError(errno.ENETUNREACH, None)): result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_IMPORT}, @@ -707,7 +710,7 @@ async def test_flow_import_network_unreachable(hass): async def test_flow_import_os_error(hass): """Test we handle an OS error in the import step.""" - with patch("broadlink.discover", side_effect=OSError()): + with patch(DEVICE_DISCOVERY, side_effect=OSError()): result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_IMPORT}, @@ -727,7 +730,7 @@ async def test_flow_reauth_works(hass): mock_api.auth.side_effect = blke.AuthenticationError() data = {"name": device.name, **device.get_entry_data()} - with patch("broadlink.gendevice", return_value=mock_api): + with patch(DEVICE_FACTORY, return_value=mock_api): result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": "reauth"}, data=data ) @@ -737,7 +740,7 @@ async def test_flow_reauth_works(hass): mock_api = device.get_mock_api() - with patch("broadlink.discover", return_value=[mock_api]) as mock_discover: + with patch(DEVICE_DISCOVERY, return_value=[mock_api]) as mock_discover: result = await hass.config_entries.flow.async_configure( result["flow_id"], {"host": device.host, "timeout": device.timeout}, @@ -763,7 +766,7 @@ async def test_flow_reauth_invalid_host(hass): mock_api.auth.side_effect = blke.AuthenticationError() data = {"name": device.name, **device.get_entry_data()} - with patch("broadlink.gendevice", return_value=mock_api): + with patch(DEVICE_FACTORY, return_value=mock_api): result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": "reauth"}, data=data ) @@ -771,7 +774,7 @@ async def test_flow_reauth_invalid_host(hass): device.mac = get_device("Office").mac mock_api = device.get_mock_api() - with patch("broadlink.discover", return_value=[mock_api]) as mock_discover: + with patch(DEVICE_DISCOVERY, return_value=[mock_api]) as mock_discover: result = await hass.config_entries.flow.async_configure( result["flow_id"], {"host": device.host, "timeout": device.timeout}, @@ -797,7 +800,7 @@ async def test_flow_reauth_valid_host(hass): mock_api.auth.side_effect = blke.AuthenticationError() data = {"name": device.name, **device.get_entry_data()} - with patch("broadlink.gendevice", return_value=mock_api): + with patch(DEVICE_FACTORY, return_value=mock_api): result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": "reauth"}, data=data ) @@ -805,7 +808,7 @@ async def test_flow_reauth_valid_host(hass): device.host = "192.168.1.128" mock_api = device.get_mock_api() - with patch("broadlink.discover", return_value=[mock_api]) as mock_discover: + with patch(DEVICE_DISCOVERY, return_value=[mock_api]) as mock_discover: result = await hass.config_entries.flow.async_configure( result["flow_id"], {"host": device.host, "timeout": device.timeout},