Clean up Insteon config_flow (#93004)
* Clean up config_flow * Remove unnecessary logging * Remove logger * Add more tests * Test closing modem connection * Simplify patchingpull/88559/head^2
parent
d62cdf3d65
commit
e2fb1de0d9
|
@ -3,8 +3,7 @@ from __future__ import annotations
|
|||
|
||||
import logging
|
||||
|
||||
from pyinsteon import async_connect
|
||||
import voluptuous as vol
|
||||
from pyinsteon import async_close, async_connect, devices
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.components import dhcp, usb
|
||||
|
@ -44,6 +43,7 @@ from .schemas import (
|
|||
build_remove_x10_schema,
|
||||
build_x10_schema,
|
||||
)
|
||||
from .utils import async_get_usb_ports
|
||||
|
||||
STEP_PLM = "plm"
|
||||
STEP_HUB_V1 = "hubv1"
|
||||
|
@ -55,18 +55,10 @@ STEP_ADD_OVERRIDE = "add_override"
|
|||
STEP_REMOVE_OVERRIDE = "remove_override"
|
||||
STEP_REMOVE_X10 = "remove_x10"
|
||||
MODEM_TYPE = "modem_type"
|
||||
PLM = "PowerLinc Modem (PLM)"
|
||||
HUB1 = "Hub version 1 (pre-2014)"
|
||||
HUB2 = "Hub version 2"
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _only_one_selected(*args):
|
||||
"""Test if only one item is True."""
|
||||
return sum(args) == 1
|
||||
|
||||
|
||||
async def _async_connect(**kwargs):
|
||||
"""Connect to the Insteon modem."""
|
||||
try:
|
||||
|
@ -128,22 +120,10 @@ class InsteonFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
|
||||
async def async_step_user(self, user_input=None):
|
||||
"""Init the config flow."""
|
||||
errors = {}
|
||||
if self._async_current_entries():
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
if user_input is not None:
|
||||
selection = user_input.get(MODEM_TYPE)
|
||||
|
||||
if selection == PLM:
|
||||
return await self.async_step_plm()
|
||||
if selection == HUB1:
|
||||
return await self.async_step_hubv1()
|
||||
return await self.async_step_hubv2()
|
||||
modem_types = [PLM, HUB1, HUB2]
|
||||
data_schema = vol.Schema({vol.Required(MODEM_TYPE): vol.In(modem_types)})
|
||||
return self.async_show_form(
|
||||
step_id="user", data_schema=data_schema, errors=errors
|
||||
)
|
||||
modem_types = [STEP_PLM, STEP_HUB_V1, STEP_HUB_V2]
|
||||
return self.async_show_menu(step_id="user", menu_options=modem_types)
|
||||
|
||||
async def async_step_plm(self, user_input=None):
|
||||
"""Set up the PLM modem type."""
|
||||
|
@ -153,7 +133,8 @@ class InsteonFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
return self.async_create_entry(title="", data=user_input)
|
||||
errors["base"] = "cannot_connect"
|
||||
schema_defaults = user_input if user_input is not None else {}
|
||||
data_schema = build_plm_schema(**schema_defaults)
|
||||
ports = await async_get_usb_ports(self.hass)
|
||||
data_schema = build_plm_schema(ports, **schema_defaults)
|
||||
return self.async_show_form(
|
||||
step_id=STEP_PLM, data_schema=data_schema, errors=errors
|
||||
)
|
||||
|
@ -243,57 +224,24 @@ class InsteonOptionsFlowHandler(config_entries.OptionsFlow):
|
|||
|
||||
async def async_step_init(self, user_input=None) -> FlowResult:
|
||||
"""Init the options config flow."""
|
||||
errors = {}
|
||||
if user_input is not None:
|
||||
change_hub_config = user_input.get(STEP_CHANGE_HUB_CONFIG, False)
|
||||
change_plm_config = user_input.get(STEP_CHANGE_PLM_CONFIG, False)
|
||||
device_override = user_input.get(STEP_ADD_OVERRIDE, False)
|
||||
x10_device = user_input.get(STEP_ADD_X10, False)
|
||||
remove_override = user_input.get(STEP_REMOVE_OVERRIDE, False)
|
||||
remove_x10 = user_input.get(STEP_REMOVE_X10, False)
|
||||
if _only_one_selected(
|
||||
change_hub_config,
|
||||
change_plm_config,
|
||||
device_override,
|
||||
x10_device,
|
||||
remove_override,
|
||||
remove_x10,
|
||||
):
|
||||
if change_hub_config:
|
||||
return await self.async_step_change_hub_config()
|
||||
if change_plm_config:
|
||||
return await self.async_step_change_plm_config()
|
||||
if device_override:
|
||||
return await self.async_step_add_override()
|
||||
if x10_device:
|
||||
return await self.async_step_add_x10()
|
||||
if remove_override:
|
||||
return await self.async_step_remove_override()
|
||||
if remove_x10:
|
||||
return await self.async_step_remove_x10()
|
||||
errors["base"] = "select_single"
|
||||
menu_options = [STEP_ADD_OVERRIDE, STEP_ADD_X10]
|
||||
|
||||
data_schema = {
|
||||
vol.Optional(STEP_ADD_OVERRIDE): bool,
|
||||
vol.Optional(STEP_ADD_X10): bool,
|
||||
}
|
||||
if self.config_entry.data.get(CONF_HOST):
|
||||
data_schema[vol.Optional(STEP_CHANGE_HUB_CONFIG)] = bool
|
||||
menu_options.append(STEP_CHANGE_HUB_CONFIG)
|
||||
else:
|
||||
data_schema[vol.Optional(STEP_CHANGE_PLM_CONFIG)] = bool
|
||||
menu_options.append(STEP_CHANGE_PLM_CONFIG)
|
||||
|
||||
options = {**self.config_entry.options}
|
||||
if options.get(CONF_OVERRIDE):
|
||||
data_schema[vol.Optional(STEP_REMOVE_OVERRIDE)] = bool
|
||||
menu_options.append(STEP_REMOVE_OVERRIDE)
|
||||
if options.get(CONF_X10):
|
||||
data_schema[vol.Optional(STEP_REMOVE_X10)] = bool
|
||||
menu_options.append(STEP_REMOVE_X10)
|
||||
|
||||
return self.async_show_form(
|
||||
step_id="init", data_schema=vol.Schema(data_schema), errors=errors
|
||||
)
|
||||
return self.async_show_menu(step_id="init", menu_options=menu_options)
|
||||
|
||||
async def async_step_change_hub_config(self, user_input=None) -> FlowResult:
|
||||
"""Change the Hub configuration."""
|
||||
errors = {}
|
||||
if user_input is not None:
|
||||
data = {
|
||||
**self.config_entry.data,
|
||||
|
@ -303,31 +251,41 @@ class InsteonOptionsFlowHandler(config_entries.OptionsFlow):
|
|||
if self.config_entry.data[CONF_HUB_VERSION] == 2:
|
||||
data[CONF_USERNAME] = user_input[CONF_USERNAME]
|
||||
data[CONF_PASSWORD] = user_input[CONF_PASSWORD]
|
||||
self.hass.config_entries.async_update_entry(self.config_entry, data=data)
|
||||
return self.async_create_entry(
|
||||
title="",
|
||||
data={**self.config_entry.options},
|
||||
)
|
||||
if devices.modem:
|
||||
await async_close()
|
||||
|
||||
if await _async_connect(**data):
|
||||
self.hass.config_entries.async_update_entry(
|
||||
self.config_entry, data=data
|
||||
)
|
||||
return self.async_create_entry(data={**self.config_entry.options})
|
||||
errors["base"] = "cannot_connect"
|
||||
data_schema = build_hub_schema(**self.config_entry.data)
|
||||
return self.async_show_form(
|
||||
step_id=STEP_CHANGE_HUB_CONFIG, data_schema=data_schema
|
||||
step_id=STEP_CHANGE_HUB_CONFIG, data_schema=data_schema, errors=errors
|
||||
)
|
||||
|
||||
async def async_step_change_plm_config(self, user_input=None) -> FlowResult:
|
||||
"""Change the PLM configuration."""
|
||||
errors = {}
|
||||
if user_input is not None:
|
||||
data = {
|
||||
**self.config_entry.data,
|
||||
CONF_DEVICE: user_input[CONF_DEVICE],
|
||||
}
|
||||
self.hass.config_entries.async_update_entry(self.config_entry, data=data)
|
||||
return self.async_create_entry(
|
||||
title="",
|
||||
data={**self.config_entry.options},
|
||||
)
|
||||
data_schema = build_plm_schema(**self.config_entry.data)
|
||||
if devices.modem:
|
||||
await async_close()
|
||||
if await _async_connect(**data):
|
||||
self.hass.config_entries.async_update_entry(
|
||||
self.config_entry, data=data
|
||||
)
|
||||
return self.async_create_entry(data={**self.config_entry.options})
|
||||
errors["base"] = "cannot_connect"
|
||||
|
||||
ports = await async_get_usb_ports(self.hass)
|
||||
data_schema = build_plm_schema(ports, **self.config_entry.data)
|
||||
return self.async_show_form(
|
||||
step_id=STEP_CHANGE_PLM_CONFIG, data_schema=data_schema
|
||||
step_id=STEP_CHANGE_PLM_CONFIG, data_schema=data_schema, errors=errors
|
||||
)
|
||||
|
||||
async def async_step_add_override(self, user_input=None) -> FlowResult:
|
||||
|
@ -337,7 +295,7 @@ class InsteonOptionsFlowHandler(config_entries.OptionsFlow):
|
|||
try:
|
||||
data = add_device_override({**self.config_entry.options}, user_input)
|
||||
async_dispatcher_send(self.hass, SIGNAL_ADD_DEVICE_OVERRIDE, user_input)
|
||||
return self.async_create_entry(title="", data=data)
|
||||
return self.async_create_entry(data=data)
|
||||
except ValueError:
|
||||
errors["base"] = "input_error"
|
||||
schema_defaults = user_input if user_input is not None else {}
|
||||
|
@ -352,7 +310,7 @@ class InsteonOptionsFlowHandler(config_entries.OptionsFlow):
|
|||
if user_input is not None:
|
||||
options = add_x10_device({**self.config_entry.options}, user_input)
|
||||
async_dispatcher_send(self.hass, SIGNAL_ADD_X10_DEVICE, user_input)
|
||||
return self.async_create_entry(title="", data=options)
|
||||
return self.async_create_entry(data=options)
|
||||
schema_defaults: dict[str, str] = user_input if user_input is not None else {}
|
||||
data_schema = build_x10_schema(**schema_defaults)
|
||||
return self.async_show_form(
|
||||
|
@ -370,7 +328,7 @@ class InsteonOptionsFlowHandler(config_entries.OptionsFlow):
|
|||
SIGNAL_REMOVE_DEVICE_OVERRIDE,
|
||||
user_input[CONF_ADDRESS],
|
||||
)
|
||||
return self.async_create_entry(title="", data=options)
|
||||
return self.async_create_entry(data=options)
|
||||
|
||||
data_schema = build_remove_override_schema(options[CONF_OVERRIDE])
|
||||
return self.async_show_form(
|
||||
|
@ -386,7 +344,7 @@ class InsteonOptionsFlowHandler(config_entries.OptionsFlow):
|
|||
async_dispatcher_send(
|
||||
self.hass, SIGNAL_REMOVE_X10_DEVICE, housecode, unitcode
|
||||
)
|
||||
return self.async_create_entry(title="", data=options)
|
||||
return self.async_create_entry(data=options)
|
||||
|
||||
data_schema = build_remove_x10_schema(options[CONF_X10])
|
||||
return self.async_show_form(
|
||||
|
|
|
@ -285,9 +285,21 @@ def build_x10_schema(
|
|||
)
|
||||
|
||||
|
||||
def build_plm_schema(device=vol.UNDEFINED):
|
||||
def _find_likely_port(ports):
|
||||
"""Return the most likely USB port for a PLM."""
|
||||
test_strings = ["FTDI", "0403:6001", "10BF:"]
|
||||
for port, name in ports.items():
|
||||
for test_string in test_strings:
|
||||
if test_string in name:
|
||||
return port
|
||||
return vol.UNDEFINED
|
||||
|
||||
|
||||
def build_plm_schema(ports: dict[str, str], device=vol.UNDEFINED):
|
||||
"""Build the PLM schema for config flow."""
|
||||
return vol.Schema({vol.Required(CONF_DEVICE, default=device): str})
|
||||
if not device or device == vol.UNDEFINED:
|
||||
device = _find_likely_port(ports)
|
||||
return vol.Schema({vol.Required(CONF_DEVICE, default=device): vol.In(ports)})
|
||||
|
||||
|
||||
def build_hub_schema(
|
||||
|
|
|
@ -4,8 +4,10 @@
|
|||
"step": {
|
||||
"user": {
|
||||
"description": "Select the Insteon modem type.",
|
||||
"data": {
|
||||
"modem_type": "Modem type."
|
||||
"menu_options": {
|
||||
"plm": "PowerLink Modem (PLM)",
|
||||
"hubv1": "Hub version 1 (pre 2014)",
|
||||
"hubv2": "Hub version 2"
|
||||
}
|
||||
},
|
||||
"plm": {
|
||||
|
@ -38,8 +40,7 @@
|
|||
}
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
|
||||
"select_single": "Select one option."
|
||||
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]"
|
||||
},
|
||||
"abort": {
|
||||
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
|
||||
|
@ -50,7 +51,7 @@
|
|||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
"data": {
|
||||
"menu_options": {
|
||||
"change_hub_config": "Change the Hub configuration.",
|
||||
"change_plm_config": "Change the PLM configuration.",
|
||||
"add_override": "Add a device override.",
|
||||
|
@ -60,7 +61,7 @@
|
|||
}
|
||||
},
|
||||
"change_hub_config": {
|
||||
"description": "Change the Insteon Hub connection information. You must restart Home Assistant after making this change. This does not change the configuration of the Hub itself. To change the configuration in the Hub use the Hub app.",
|
||||
"description": "Change the Insteon Hub connection information.",
|
||||
"data": {
|
||||
"host": "[%key:common::config_flow::data::ip%]",
|
||||
"port": "[%key:common::config_flow::data::port%]",
|
||||
|
@ -69,7 +70,7 @@
|
|||
}
|
||||
},
|
||||
"change_plm_config": {
|
||||
"description": "Change the Insteon PLM connection information. You must restart Home Assistant after making this change. This does not change the configuration of the PLM itself.",
|
||||
"description": "Change the Insteon PLM connection information.",
|
||||
"data": {
|
||||
"device": "[%key:common::config_flow::data::usb_path%]"
|
||||
}
|
||||
|
@ -106,7 +107,6 @@
|
|||
},
|
||||
"error": {
|
||||
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
|
||||
"select_single": "Select one option.",
|
||||
"input_error": "Invalid entries, please check your values."
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,9 @@ from pyinsteon.managers.x10_manager import (
|
|||
async_x10_all_units_off,
|
||||
)
|
||||
from pyinsteon.x10_address import create as create_x10_address
|
||||
from serial.tools import list_ports
|
||||
|
||||
from homeassistant.components import usb
|
||||
from homeassistant.const import (
|
||||
CONF_ADDRESS,
|
||||
CONF_ENTITY_ID,
|
||||
|
@ -393,3 +395,32 @@ def async_add_insteon_entities(
|
|||
for group in groups:
|
||||
new_entities.append(entity_type(device, group))
|
||||
async_add_entities(new_entities)
|
||||
|
||||
|
||||
def get_usb_ports() -> dict[str, str]:
|
||||
"""Return a dict of USB ports and their friendly names."""
|
||||
ports = list_ports.comports()
|
||||
port_descriptions = {}
|
||||
for port in ports:
|
||||
vid: str | None = None
|
||||
pid: str | None = None
|
||||
if port.vid is not None and port.pid is not None:
|
||||
usb_device = usb.usb_device_from_port(port)
|
||||
vid = usb_device.vid
|
||||
pid = usb_device.pid
|
||||
dev_path = usb.get_serial_by_id(port.device)
|
||||
human_name = usb.human_readable_device_name(
|
||||
dev_path,
|
||||
port.serial_number,
|
||||
port.manufacturer,
|
||||
port.description,
|
||||
vid,
|
||||
pid,
|
||||
)
|
||||
port_descriptions[dev_path] = human_name
|
||||
return port_descriptions
|
||||
|
||||
|
||||
async def async_get_usb_ports(hass: HomeAssistant) -> dict[str, str]:
|
||||
"""Return a dict of USB ports and their friendly names."""
|
||||
return await hass.async_add_executor_job(get_usb_ports)
|
||||
|
|
|
@ -96,5 +96,8 @@ MOCK_IMPORT_FULL_CONFIG_HUB_V1[CONF_OVERRIDE] = [MOCK_DEVICE_OVERRIDE_CONFIG]
|
|||
MOCK_IMPORT_FULL_CONFIG_HUB_V1[CONF_X10] = [MOCK_X10_CONFIG_1, MOCK_X10_CONFIG_2]
|
||||
|
||||
PATCH_CONNECTION = "homeassistant.components.insteon.config_flow.async_connect"
|
||||
PATCH_CONNECTION_CLOSE = "homeassistant.components.insteon.config_flow.async_close"
|
||||
PATCH_DEVICES = "homeassistant.components.insteon.config_flow.devices"
|
||||
PATCH_USB_LIST = "homeassistant.components.insteon.config_flow.async_get_usb_ports"
|
||||
PATCH_ASYNC_SETUP = "homeassistant.components.insteon.async_setup"
|
||||
PATCH_ASYNC_SETUP_ENTRY = "homeassistant.components.insteon.async_setup_entry"
|
||||
|
|
|
@ -2,18 +2,19 @@
|
|||
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
from voluptuous_serialize import convert
|
||||
|
||||
from homeassistant import config_entries, data_entry_flow
|
||||
from homeassistant.components import usb
|
||||
from homeassistant.components import dhcp, usb
|
||||
from homeassistant.components.insteon.config_flow import (
|
||||
HUB1,
|
||||
HUB2,
|
||||
MODEM_TYPE,
|
||||
PLM,
|
||||
STEP_ADD_OVERRIDE,
|
||||
STEP_ADD_X10,
|
||||
STEP_CHANGE_HUB_CONFIG,
|
||||
STEP_CHANGE_PLM_CONFIG,
|
||||
STEP_HUB_V1,
|
||||
STEP_HUB_V2,
|
||||
STEP_PLM,
|
||||
STEP_REMOVE_OVERRIDE,
|
||||
STEP_REMOVE_X10,
|
||||
)
|
||||
|
@ -40,6 +41,7 @@ from homeassistant.const import (
|
|||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from .const import (
|
||||
MOCK_DEVICE,
|
||||
MOCK_HOSTNAME,
|
||||
MOCK_IMPORT_CONFIG_PLM,
|
||||
MOCK_IMPORT_MINIMUM_HUB_V1,
|
||||
|
@ -52,16 +54,37 @@ from .const import (
|
|||
PATCH_ASYNC_SETUP,
|
||||
PATCH_ASYNC_SETUP_ENTRY,
|
||||
PATCH_CONNECTION,
|
||||
PATCH_CONNECTION_CLOSE,
|
||||
PATCH_DEVICES,
|
||||
PATCH_USB_LIST,
|
||||
)
|
||||
from .mock_devices import MockDevices
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
USB_PORTS = {"/dev/ttyUSB0": "/dev/ttyUSB0", MOCK_DEVICE: MOCK_DEVICE}
|
||||
|
||||
|
||||
async def mock_successful_connection(*args, **kwargs):
|
||||
"""Return a successful connection."""
|
||||
return True
|
||||
|
||||
|
||||
async def mock_usb_list(hass: HomeAssistant):
|
||||
"""Return a mock list of USB devices."""
|
||||
return USB_PORTS
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def patch_usb_list():
|
||||
"""Only setup the lock and required base platforms to speed up tests."""
|
||||
with patch(
|
||||
PATCH_USB_LIST,
|
||||
mock_usb_list,
|
||||
):
|
||||
yield
|
||||
|
||||
|
||||
async def mock_failed_connection(*args, **kwargs):
|
||||
"""Return a failed connection."""
|
||||
raise ConnectionError("Connection failed")
|
||||
|
@ -72,12 +95,11 @@ async def _init_form(hass, modem_type):
|
|||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
assert result["type"] == data_entry_flow.FlowResultType.FORM
|
||||
assert result["errors"] == {}
|
||||
assert result["type"] == data_entry_flow.FlowResultType.MENU
|
||||
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{MODEM_TYPE: modem_type},
|
||||
{"next_step_id": modem_type},
|
||||
)
|
||||
return result2
|
||||
|
||||
|
@ -99,7 +121,7 @@ async def _device_form(hass, flow_id, connection, user_input):
|
|||
async def test_form_select_modem(hass: HomeAssistant) -> None:
|
||||
"""Test we get a modem form."""
|
||||
|
||||
result = await _init_form(hass, HUB2)
|
||||
result = await _init_form(hass, STEP_HUB_V2)
|
||||
assert result["step_id"] == STEP_HUB_V2
|
||||
assert result["type"] == "form"
|
||||
|
||||
|
@ -127,7 +149,7 @@ async def test_fail_on_existing(hass: HomeAssistant) -> None:
|
|||
async def test_form_select_plm(hass: HomeAssistant) -> None:
|
||||
"""Test we set up the PLM correctly."""
|
||||
|
||||
result = await _init_form(hass, PLM)
|
||||
result = await _init_form(hass, STEP_PLM)
|
||||
|
||||
result2, mock_setup, mock_setup_entry = await _device_form(
|
||||
hass, result["flow_id"], mock_successful_connection, MOCK_USER_INPUT_PLM
|
||||
|
@ -142,7 +164,7 @@ async def test_form_select_plm(hass: HomeAssistant) -> None:
|
|||
async def test_form_select_hub_v1(hass: HomeAssistant) -> None:
|
||||
"""Test we set up the Hub v1 correctly."""
|
||||
|
||||
result = await _init_form(hass, HUB1)
|
||||
result = await _init_form(hass, STEP_HUB_V1)
|
||||
|
||||
result2, mock_setup, mock_setup_entry = await _device_form(
|
||||
hass, result["flow_id"], mock_successful_connection, MOCK_USER_INPUT_HUB_V1
|
||||
|
@ -160,7 +182,7 @@ async def test_form_select_hub_v1(hass: HomeAssistant) -> None:
|
|||
async def test_form_select_hub_v2(hass: HomeAssistant) -> None:
|
||||
"""Test we set up the Hub v2 correctly."""
|
||||
|
||||
result = await _init_form(hass, HUB2)
|
||||
result = await _init_form(hass, STEP_HUB_V2)
|
||||
|
||||
result2, mock_setup, mock_setup_entry = await _device_form(
|
||||
hass, result["flow_id"], mock_successful_connection, MOCK_USER_INPUT_HUB_V2
|
||||
|
@ -175,10 +197,32 @@ async def test_form_select_hub_v2(hass: HomeAssistant) -> None:
|
|||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_form_discovery_dhcp(hass: HomeAssistant) -> None:
|
||||
"""Test the discovery of the Hub via DHCP."""
|
||||
discovery_info = dhcp.DhcpServiceInfo("1.2.3.4", "", "aa:bb:cc:dd:ee:ff")
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_DHCP}, data=discovery_info
|
||||
)
|
||||
assert result["type"] == data_entry_flow.FlowResultType.MENU
|
||||
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{"next_step_id": STEP_HUB_V2},
|
||||
)
|
||||
assert result2["type"] == data_entry_flow.FlowResultType.FORM
|
||||
schema = convert(result2["data_schema"])
|
||||
found_host = False
|
||||
for field in schema:
|
||||
if field["name"] == CONF_HOST:
|
||||
assert field["default"] == "1.2.3.4"
|
||||
found_host = True
|
||||
assert found_host
|
||||
|
||||
|
||||
async def test_failed_connection_plm(hass: HomeAssistant) -> None:
|
||||
"""Test a failed connection with the PLM."""
|
||||
|
||||
result = await _init_form(hass, PLM)
|
||||
result = await _init_form(hass, STEP_PLM)
|
||||
|
||||
result2, _, _ = await _device_form(
|
||||
hass, result["flow_id"], mock_failed_connection, MOCK_USER_INPUT_PLM
|
||||
|
@ -190,7 +234,7 @@ async def test_failed_connection_plm(hass: HomeAssistant) -> None:
|
|||
async def test_failed_connection_hub(hass: HomeAssistant) -> None:
|
||||
"""Test a failed connection with a Hub."""
|
||||
|
||||
result = await _init_form(hass, HUB2)
|
||||
result = await _init_form(hass, STEP_HUB_V2)
|
||||
|
||||
result2, _, _ = await _device_form(
|
||||
hass, result["flow_id"], mock_failed_connection, MOCK_USER_INPUT_HUB_V2
|
||||
|
@ -228,12 +272,12 @@ async def _options_init_form(hass, entry_id, step):
|
|||
with patch(PATCH_ASYNC_SETUP_ENTRY, return_value=True):
|
||||
result = await hass.config_entries.options.async_init(entry_id)
|
||||
|
||||
assert result["type"] == data_entry_flow.FlowResultType.FORM
|
||||
assert result["type"] == data_entry_flow.FlowResultType.MENU
|
||||
assert result["step_id"] == "init"
|
||||
|
||||
result2 = await hass.config_entries.options.async_configure(
|
||||
result["flow_id"],
|
||||
{step: True},
|
||||
{"next_step_id": step},
|
||||
)
|
||||
return result2
|
||||
|
||||
|
@ -307,10 +351,18 @@ async def test_import_failed_connection(hass: HomeAssistant) -> None:
|
|||
assert result["reason"] == "cannot_connect"
|
||||
|
||||
|
||||
async def _options_form(hass, flow_id, user_input):
|
||||
async def _options_form(
|
||||
hass, flow_id, user_input, connection=mock_successful_connection
|
||||
):
|
||||
"""Test an options form."""
|
||||
|
||||
with patch(PATCH_ASYNC_SETUP_ENTRY, return_value=True) as mock_setup_entry:
|
||||
mock_devices = MockDevices(connected=True)
|
||||
await mock_devices.async_load()
|
||||
mock_devices.modem = mock_devices["AA.AA.AA"]
|
||||
with patch(PATCH_CONNECTION, new=connection), patch(
|
||||
PATCH_ASYNC_SETUP_ENTRY, return_value=True
|
||||
) as mock_setup_entry, patch(PATCH_DEVICES, mock_devices), patch(
|
||||
PATCH_CONNECTION_CLOSE
|
||||
):
|
||||
result = await hass.config_entries.options.async_configure(flow_id, user_input)
|
||||
return result, mock_setup_entry
|
||||
|
||||
|
@ -336,12 +388,39 @@ async def test_options_change_hub_config(hass: HomeAssistant) -> None:
|
|||
CONF_PASSWORD: "new password",
|
||||
}
|
||||
result, _ = await _options_form(hass, result["flow_id"], user_input)
|
||||
|
||||
assert result["type"] == data_entry_flow.FlowResultType.CREATE_ENTRY
|
||||
assert config_entry.options == {}
|
||||
assert config_entry.data == {**user_input, CONF_HUB_VERSION: 2}
|
||||
|
||||
|
||||
async def test_options_change_hub_bad_config(hass: HomeAssistant) -> None:
|
||||
"""Test changing Hub v2 with bad config."""
|
||||
config_entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
entry_id="abcde12345",
|
||||
data={**MOCK_USER_INPUT_HUB_V2, CONF_HUB_VERSION: 2},
|
||||
options={},
|
||||
)
|
||||
|
||||
config_entry.add_to_hass(hass)
|
||||
result = await _options_init_form(
|
||||
hass, config_entry.entry_id, STEP_CHANGE_HUB_CONFIG
|
||||
)
|
||||
|
||||
user_input = {
|
||||
CONF_HOST: "2.3.4.5",
|
||||
CONF_PORT: 9999,
|
||||
CONF_USERNAME: "new username",
|
||||
CONF_PASSWORD: "new password",
|
||||
}
|
||||
result, _ = await _options_form(
|
||||
hass, result["flow_id"], user_input, mock_failed_connection
|
||||
)
|
||||
|
||||
assert result["type"] == data_entry_flow.FlowResultType.FORM
|
||||
assert result["errors"]["base"] == "cannot_connect"
|
||||
|
||||
|
||||
async def test_options_change_plm_config(hass: HomeAssistant) -> None:
|
||||
"""Test changing PLM config."""
|
||||
config_entry = MockConfigEntry(
|
||||
|
@ -356,7 +435,7 @@ async def test_options_change_plm_config(hass: HomeAssistant) -> None:
|
|||
hass, config_entry.entry_id, STEP_CHANGE_PLM_CONFIG
|
||||
)
|
||||
|
||||
user_input = {CONF_DEVICE: "/dev/some_other_device"}
|
||||
user_input = {CONF_DEVICE: "/dev/ttyUSB0"}
|
||||
result, _ = await _options_form(hass, result["flow_id"], user_input)
|
||||
|
||||
assert result["type"] == data_entry_flow.FlowResultType.CREATE_ENTRY
|
||||
|
@ -364,6 +443,31 @@ async def test_options_change_plm_config(hass: HomeAssistant) -> None:
|
|||
assert config_entry.data == user_input
|
||||
|
||||
|
||||
async def test_options_change_plm_bad_config(hass: HomeAssistant) -> None:
|
||||
"""Test changing PLM config."""
|
||||
config_entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
entry_id="abcde12345",
|
||||
data=MOCK_USER_INPUT_PLM,
|
||||
options={},
|
||||
)
|
||||
|
||||
config_entry.add_to_hass(hass)
|
||||
result = await _options_init_form(
|
||||
hass, config_entry.entry_id, STEP_CHANGE_PLM_CONFIG
|
||||
)
|
||||
|
||||
user_input = {CONF_DEVICE: "/dev/ttyUSB0"}
|
||||
result, _ = await _options_form(
|
||||
hass, result["flow_id"], user_input, mock_failed_connection
|
||||
)
|
||||
|
||||
assert result["type"] == data_entry_flow.FlowResultType.FORM
|
||||
|
||||
assert result["type"] == data_entry_flow.FlowResultType.FORM
|
||||
assert result["errors"]["base"] == "cannot_connect"
|
||||
|
||||
|
||||
async def test_options_add_device_override(hass: HomeAssistant) -> None:
|
||||
"""Test adding a device override."""
|
||||
config_entry = MockConfigEntry(
|
||||
|
@ -581,28 +685,6 @@ async def test_options_remove_x10_device_with_override(hass: HomeAssistant) -> N
|
|||
assert len(config_entry.options[CONF_OVERRIDE]) == 1
|
||||
|
||||
|
||||
async def test_options_dup_selection(hass: HomeAssistant) -> None:
|
||||
"""Test if a duplicate selection was made in options."""
|
||||
config_entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
entry_id="abcde12345",
|
||||
data={**MOCK_USER_INPUT_HUB_V2, CONF_HUB_VERSION: 2},
|
||||
options={},
|
||||
)
|
||||
config_entry.add_to_hass(hass)
|
||||
result = await hass.config_entries.options.async_init(config_entry.entry_id)
|
||||
|
||||
assert result["type"] == data_entry_flow.FlowResultType.FORM
|
||||
assert result["step_id"] == "init"
|
||||
|
||||
result2 = await hass.config_entries.options.async_configure(
|
||||
result["flow_id"],
|
||||
{STEP_ADD_OVERRIDE: True, STEP_ADD_X10: True},
|
||||
)
|
||||
assert result2["type"] == data_entry_flow.FlowResultType.FORM
|
||||
assert result2["errors"] == {"base": "select_single"}
|
||||
|
||||
|
||||
async def test_options_override_bad_data(hass: HomeAssistant) -> None:
|
||||
"""Test for bad data in a device override."""
|
||||
|
||||
|
@ -644,9 +726,7 @@ async def test_discovery_via_usb(hass: HomeAssistant) -> None:
|
|||
assert result["type"] == data_entry_flow.FlowResultType.FORM
|
||||
assert result["step_id"] == "confirm_usb"
|
||||
|
||||
with patch("homeassistant.components.insteon.config_flow.async_connect"), patch(
|
||||
"homeassistant.components.insteon.async_setup_entry", return_value=True
|
||||
):
|
||||
with patch(PATCH_CONNECTION), patch(PATCH_ASYNC_SETUP, return_value=True):
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={}
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue