From 8140ed724c6998164e0ff43197c25d97a123df64 Mon Sep 17 00:00:00 2001 From: Martin Hjelmare Date: Tue, 31 May 2022 15:22:31 +0200 Subject: [PATCH] Remove mysensors yaml (#72761) --- .../components/mysensors/__init__.py | 150 +------- .../components/mysensors/config_flow.py | 46 +-- homeassistant/components/mysensors/const.py | 3 - tests/components/mysensors/conftest.py | 7 +- .../components/mysensors/test_config_flow.py | 189 ++++------ tests/components/mysensors/test_init.py | 343 +----------------- 6 files changed, 87 insertions(+), 651 deletions(-) diff --git a/homeassistant/components/mysensors/__init__.py b/homeassistant/components/mysensors/__init__.py index d392624bbe4..3313a70808c 100644 --- a/homeassistant/components/mysensors/__init__.py +++ b/homeassistant/components/mysensors/__init__.py @@ -7,12 +7,9 @@ from functools import partial import logging from mysensors import BaseAsyncGateway -import voluptuous as vol -from homeassistant import config_entries -from homeassistant.components.mqtt import valid_publish_topic, valid_subscribe_topic from homeassistant.config_entries import ConfigEntry -from homeassistant.const import CONF_OPTIMISTIC, Platform +from homeassistant.const import Platform from homeassistant.core import HomeAssistant, callback import homeassistant.helpers.config_validation as cv from homeassistant.helpers.device_registry import DeviceEntry @@ -22,17 +19,6 @@ from homeassistant.helpers.typing import ConfigType from .const import ( ATTR_DEVICES, - CONF_BAUD_RATE, - CONF_DEVICE, - CONF_GATEWAYS, - CONF_NODES, - CONF_PERSISTENCE, - CONF_PERSISTENCE_FILE, - CONF_RETAIN, - CONF_TCP_PORT, - CONF_TOPIC_IN_PREFIX, - CONF_TOPIC_OUT_PREFIX, - CONF_VERSION, DOMAIN, MYSENSORS_DISCOVERY, MYSENSORS_GATEWAYS, @@ -48,147 +34,17 @@ from .helpers import on_unload _LOGGER = logging.getLogger(__name__) -CONF_DEBUG = "debug" -CONF_NODE_NAME = "name" - DATA_HASS_CONFIG = "hass_config" -DEFAULT_BAUD_RATE = 115200 -DEFAULT_TCP_PORT = 5003 -DEFAULT_VERSION = "1.4" - -def set_default_persistence_file(value: dict) -> dict: - """Set default persistence file.""" - for idx, gateway in enumerate(value): - if gateway.get(CONF_PERSISTENCE_FILE) is not None: - continue - new_name = f"mysensors{idx + 1}.pickle" - gateway[CONF_PERSISTENCE_FILE] = new_name - - return value - - -def has_all_unique_files(value: list[dict]) -> list[dict]: - """Validate that all persistence files are unique and set if any is set.""" - persistence_files = [gateway[CONF_PERSISTENCE_FILE] for gateway in value] - schema = vol.Schema(vol.Unique()) - schema(persistence_files) - return value - - -def is_persistence_file(value: str) -> str: - """Validate that persistence file path ends in either .pickle or .json.""" - if value.endswith((".json", ".pickle")): - return value - raise vol.Invalid(f"{value} does not end in either `.json` or `.pickle`") - - -def deprecated(key: str) -> Callable[[dict], dict]: - """Mark key as deprecated in configuration.""" - - def validator(config: dict) -> dict: - """Check if key is in config, log warning and remove key.""" - if key not in config: - return config - _LOGGER.warning( - "%s option for %s is deprecated. Please remove %s from your " - "configuration file", - key, - DOMAIN, - key, - ) - config.pop(key) - return config - - return validator - - -NODE_SCHEMA = vol.Schema({cv.positive_int: {vol.Required(CONF_NODE_NAME): cv.string}}) - -GATEWAY_SCHEMA = vol.Schema( - vol.All( - deprecated(CONF_NODES), - { - vol.Required(CONF_DEVICE): cv.string, - vol.Optional(CONF_PERSISTENCE_FILE): vol.All( - cv.string, is_persistence_file - ), - vol.Optional(CONF_BAUD_RATE, default=DEFAULT_BAUD_RATE): cv.positive_int, - vol.Optional(CONF_TCP_PORT, default=DEFAULT_TCP_PORT): cv.port, - vol.Optional(CONF_TOPIC_IN_PREFIX): valid_subscribe_topic, - vol.Optional(CONF_TOPIC_OUT_PREFIX): valid_publish_topic, - vol.Optional(CONF_NODES, default={}): NODE_SCHEMA, - }, - ) -) - -CONFIG_SCHEMA = vol.Schema( - vol.All( - cv.deprecated(DOMAIN), - { - DOMAIN: vol.Schema( - vol.All( - deprecated(CONF_DEBUG), - deprecated(CONF_OPTIMISTIC), - deprecated(CONF_PERSISTENCE), - { - vol.Required(CONF_GATEWAYS): vol.All( - cv.ensure_list, - set_default_persistence_file, - has_all_unique_files, - [GATEWAY_SCHEMA], - ), - vol.Optional(CONF_RETAIN, default=True): cv.boolean, - vol.Optional(CONF_VERSION, default=DEFAULT_VERSION): cv.string, - vol.Optional(CONF_OPTIMISTIC, default=False): cv.boolean, - vol.Optional(CONF_PERSISTENCE, default=True): cv.boolean, - }, - ) - ) - }, - ), - extra=vol.ALLOW_EXTRA, -) +CONFIG_SCHEMA = cv.removed(DOMAIN, raise_if_present=False) async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: """Set up the MySensors component.""" + # This is needed to set up the notify platform via discovery. hass.data[DOMAIN] = {DATA_HASS_CONFIG: config} - if DOMAIN not in config or bool(hass.config_entries.async_entries(DOMAIN)): - return True - - config = config[DOMAIN] - user_inputs = [ - { - CONF_DEVICE: gw[CONF_DEVICE], - CONF_BAUD_RATE: gw[CONF_BAUD_RATE], - CONF_TCP_PORT: gw[CONF_TCP_PORT], - CONF_TOPIC_OUT_PREFIX: gw.get(CONF_TOPIC_OUT_PREFIX, ""), - CONF_TOPIC_IN_PREFIX: gw.get(CONF_TOPIC_IN_PREFIX, ""), - CONF_RETAIN: config[CONF_RETAIN], - CONF_VERSION: config[CONF_VERSION], - CONF_PERSISTENCE_FILE: gw[CONF_PERSISTENCE_FILE] - # nodes config ignored at this time. renaming nodes can now be done from the frontend. - } - for gw in config[CONF_GATEWAYS] - ] - user_inputs = [ - {k: v for k, v in userinput.items() if v is not None} - for userinput in user_inputs - ] - - # there is an actual configuration in configuration.yaml, so we have to process it - for user_input in user_inputs: - hass.async_create_task( - hass.config_entries.flow.async_init( - DOMAIN, - context={"source": config_entries.SOURCE_IMPORT}, - data=user_input, - ) - ) - return True diff --git a/homeassistant/components/mysensors/config_flow.py b/homeassistant/components/mysensors/config_flow.py index 9d992e172b0..5409e3c9a85 100644 --- a/homeassistant/components/mysensors/config_flow.py +++ b/homeassistant/components/mysensors/config_flow.py @@ -22,7 +22,6 @@ from homeassistant.core import callback from homeassistant.data_entry_flow import FlowResult import homeassistant.helpers.config_validation as cv -from . import DEFAULT_BAUD_RATE, DEFAULT_TCP_PORT, DEFAULT_VERSION, is_persistence_file from .const import ( CONF_BAUD_RATE, CONF_DEVICE, @@ -42,6 +41,17 @@ from .const import ( ) from .gateway import MQTT_COMPONENT, is_serial_port, is_socket_address, try_connect +DEFAULT_BAUD_RATE = 115200 +DEFAULT_TCP_PORT = 5003 +DEFAULT_VERSION = "1.4" + + +def is_persistence_file(value: str) -> str: + """Validate that persistence file path ends in either .pickle or .json.""" + if value.endswith((".json", ".pickle")): + return value + raise vol.Invalid(f"{value} does not end in either `.json` or `.pickle`") + def _get_schema_common(user_input: dict[str, str]) -> dict: """Create a schema with options common to all gateway types.""" @@ -105,31 +115,6 @@ class MySensorsConfigFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): """Set up config flow.""" self._gw_type: str | None = None - async def async_step_import(self, user_input: dict[str, Any]) -> FlowResult: - """Import a config entry. - - This method is called by async_setup and it has already - prepared the dict to be compatible with what a user would have - entered from the frontend. - Therefore we process it as though it came from the frontend. - """ - if user_input[CONF_DEVICE] == MQTT_COMPONENT: - user_input[CONF_GATEWAY_TYPE] = CONF_GATEWAY_TYPE_MQTT - else: - try: - await self.hass.async_add_executor_job( - is_serial_port, user_input[CONF_DEVICE] - ) - except vol.Invalid: - user_input[CONF_GATEWAY_TYPE] = CONF_GATEWAY_TYPE_TCP - else: - user_input[CONF_GATEWAY_TYPE] = CONF_GATEWAY_TYPE_SERIAL - - result: FlowResult = await self.async_step_user(user_input=user_input) - if errors := result.get("errors"): - return self.async_abort(reason=next(iter(errors.values()))) - return result - async def async_step_user( self, user_input: dict[str, str] | None = None ) -> FlowResult: @@ -335,10 +320,11 @@ class MySensorsConfigFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): errors[CONF_PERSISTENCE_FILE] = "duplicate_persistence_file" break - for other_entry in self._async_current_entries(): - if _is_same_device(gw_type, user_input, other_entry): - errors["base"] = "already_configured" - break + if not errors: + for other_entry in self._async_current_entries(): + if _is_same_device(gw_type, user_input, other_entry): + errors["base"] = "already_configured" + break # if no errors so far, try to connect if not errors and not await try_connect(self.hass, gw_type, user_input): diff --git a/homeassistant/components/mysensors/const.py b/homeassistant/components/mysensors/const.py index 5f3cb6aed96..32e2110dd95 100644 --- a/homeassistant/components/mysensors/const.py +++ b/homeassistant/components/mysensors/const.py @@ -11,9 +11,6 @@ ATTR_GATEWAY_ID: Final = "gateway_id" CONF_BAUD_RATE: Final = "baud_rate" CONF_DEVICE: Final = "device" -CONF_GATEWAYS: Final = "gateways" -CONF_NODES: Final = "nodes" -CONF_PERSISTENCE: Final = "persistence" CONF_PERSISTENCE_FILE: Final = "persistence_file" CONF_RETAIN: Final = "retain" CONF_TCP_PORT: Final = "tcp_port" diff --git a/tests/components/mysensors/conftest.py b/tests/components/mysensors/conftest.py index 54ae88cdccb..7c73ce1a389 100644 --- a/tests/components/mysensors/conftest.py +++ b/tests/components/mysensors/conftest.py @@ -13,13 +13,13 @@ import pytest from homeassistant.components.device_tracker.legacy import Device from homeassistant.components.mqtt import DOMAIN as MQTT_DOMAIN -from homeassistant.components.mysensors import CONF_VERSION, DEFAULT_BAUD_RATE +from homeassistant.components.mysensors.config_flow import DEFAULT_BAUD_RATE from homeassistant.components.mysensors.const import ( CONF_BAUD_RATE, CONF_DEVICE, CONF_GATEWAY_TYPE, CONF_GATEWAY_TYPE_SERIAL, - CONF_GATEWAYS, + CONF_VERSION, DOMAIN, ) from homeassistant.core import HomeAssistant @@ -141,8 +141,7 @@ async def integration_fixture( hass: HomeAssistant, transport: MagicMock, config_entry: MockConfigEntry ) -> AsyncGenerator[MockConfigEntry, None]: """Set up the mysensors integration with a config entry.""" - device = config_entry.data[CONF_DEVICE] - config: dict[str, Any] = {DOMAIN: {CONF_GATEWAYS: [{CONF_DEVICE: device}]}} + config: dict[str, Any] = {} config_entry.add_to_hass(hass) with patch("homeassistant.components.mysensors.device.UPDATE_DELAY", new=0): diff --git a/tests/components/mysensors/test_config_flow.py b/tests/components/mysensors/test_config_flow.py index ca13a6d9cef..e7808162043 100644 --- a/tests/components/mysensors/test_config_flow.py +++ b/tests/components/mysensors/test_config_flow.py @@ -14,7 +14,6 @@ from homeassistant.components.mysensors.const import ( CONF_GATEWAY_TYPE_MQTT, CONF_GATEWAY_TYPE_SERIAL, CONF_GATEWAY_TYPE_TCP, - CONF_PERSISTENCE, CONF_PERSISTENCE_FILE, CONF_RETAIN, CONF_TCP_PORT, @@ -399,333 +398,268 @@ async def test_config_invalid( assert len(mock_setup_entry.mock_calls) == 0 -@pytest.mark.parametrize( - "user_input", - [ - { - CONF_DEVICE: "COM5", - CONF_BAUD_RATE: 57600, - CONF_TCP_PORT: 5003, - CONF_RETAIN: True, - CONF_VERSION: "2.3", - CONF_PERSISTENCE_FILE: "bla.json", - }, - { - CONF_DEVICE: "COM5", - CONF_PERSISTENCE_FILE: "bla.json", - CONF_BAUD_RATE: 57600, - CONF_TCP_PORT: 5003, - CONF_VERSION: "2.3", - CONF_PERSISTENCE: False, - CONF_RETAIN: True, - }, - { - CONF_DEVICE: "mqtt", - CONF_BAUD_RATE: 115200, - CONF_TCP_PORT: 5003, - CONF_TOPIC_IN_PREFIX: "intopic", - CONF_TOPIC_OUT_PREFIX: "outtopic", - CONF_VERSION: "2.4", - CONF_PERSISTENCE: False, - CONF_RETAIN: False, - }, - { - CONF_DEVICE: "127.0.0.1", - CONF_PERSISTENCE_FILE: "blub.pickle", - CONF_BAUD_RATE: 115200, - CONF_TCP_PORT: 343, - CONF_VERSION: "2.4", - CONF_PERSISTENCE: False, - CONF_RETAIN: False, - }, - ], -) -async def test_import(hass: HomeAssistant, mqtt: None, user_input: dict) -> None: - """Test importing a gateway.""" - - with patch("sys.platform", "win32"), patch( - "homeassistant.components.mysensors.config_flow.try_connect", return_value=True - ), patch( - "homeassistant.components.mysensors.async_setup_entry", - return_value=True, - ): - result = await hass.config_entries.flow.async_init( - DOMAIN, data=user_input, context={"source": config_entries.SOURCE_IMPORT} - ) - await hass.async_block_till_done() - - assert result["type"] == "create_entry" - - @pytest.mark.parametrize( "first_input, second_input, expected_result", [ ( { + CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_MQTT, CONF_DEVICE: "mqtt", CONF_VERSION: "2.3", CONF_TOPIC_IN_PREFIX: "same1", CONF_TOPIC_OUT_PREFIX: "same2", }, { - CONF_DEVICE: "mqtt", + CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_MQTT, CONF_VERSION: "2.3", CONF_TOPIC_IN_PREFIX: "same1", CONF_TOPIC_OUT_PREFIX: "same2", }, - (CONF_TOPIC_IN_PREFIX, "duplicate_topic"), + FlowResult(type="form", errors={CONF_TOPIC_IN_PREFIX: "duplicate_topic"}), ), ( { + CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_MQTT, CONF_DEVICE: "mqtt", CONF_VERSION: "2.3", CONF_TOPIC_IN_PREFIX: "different1", CONF_TOPIC_OUT_PREFIX: "different2", }, { - CONF_DEVICE: "mqtt", + CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_MQTT, CONF_VERSION: "2.3", CONF_TOPIC_IN_PREFIX: "different3", CONF_TOPIC_OUT_PREFIX: "different4", }, - None, + FlowResult(type="create_entry"), ), ( { + CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_MQTT, CONF_DEVICE: "mqtt", CONF_VERSION: "2.3", CONF_TOPIC_IN_PREFIX: "same1", CONF_TOPIC_OUT_PREFIX: "different2", }, { - CONF_DEVICE: "mqtt", + CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_MQTT, CONF_VERSION: "2.3", CONF_TOPIC_IN_PREFIX: "same1", CONF_TOPIC_OUT_PREFIX: "different4", }, - (CONF_TOPIC_IN_PREFIX, "duplicate_topic"), + FlowResult(type="form", errors={CONF_TOPIC_IN_PREFIX: "duplicate_topic"}), ), ( { + CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_MQTT, CONF_DEVICE: "mqtt", CONF_VERSION: "2.3", CONF_TOPIC_IN_PREFIX: "same1", CONF_TOPIC_OUT_PREFIX: "different2", }, { - CONF_DEVICE: "mqtt", + CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_MQTT, CONF_VERSION: "2.3", CONF_TOPIC_IN_PREFIX: "different1", CONF_TOPIC_OUT_PREFIX: "same1", }, - (CONF_TOPIC_OUT_PREFIX, "duplicate_topic"), + FlowResult(type="form", errors={CONF_TOPIC_OUT_PREFIX: "duplicate_topic"}), ), ( { + CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_MQTT, CONF_DEVICE: "mqtt", CONF_VERSION: "2.3", CONF_TOPIC_IN_PREFIX: "same1", CONF_TOPIC_OUT_PREFIX: "different2", }, { - CONF_DEVICE: "mqtt", + CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_MQTT, CONF_VERSION: "2.3", CONF_TOPIC_IN_PREFIX: "same1", CONF_TOPIC_OUT_PREFIX: "different1", }, - (CONF_TOPIC_IN_PREFIX, "duplicate_topic"), + FlowResult(type="form", errors={CONF_TOPIC_IN_PREFIX: "duplicate_topic"}), ), ( { + CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_TCP, CONF_DEVICE: "127.0.0.1", CONF_PERSISTENCE_FILE: "same.json", CONF_TCP_PORT: 343, CONF_VERSION: "2.3", - CONF_PERSISTENCE: False, - CONF_RETAIN: False, }, { + CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_TCP, CONF_DEVICE: "192.168.1.2", CONF_PERSISTENCE_FILE: "same.json", CONF_TCP_PORT: 343, CONF_VERSION: "2.3", - CONF_PERSISTENCE: False, - CONF_RETAIN: False, }, - ("persistence_file", "duplicate_persistence_file"), + FlowResult( + type="form", errors={"persistence_file": "duplicate_persistence_file"} + ), ), ( { + CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_TCP, CONF_DEVICE: "127.0.0.1", CONF_TCP_PORT: 343, CONF_VERSION: "2.3", - CONF_PERSISTENCE: False, - CONF_RETAIN: False, }, { + CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_TCP, CONF_DEVICE: "192.168.1.2", CONF_PERSISTENCE_FILE: "same.json", CONF_TCP_PORT: 343, CONF_VERSION: "2.3", - CONF_PERSISTENCE: False, - CONF_RETAIN: False, }, - None, + FlowResult(type="create_entry"), ), ( { + CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_TCP, CONF_DEVICE: "127.0.0.1", CONF_TCP_PORT: 343, CONF_VERSION: "2.3", - CONF_PERSISTENCE: False, - CONF_RETAIN: False, }, { + CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_TCP, CONF_DEVICE: "192.168.1.2", CONF_TCP_PORT: 343, CONF_VERSION: "2.3", - CONF_PERSISTENCE: False, - CONF_RETAIN: False, }, - None, + FlowResult(type="create_entry"), ), ( { + CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_TCP, CONF_DEVICE: "192.168.1.2", CONF_PERSISTENCE_FILE: "different1.json", CONF_TCP_PORT: 343, CONF_VERSION: "2.3", - CONF_PERSISTENCE: False, - CONF_RETAIN: False, }, { + CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_TCP, CONF_DEVICE: "192.168.1.2", CONF_PERSISTENCE_FILE: "different2.json", CONF_TCP_PORT: 343, CONF_VERSION: "2.3", - CONF_PERSISTENCE: False, - CONF_RETAIN: False, }, - ("base", "already_configured"), + FlowResult(type="form", errors={"base": "already_configured"}), ), ( { + CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_TCP, CONF_DEVICE: "192.168.1.2", CONF_PERSISTENCE_FILE: "different1.json", CONF_TCP_PORT: 343, CONF_VERSION: "2.3", - CONF_PERSISTENCE: False, - CONF_RETAIN: False, }, { + CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_TCP, CONF_DEVICE: "192.168.1.2", CONF_PERSISTENCE_FILE: "different2.json", CONF_TCP_PORT: 5003, CONF_VERSION: "2.3", - CONF_PERSISTENCE: False, - CONF_RETAIN: False, }, - None, + FlowResult(type="create_entry"), ), ( { + CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_TCP, CONF_DEVICE: "192.168.1.2", CONF_TCP_PORT: 5003, CONF_VERSION: "2.3", - CONF_PERSISTENCE: False, - CONF_RETAIN: False, }, { + CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_TCP, CONF_DEVICE: "192.168.1.3", CONF_TCP_PORT: 5003, CONF_VERSION: "2.3", - CONF_PERSISTENCE: False, - CONF_RETAIN: False, }, - None, + FlowResult(type="create_entry"), ), ( { + CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_SERIAL, CONF_DEVICE: "COM5", - CONF_TCP_PORT: 5003, - CONF_RETAIN: True, CONF_VERSION: "2.3", CONF_PERSISTENCE_FILE: "different1.json", }, { + CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_SERIAL, CONF_DEVICE: "COM5", - CONF_TCP_PORT: 5003, - CONF_RETAIN: True, CONF_VERSION: "2.3", CONF_PERSISTENCE_FILE: "different2.json", }, - ("base", "already_configured"), + FlowResult(type="form", errors={"base": "already_configured"}), ), ( { + CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_SERIAL, CONF_DEVICE: "COM6", CONF_BAUD_RATE: 57600, - CONF_RETAIN: True, CONF_VERSION: "2.3", }, { + CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_SERIAL, CONF_DEVICE: "COM5", - CONF_TCP_PORT: 5003, - CONF_RETAIN: True, CONF_VERSION: "2.3", }, - None, + FlowResult(type="create_entry"), ), ( { + CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_SERIAL, CONF_DEVICE: "COM5", CONF_BAUD_RATE: 115200, - CONF_RETAIN: True, CONF_VERSION: "2.3", CONF_PERSISTENCE_FILE: "different1.json", }, { + CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_SERIAL, CONF_DEVICE: "COM5", CONF_BAUD_RATE: 57600, - CONF_RETAIN: True, CONF_VERSION: "2.3", CONF_PERSISTENCE_FILE: "different2.json", }, - ("base", "already_configured"), + FlowResult(type="form", errors={"base": "already_configured"}), ), ( { + CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_SERIAL, CONF_DEVICE: "COM5", CONF_BAUD_RATE: 115200, - CONF_RETAIN: True, CONF_VERSION: "2.3", CONF_PERSISTENCE_FILE: "same.json", }, { + CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_SERIAL, CONF_DEVICE: "COM6", CONF_BAUD_RATE: 57600, - CONF_RETAIN: True, CONF_VERSION: "2.3", CONF_PERSISTENCE_FILE: "same.json", }, - ("persistence_file", "duplicate_persistence_file"), + FlowResult( + type="form", errors={"persistence_file": "duplicate_persistence_file"} + ), ), ( { + CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_MQTT, CONF_DEVICE: "mqtt", CONF_PERSISTENCE_FILE: "bla.json", - CONF_BAUD_RATE: 115200, - CONF_TCP_PORT: 5003, CONF_VERSION: "1.4", }, { + CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_SERIAL, CONF_DEVICE: "COM6", CONF_PERSISTENCE_FILE: "bla2.json", CONF_BAUD_RATE: 115200, - CONF_TCP_PORT: 5003, CONF_VERSION: "1.4", }, - None, + FlowResult(type="create_entry"), ), ], ) @@ -734,7 +668,7 @@ async def test_duplicate( mqtt: None, first_input: dict, second_input: dict, - expected_result: tuple[str, str] | None, + expected_result: FlowResult, ) -> None: """Test duplicate detection.""" @@ -746,12 +680,17 @@ async def test_duplicate( ): MockConfigEntry(domain=DOMAIN, data=first_input).add_to_hass(hass) + second_gateway_type = second_input.pop(CONF_GATEWAY_TYPE) result = await hass.config_entries.flow.async_init( - DOMAIN, data=second_input, context={"source": config_entries.SOURCE_IMPORT} + DOMAIN, + data={CONF_GATEWAY_TYPE: second_gateway_type}, + context={"source": config_entries.SOURCE_USER}, + ) + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + second_input, ) await hass.async_block_till_done() - if expected_result is None: - assert result["type"] == "create_entry" - else: - assert result["type"] == "abort" - assert result["reason"] == expected_result[1] + + for key, val in expected_result.items(): + assert result[key] == val # type: ignore[literal-required] diff --git a/tests/components/mysensors/test_init.py b/tests/components/mysensors/test_init.py index bb5d77dc7e3..5d44cdbdb3c 100644 --- a/tests/components/mysensors/test_init.py +++ b/tests/components/mysensors/test_init.py @@ -2,360 +2,19 @@ from __future__ import annotations from collections.abc import Awaitable, Callable -from typing import Any -from unittest.mock import patch from aiohttp import ClientWebSocketResponse from mysensors import BaseSyncGateway from mysensors.sensor import Sensor -import pytest -from homeassistant.components.mysensors import ( - CONF_BAUD_RATE, - CONF_DEVICE, - CONF_GATEWAYS, - CONF_PERSISTENCE, - CONF_PERSISTENCE_FILE, - CONF_RETAIN, - CONF_TCP_PORT, - CONF_VERSION, - DEFAULT_VERSION, - DOMAIN, -) -from homeassistant.components.mysensors.const import ( - CONF_GATEWAY_TYPE, - CONF_GATEWAY_TYPE_MQTT, - CONF_GATEWAY_TYPE_SERIAL, - CONF_GATEWAY_TYPE_TCP, - CONF_TOPIC_IN_PREFIX, - CONF_TOPIC_OUT_PREFIX, -) +from homeassistant.components.mysensors import DOMAIN from homeassistant.core import HomeAssistant from homeassistant.helpers import device_registry as dr, entity_registry as er -from homeassistant.helpers.typing import ConfigType from homeassistant.setup import async_setup_component from tests.common import MockConfigEntry -@pytest.mark.parametrize( - "config, expected_calls, expected_to_succeed, expected_config_entry_data", - [ - ( - { - DOMAIN: { - CONF_GATEWAYS: [ - { - CONF_DEVICE: "COM5", - CONF_PERSISTENCE_FILE: "bla.json", - CONF_BAUD_RATE: 57600, - CONF_TCP_PORT: 5003, - } - ], - CONF_VERSION: "2.3", - CONF_PERSISTENCE: False, - CONF_RETAIN: True, - } - }, - 1, - True, - [ - { - CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_SERIAL, - CONF_DEVICE: "COM5", - CONF_PERSISTENCE_FILE: "bla.json", - CONF_BAUD_RATE: 57600, - CONF_VERSION: "2.3", - CONF_TCP_PORT: 5003, - CONF_TOPIC_IN_PREFIX: "", - CONF_TOPIC_OUT_PREFIX: "", - CONF_RETAIN: True, - } - ], - ), - ( - { - DOMAIN: { - CONF_GATEWAYS: [ - { - CONF_DEVICE: "127.0.0.1", - CONF_PERSISTENCE_FILE: "blub.pickle", - CONF_BAUD_RATE: 115200, - CONF_TCP_PORT: 343, - } - ], - CONF_VERSION: "2.4", - CONF_PERSISTENCE: False, - CONF_RETAIN: False, - } - }, - 1, - True, - [ - { - CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_TCP, - CONF_DEVICE: "127.0.0.1", - CONF_PERSISTENCE_FILE: "blub.pickle", - CONF_TCP_PORT: 343, - CONF_VERSION: "2.4", - CONF_BAUD_RATE: 115200, - CONF_TOPIC_IN_PREFIX: "", - CONF_TOPIC_OUT_PREFIX: "", - CONF_RETAIN: False, - } - ], - ), - ( - { - DOMAIN: { - CONF_GATEWAYS: [ - { - CONF_DEVICE: "127.0.0.1", - } - ], - CONF_PERSISTENCE: False, - CONF_RETAIN: False, - } - }, - 1, - True, - [ - { - CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_TCP, - CONF_DEVICE: "127.0.0.1", - CONF_TCP_PORT: 5003, - CONF_VERSION: DEFAULT_VERSION, - CONF_BAUD_RATE: 115200, - CONF_TOPIC_IN_PREFIX: "", - CONF_TOPIC_OUT_PREFIX: "", - CONF_RETAIN: False, - CONF_PERSISTENCE_FILE: "mysensors1.pickle", - } - ], - ), - ( - { - DOMAIN: { - CONF_GATEWAYS: [ - { - CONF_DEVICE: "mqtt", - CONF_BAUD_RATE: 115200, - CONF_TCP_PORT: 5003, - CONF_TOPIC_IN_PREFIX: "intopic", - CONF_TOPIC_OUT_PREFIX: "outtopic", - } - ], - CONF_PERSISTENCE: False, - CONF_RETAIN: False, - } - }, - 1, - True, - [ - { - CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_MQTT, - CONF_DEVICE: "mqtt", - CONF_VERSION: DEFAULT_VERSION, - CONF_BAUD_RATE: 115200, - CONF_TCP_PORT: 5003, - CONF_TOPIC_OUT_PREFIX: "outtopic", - CONF_TOPIC_IN_PREFIX: "intopic", - CONF_RETAIN: False, - CONF_PERSISTENCE_FILE: "mysensors1.pickle", - } - ], - ), - ( - { - DOMAIN: { - CONF_GATEWAYS: [ - { - CONF_DEVICE: "mqtt", - CONF_BAUD_RATE: 115200, - CONF_TCP_PORT: 5003, - } - ], - CONF_PERSISTENCE: False, - CONF_RETAIN: False, - } - }, - 0, - True, - [{}], - ), - ( - { - DOMAIN: { - CONF_GATEWAYS: [ - { - CONF_DEVICE: "mqtt", - CONF_PERSISTENCE_FILE: "bla.json", - CONF_TOPIC_OUT_PREFIX: "out", - CONF_TOPIC_IN_PREFIX: "in", - CONF_BAUD_RATE: 115200, - CONF_TCP_PORT: 5003, - }, - { - CONF_DEVICE: "COM6", - CONF_PERSISTENCE_FILE: "bla2.json", - CONF_BAUD_RATE: 115200, - CONF_TCP_PORT: 5003, - }, - ], - CONF_VERSION: "2.4", - CONF_PERSISTENCE: False, - CONF_RETAIN: False, - } - }, - 2, - True, - [ - { - CONF_DEVICE: "mqtt", - CONF_PERSISTENCE_FILE: "bla.json", - CONF_TOPIC_OUT_PREFIX: "out", - CONF_TOPIC_IN_PREFIX: "in", - CONF_BAUD_RATE: 115200, - CONF_TCP_PORT: 5003, - CONF_VERSION: "2.4", - CONF_RETAIN: False, - CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_MQTT, - }, - { - CONF_DEVICE: "COM6", - CONF_PERSISTENCE_FILE: "bla2.json", - CONF_TOPIC_OUT_PREFIX: "", - CONF_TOPIC_IN_PREFIX: "", - CONF_BAUD_RATE: 115200, - CONF_TCP_PORT: 5003, - CONF_VERSION: "2.4", - CONF_RETAIN: False, - CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_SERIAL, - }, - ], - ), - ( - { - DOMAIN: { - CONF_GATEWAYS: [ - { - CONF_DEVICE: "mqtt", - CONF_PERSISTENCE_FILE: "bla.json", - CONF_BAUD_RATE: 115200, - CONF_TCP_PORT: 5003, - }, - { - CONF_DEVICE: "COM6", - CONF_PERSISTENCE_FILE: "bla.json", - CONF_BAUD_RATE: 115200, - CONF_TCP_PORT: 5003, - }, - ], - CONF_VERSION: "2.4", - CONF_PERSISTENCE: False, - CONF_RETAIN: False, - } - }, - 0, - False, - [{}], - ), - ( - { - DOMAIN: { - CONF_GATEWAYS: [ - { - CONF_DEVICE: "COMx", - CONF_PERSISTENCE_FILE: "bla.json", - CONF_BAUD_RATE: 115200, - CONF_TCP_PORT: 5003, - }, - ], - CONF_VERSION: "2.4", - CONF_PERSISTENCE: False, - CONF_RETAIN: False, - } - }, - 0, - True, - [{}], - ), - ( - { - DOMAIN: { - CONF_GATEWAYS: [ - { - CONF_DEVICE: "COM1", - }, - { - CONF_DEVICE: "COM2", - }, - ], - } - }, - 2, - True, - [ - { - CONF_DEVICE: "COM1", - CONF_PERSISTENCE_FILE: "mysensors1.pickle", - CONF_TOPIC_OUT_PREFIX: "", - CONF_TOPIC_IN_PREFIX: "", - CONF_BAUD_RATE: 115200, - CONF_TCP_PORT: 5003, - CONF_VERSION: "1.4", - CONF_RETAIN: True, - CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_SERIAL, - }, - { - CONF_DEVICE: "COM2", - CONF_PERSISTENCE_FILE: "mysensors2.pickle", - CONF_TOPIC_OUT_PREFIX: "", - CONF_TOPIC_IN_PREFIX: "", - CONF_BAUD_RATE: 115200, - CONF_TCP_PORT: 5003, - CONF_VERSION: "1.4", - CONF_RETAIN: True, - CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_SERIAL, - }, - ], - ), - ], -) -async def test_import( - hass: HomeAssistant, - mqtt: None, - config: ConfigType, - expected_calls: int, - expected_to_succeed: bool, - expected_config_entry_data: list[dict[str, Any]], -) -> None: - """Test importing a gateway.""" - - with patch("sys.platform", "win32"), patch( - "homeassistant.components.mysensors.config_flow.try_connect", return_value=True - ), patch( - "homeassistant.components.mysensors.async_setup_entry", - return_value=True, - ) as mock_setup_entry: - result = await async_setup_component(hass, DOMAIN, config) - assert result == expected_to_succeed - await hass.async_block_till_done() - - assert len(mock_setup_entry.mock_calls) == expected_calls - - for idx in range(expected_calls): - config_entry = mock_setup_entry.mock_calls[idx][1][1] - expected_persistence_file = expected_config_entry_data[idx].pop( - CONF_PERSISTENCE_FILE - ) - expected_persistence_path = hass.config.path(expected_persistence_file) - config_entry_data = dict(config_entry.data) - persistence_path = config_entry_data.pop(CONF_PERSISTENCE_FILE) - assert persistence_path == expected_persistence_path - assert config_entry_data == expected_config_entry_data[idx] - - async def test_remove_config_entry_device( hass: HomeAssistant, gps_sensor: Sensor,