Add reconfig flow to bosch_alarm (#142451)

* add reconfig flow to bosch_alarm

* change translation string key

* change translation string key

* cleanup

* cleanup

* Update homeassistant/components/bosch_alarm/config_flow.py

Co-authored-by: Josef Zweck <josef@zweck.dev>

* fix linting

---------

Co-authored-by: Josef Zweck <josef@zweck.dev>
This commit is contained in:
Sanjay Govind 2025-04-08 18:22:39 +12:00 committed by GitHub
parent 8dee5851d2
commit cb07e64b47
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 120 additions and 6 deletions

View File

@ -11,7 +11,12 @@ from typing import Any
from bosch_alarm_mode2 import Panel
import voluptuous as vol
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
from homeassistant.config_entries import (
SOURCE_RECONFIGURE,
SOURCE_USER,
ConfigFlow,
ConfigFlowResult,
)
from homeassistant.const import (
CONF_CODE,
CONF_HOST,
@ -108,6 +113,13 @@ class BoschAlarmConfigFlow(ConfigFlow, domain=DOMAIN):
else:
self._data = user_input
self._data[CONF_MODEL] = model
if self.source == SOURCE_RECONFIGURE:
if (
self._get_reconfigure_entry().data[CONF_MODEL]
!= self._data[CONF_MODEL]
):
return self.async_abort(reason="device_mismatch")
return await self.async_step_auth()
return self.async_show_form(
step_id="user",
@ -117,6 +129,12 @@ class BoschAlarmConfigFlow(ConfigFlow, domain=DOMAIN):
errors=errors,
)
async def async_step_reconfigure(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Handle the reconfigure step."""
return await self.async_step_user()
async def async_step_auth(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
@ -154,10 +172,22 @@ class BoschAlarmConfigFlow(ConfigFlow, domain=DOMAIN):
else:
if serial_number:
await self.async_set_unique_id(str(serial_number))
self._abort_if_unique_id_configured()
else:
self._async_abort_entries_match({CONF_HOST: self._data[CONF_HOST]})
return self.async_create_entry(title=f"Bosch {model}", data=self._data)
if self.source == SOURCE_USER:
if serial_number:
self._abort_if_unique_id_configured()
else:
self._async_abort_entries_match(
{CONF_HOST: self._data[CONF_HOST]}
)
return self.async_create_entry(
title=f"Bosch {model}", data=self._data
)
if serial_number:
self._abort_if_unique_id_mismatch(reason="device_mismatch")
return self.async_update_reload_and_abort(
self._get_reconfigure_entry(),
data=self._data,
)
return self.async_show_form(
step_id="auth",

View File

@ -43,7 +43,9 @@
},
"abort": {
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]",
"reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]"
"reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]",
"reconfigure_successful": "[%key:common::config_flow::abort::reconfigure_successful%]",
"device_mismatch": "Please ensure you reconfigure against the same device."
}
},
"exceptions": {

View File

@ -283,3 +283,85 @@ async def test_reauth_flow_error(
assert result["reason"] == "reauth_successful"
compare = {**mock_config_entry.data, **config_flow_data}
assert compare == mock_config_entry.data
async def test_reconfig_flow(
hass: HomeAssistant,
mock_setup_entry: AsyncMock,
mock_config_entry: MockConfigEntry,
mock_panel: AsyncMock,
model_name: str,
serial_number: str,
config_flow_data: dict[str, Any],
) -> None:
"""Test reconfig auth."""
await setup_integration(hass, mock_config_entry)
config_flow_data = {k: f"{v}2" for k, v in config_flow_data.items()}
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={
"source": config_entries.SOURCE_RECONFIGURE,
"entry_id": mock_config_entry.entry_id,
},
)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "user"
assert result["errors"] == {}
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_HOST: "1.1.1.1", CONF_PORT: 7700},
)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "auth"
assert result["errors"] == {}
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
config_flow_data,
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "reconfigure_successful"
assert mock_config_entry.data == {
CONF_HOST: "1.1.1.1",
CONF_PORT: 7700,
CONF_MODEL: model_name,
**config_flow_data,
}
@pytest.mark.parametrize("model", ["b5512"])
async def test_reconfig_flow_incorrect_model(
hass: HomeAssistant,
mock_setup_entry: AsyncMock,
mock_config_entry: MockConfigEntry,
mock_panel: AsyncMock,
model_name: str,
serial_number: str,
config_flow_data: dict[str, Any],
) -> None:
"""Test reconfig fails with a different device."""
await setup_integration(hass, mock_config_entry)
config_flow_data = {k: f"{v}2" for k, v in config_flow_data.items()}
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={
"source": config_entries.SOURCE_RECONFIGURE,
"entry_id": mock_config_entry.entry_id,
},
)
mock_panel.model = "Solution 3000"
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "user"
assert result["errors"] == {}
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_HOST: "0.0.0.0", CONF_PORT: 7700},
)
await hass.async_block_till_done()
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "device_mismatch"