Move Insteon configuration panel to config entry (#105581)

* Move Insteon panel to the config menu

* Bump pyinsteon to 1.5.3

* Undo devcontainer.json changes

* Bump Insteon frontend

* Update config_flow.py

* Code cleanup

* Code review changes

* Fix failing tests

* Fix format

* Remove unnecessary exception

* codecov

* Remove return from try

* Fix merge mistake

---------

Co-authored-by: Erik Montnemery <erik@montnemery.com>
This commit is contained in:
Tom Harris 2024-04-16 03:10:32 -04:00 committed by GitHub
parent 1dfabf34c4
commit c5c407b3bb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 988 additions and 766 deletions

View file

@ -8,38 +8,14 @@ from voluptuous_serialize import convert
from homeassistant import config_entries
from homeassistant.components import dhcp, usb
from homeassistant.components.insteon.config_flow import (
STEP_ADD_OVERRIDE,
STEP_ADD_X10,
STEP_CHANGE_HUB_CONFIG,
STEP_CHANGE_PLM_CONFIG,
STEP_HUB_V1,
STEP_HUB_V2,
STEP_PLM,
STEP_PLM_MANUALLY,
STEP_REMOVE_OVERRIDE,
STEP_REMOVE_X10,
)
from homeassistant.components.insteon.const import (
CONF_CAT,
CONF_DIM_STEPS,
CONF_HOUSECODE,
CONF_HUB_VERSION,
CONF_OVERRIDE,
CONF_SUBCAT,
CONF_UNITCODE,
CONF_X10,
DOMAIN,
)
from homeassistant.components.insteon.const import CONF_HUB_VERSION, DOMAIN
from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import (
CONF_ADDRESS,
CONF_DEVICE,
CONF_HOST,
CONF_PASSWORD,
CONF_PLATFORM,
CONF_PORT,
CONF_USERNAME,
)
from homeassistant.const import CONF_DEVICE, CONF_HOST
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType
@ -52,11 +28,8 @@ 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
@ -294,379 +267,6 @@ async def test_failed_connection_hub(hass: HomeAssistant) -> None:
assert result2["errors"] == {"base": "cannot_connect"}
async def _options_init_form(hass, entry_id, step):
"""Run the init options form."""
with patch(PATCH_ASYNC_SETUP_ENTRY, return_value=True):
result = await hass.config_entries.options.async_init(entry_id)
assert result["type"] is FlowResultType.MENU
assert result["step_id"] == "init"
return await hass.config_entries.options.async_configure(
result["flow_id"],
{"next_step_id": step},
)
async def _options_form(
hass, flow_id, user_input, connection=mock_successful_connection
):
"""Test an options form."""
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
async def test_options_change_hub_config(hass: HomeAssistant) -> None:
"""Test changing Hub v2 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)
assert result["type"] is 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"] is 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(
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)
assert result["type"] is FlowResultType.CREATE_ENTRY
assert config_entry.options == {}
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"] is FlowResultType.FORM
assert result["type"] is 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(
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_ADD_OVERRIDE)
user_input = {
CONF_ADDRESS: "1a2b3c",
CONF_CAT: "0x04",
CONF_SUBCAT: "0xaa",
}
result, _ = await _options_form(hass, result["flow_id"], user_input)
assert result["type"] is FlowResultType.CREATE_ENTRY
assert len(config_entry.options[CONF_OVERRIDE]) == 1
assert config_entry.options[CONF_OVERRIDE][0][CONF_ADDRESS] == "1A.2B.3C"
assert config_entry.options[CONF_OVERRIDE][0][CONF_CAT] == 4
assert config_entry.options[CONF_OVERRIDE][0][CONF_SUBCAT] == 170
result2 = await _options_init_form(hass, config_entry.entry_id, STEP_ADD_OVERRIDE)
user_input = {
CONF_ADDRESS: "4d5e6f",
CONF_CAT: "05",
CONF_SUBCAT: "bb",
}
result3, _ = await _options_form(hass, result2["flow_id"], user_input)
assert len(config_entry.options[CONF_OVERRIDE]) == 2
assert config_entry.options[CONF_OVERRIDE][1][CONF_ADDRESS] == "4D.5E.6F"
assert config_entry.options[CONF_OVERRIDE][1][CONF_CAT] == 5
assert config_entry.options[CONF_OVERRIDE][1][CONF_SUBCAT] == 187
# If result1 eq result2 the changes will not save
assert result["data"] != result3["data"]
async def test_options_remove_device_override(hass: HomeAssistant) -> None:
"""Test removing a device override."""
config_entry = MockConfigEntry(
domain=DOMAIN,
entry_id="abcde12345",
data={**MOCK_USER_INPUT_HUB_V2, CONF_HUB_VERSION: 2},
options={
CONF_OVERRIDE: [
{CONF_ADDRESS: "1A.2B.3C", CONF_CAT: 6, CONF_SUBCAT: 100},
{CONF_ADDRESS: "4D.5E.6F", CONF_CAT: 7, CONF_SUBCAT: 200},
]
},
)
config_entry.add_to_hass(hass)
result = await _options_init_form(hass, config_entry.entry_id, STEP_REMOVE_OVERRIDE)
user_input = {CONF_ADDRESS: "1A.2B.3C"}
result, _ = await _options_form(hass, result["flow_id"], user_input)
assert result["type"] is FlowResultType.CREATE_ENTRY
assert len(config_entry.options[CONF_OVERRIDE]) == 1
async def test_options_remove_device_override_with_x10(hass: HomeAssistant) -> None:
"""Test removing a device override when an X10 device is configured."""
config_entry = MockConfigEntry(
domain=DOMAIN,
entry_id="abcde12345",
data={**MOCK_USER_INPUT_HUB_V2, CONF_HUB_VERSION: 2},
options={
CONF_OVERRIDE: [
{CONF_ADDRESS: "1A.2B.3C", CONF_CAT: 6, CONF_SUBCAT: 100},
{CONF_ADDRESS: "4D.5E.6F", CONF_CAT: 7, CONF_SUBCAT: 200},
],
CONF_X10: [
{
CONF_HOUSECODE: "d",
CONF_UNITCODE: 5,
CONF_PLATFORM: "light",
CONF_DIM_STEPS: 22,
}
],
},
)
config_entry.add_to_hass(hass)
result = await _options_init_form(hass, config_entry.entry_id, STEP_REMOVE_OVERRIDE)
user_input = {CONF_ADDRESS: "1A.2B.3C"}
result, _ = await _options_form(hass, result["flow_id"], user_input)
assert result["type"] is FlowResultType.CREATE_ENTRY
assert len(config_entry.options[CONF_OVERRIDE]) == 1
assert len(config_entry.options[CONF_X10]) == 1
async def test_options_add_x10_device(hass: HomeAssistant) -> None:
"""Test adding an X10 device."""
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_ADD_X10)
user_input = {
CONF_HOUSECODE: "c",
CONF_UNITCODE: 12,
CONF_PLATFORM: "light",
CONF_DIM_STEPS: 18,
}
result2, _ = await _options_form(hass, result["flow_id"], user_input)
assert result2["type"] is FlowResultType.CREATE_ENTRY
assert len(config_entry.options[CONF_X10]) == 1
assert config_entry.options[CONF_X10][0][CONF_HOUSECODE] == "c"
assert config_entry.options[CONF_X10][0][CONF_UNITCODE] == 12
assert config_entry.options[CONF_X10][0][CONF_PLATFORM] == "light"
assert config_entry.options[CONF_X10][0][CONF_DIM_STEPS] == 18
result = await _options_init_form(hass, config_entry.entry_id, STEP_ADD_X10)
user_input = {
CONF_HOUSECODE: "d",
CONF_UNITCODE: 10,
CONF_PLATFORM: "binary_sensor",
CONF_DIM_STEPS: 15,
}
result3, _ = await _options_form(hass, result["flow_id"], user_input)
assert result3["type"] is FlowResultType.CREATE_ENTRY
assert len(config_entry.options[CONF_X10]) == 2
assert config_entry.options[CONF_X10][1][CONF_HOUSECODE] == "d"
assert config_entry.options[CONF_X10][1][CONF_UNITCODE] == 10
assert config_entry.options[CONF_X10][1][CONF_PLATFORM] == "binary_sensor"
assert config_entry.options[CONF_X10][1][CONF_DIM_STEPS] == 15
# If result2 eq result3 the changes will not save
assert result2["data"] != result3["data"]
async def test_options_remove_x10_device(hass: HomeAssistant) -> None:
"""Test removing an X10 device."""
config_entry = MockConfigEntry(
domain=DOMAIN,
entry_id="abcde12345",
data={**MOCK_USER_INPUT_HUB_V2, CONF_HUB_VERSION: 2},
options={
CONF_X10: [
{
CONF_HOUSECODE: "C",
CONF_UNITCODE: 4,
CONF_PLATFORM: "light",
CONF_DIM_STEPS: 18,
},
{
CONF_HOUSECODE: "D",
CONF_UNITCODE: 10,
CONF_PLATFORM: "binary_sensor",
CONF_DIM_STEPS: 15,
},
]
},
)
config_entry.add_to_hass(hass)
result = await _options_init_form(hass, config_entry.entry_id, STEP_REMOVE_X10)
user_input = {CONF_DEVICE: "Housecode: C, Unitcode: 4"}
result, _ = await _options_form(hass, result["flow_id"], user_input)
assert result["type"] is FlowResultType.CREATE_ENTRY
assert len(config_entry.options[CONF_X10]) == 1
async def test_options_remove_x10_device_with_override(hass: HomeAssistant) -> None:
"""Test removing an X10 device when a device override is configured."""
config_entry = MockConfigEntry(
domain=DOMAIN,
entry_id="abcde12345",
data={**MOCK_USER_INPUT_HUB_V2, CONF_HUB_VERSION: 2},
options={
CONF_X10: [
{
CONF_HOUSECODE: "C",
CONF_UNITCODE: 4,
CONF_PLATFORM: "light",
CONF_DIM_STEPS: 18,
},
{
CONF_HOUSECODE: "D",
CONF_UNITCODE: 10,
CONF_PLATFORM: "binary_sensor",
CONF_DIM_STEPS: 15,
},
],
CONF_OVERRIDE: [{CONF_ADDRESS: "1A.2B.3C", CONF_CAT: 1, CONF_SUBCAT: 18}],
},
)
config_entry.add_to_hass(hass)
result = await _options_init_form(hass, config_entry.entry_id, STEP_REMOVE_X10)
user_input = {CONF_DEVICE: "Housecode: C, Unitcode: 4"}
result, _ = await _options_form(hass, result["flow_id"], user_input)
assert result["type"] is FlowResultType.CREATE_ENTRY
assert len(config_entry.options[CONF_X10]) == 1
assert len(config_entry.options[CONF_OVERRIDE]) == 1
async def test_options_override_bad_data(hass: HomeAssistant) -> None:
"""Test for bad data in a device override."""
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_ADD_OVERRIDE)
user_input = {
CONF_ADDRESS: "zzzzzz",
CONF_CAT: "bad",
CONF_SUBCAT: "data",
}
result, _ = await _options_form(hass, result["flow_id"], user_input)
assert result["type"] is FlowResultType.FORM
assert result["errors"] == {"base": "input_error"}
async def test_discovery_via_usb(hass: HomeAssistant) -> None:
"""Test usb flow."""
discovery_info = usb.UsbServiceInfo(