Improve Z-Wave reconfigure flow (#142475)

This commit is contained in:
Martin Hjelmare 2025-04-11 12:15:11 +02:00 committed by GitHub
parent 16d9ccd423
commit af8ecdd48d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 123 additions and 5 deletions

View File

@ -23,7 +23,6 @@ from homeassistant.config_entries import (
SOURCE_USB,
ConfigEntry,
ConfigEntryBaseFlow,
ConfigEntryState,
ConfigFlow,
ConfigFlowResult,
OptionsFlow,
@ -787,7 +786,21 @@ class OptionsFlowHandler(BaseZwaveJSFlow, OptionsFlow):
{CONF_USE_ADDON: self.config_entry.data.get(CONF_USE_ADDON, True)}
),
)
if not user_input[CONF_USE_ADDON]:
if self.config_entry.data.get(CONF_USE_ADDON):
# Unload the config entry before stopping the add-on.
await self.hass.config_entries.async_unload(self.config_entry.entry_id)
addon_manager = get_addon_manager(self.hass)
_LOGGER.debug("Stopping Z-Wave JS add-on")
try:
await addon_manager.async_stop_addon()
except AddonError as err:
_LOGGER.error(err)
self.hass.config_entries.async_schedule_reload(
self.config_entry.entry_id
)
raise AbortFlow("addon_stop_failed") from err
return await self.async_step_manual()
addon_info = await self._async_get_addon_info()
@ -840,10 +853,7 @@ class OptionsFlowHandler(BaseZwaveJSFlow, OptionsFlow):
if addon_info.state == AddonState.RUNNING and not self.restart_addon:
return await self.async_step_finish_addon_setup()
if (
self.config_entry.data.get(CONF_USE_ADDON)
and self.config_entry.state == ConfigEntryState.LOADED
):
if self.config_entry.data.get(CONF_USE_ADDON):
# Disconnect integration before restarting add-on.
await self.hass.config_entries.async_unload(self.config_entry.entry_id)

View File

@ -214,6 +214,7 @@
"addon_install_failed": "[%key:component::zwave_js::config::abort::addon_install_failed%]",
"addon_set_config_failed": "[%key:component::zwave_js::config::abort::addon_set_config_failed%]",
"addon_start_failed": "[%key:component::zwave_js::config::abort::addon_start_failed%]",
"addon_stop_failed": "Failed to stop the Z-Wave add-on.",
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]",
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
"different_device": "The connected USB device is not the same as previously configured for this config entry. Please instead create a new config entry for the new device."

View File

@ -70,6 +70,15 @@ def setup_entry_fixture() -> Generator[AsyncMock]:
yield mock_setup_entry
@pytest.fixture(name="unload_entry")
def unload_entry_fixture() -> Generator[AsyncMock]:
"""Mock entry unload."""
with patch(
"homeassistant.components.zwave_js.async_unload_entry", return_value=True
) as mock_unload_entry:
yield mock_unload_entry
@pytest.fixture(name="supervisor")
def mock_supervisor_fixture() -> Generator[None]:
"""Mock Supervisor."""
@ -2038,6 +2047,104 @@ async def test_options_not_addon(
assert client.disconnect.call_count == 1
@pytest.mark.usefixtures("supervisor")
async def test_options_not_addon_with_addon(
hass: HomeAssistant,
setup_entry: AsyncMock,
unload_entry: AsyncMock,
integration: MockConfigEntry,
stop_addon: AsyncMock,
) -> None:
"""Test options flow opting out of add-on on Supervisor with add-on."""
entry = integration
hass.config_entries.async_update_entry(
entry,
data={**entry.data, "url": "ws://host1:3001", "use_addon": True},
unique_id="1234",
)
assert entry.state is config_entries.ConfigEntryState.LOADED
assert unload_entry.call_count == 0
setup_entry.reset_mock()
result = await hass.config_entries.options.async_init(entry.entry_id)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "on_supervisor"
result = await hass.config_entries.options.async_configure(
result["flow_id"], {"use_addon": False}
)
assert entry.state is config_entries.ConfigEntryState.NOT_LOADED
assert setup_entry.call_count == 0
assert unload_entry.call_count == 1
assert stop_addon.call_count == 1
assert stop_addon.call_args == call("core_zwave_js")
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "manual"
result = await hass.config_entries.options.async_configure(
result["flow_id"],
{
"url": "ws://localhost:3000",
},
)
await hass.async_block_till_done()
assert result["type"] is FlowResultType.CREATE_ENTRY
assert entry.data["url"] == "ws://localhost:3000"
assert entry.data["use_addon"] is False
assert entry.data["integration_created_addon"] is False
assert entry.state is config_entries.ConfigEntryState.LOADED
assert setup_entry.call_count == 1
assert unload_entry.call_count == 1
@pytest.mark.usefixtures("supervisor")
async def test_options_not_addon_with_addon_stop_fail(
hass: HomeAssistant,
setup_entry: AsyncMock,
unload_entry: AsyncMock,
integration: MockConfigEntry,
stop_addon: AsyncMock,
) -> None:
"""Test options flow opting out of add-on and add-on stop error."""
stop_addon.side_effect = SupervisorError("Boom!")
entry = integration
hass.config_entries.async_update_entry(
entry,
data={**entry.data, "url": "ws://host1:3001", "use_addon": True},
unique_id="1234",
)
assert entry.state is config_entries.ConfigEntryState.LOADED
assert unload_entry.call_count == 0
setup_entry.reset_mock()
result = await hass.config_entries.options.async_init(entry.entry_id)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "on_supervisor"
result = await hass.config_entries.options.async_configure(
result["flow_id"], {"use_addon": False}
)
await hass.async_block_till_done()
assert stop_addon.call_count == 1
assert stop_addon.call_args == call("core_zwave_js")
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "addon_stop_failed"
assert entry.data["url"] == "ws://host1:3001"
assert entry.data["use_addon"] is True
assert entry.state is config_entries.ConfigEntryState.LOADED
assert setup_entry.call_count == 1
assert unload_entry.call_count == 1
@pytest.mark.parametrize(
(
"discovery_info",