Skip to content

Commit 72fc863

Browse files
committed
fix(esphome): polish unreachable reconfigure confirmation
1 parent 873b806 commit 72fc863

2 files changed

Lines changed: 38 additions & 16 deletions

File tree

homeassistant/components/esphome/config_flow.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from collections import OrderedDict
44
from collections.abc import Mapping
5+
from ipaddress import IPv6Address, ip_address
56
import json
67
import logging
78
from typing import Any, cast
@@ -69,6 +70,17 @@
6970
DEFAULT_NAME = "ESPHome"
7071

7172

73+
def _format_host_for_display(host: str) -> str:
74+
"""Return host formatted for host:port display."""
75+
try:
76+
address = ip_address(host)
77+
except ValueError:
78+
return host
79+
if isinstance(address, IPv6Address):
80+
return f"[{host}]"
81+
return host
82+
83+
7284
class EsphomeFlowHandler(ConfigFlow, domain=DOMAIN):
7385
"""Handle a esphome config flow."""
7486

@@ -272,14 +284,14 @@ async def _async_try_fetch_device_info(self) -> ConfigFlowResult:
272284
if (
273285
self.source == SOURCE_RECONFIGURE
274286
and response in ("connection_error", "resolve_error")
275-
and self._async_reconfigure_host_changed()
287+
and self._async_reconfigure_connection_changed()
276288
):
277289
return await self.async_step_reconfigure_confirm_unreachable()
278290
return await self._async_step_user_base(error=response)
279291
return await self._async_authenticate_or_add()
280292

281293
@callback
282-
def _async_reconfigure_host_changed(self) -> bool:
294+
def _async_reconfigure_connection_changed(self) -> bool:
283295
"""Return if the reconfigure flow has a new host or port."""
284296
assert self._host is not None
285297
assert self._port is not None
@@ -307,11 +319,9 @@ async def async_step_reconfigure_confirm_unreachable(
307319
return self.async_show_form(
308320
step_id="reconfigure_confirm_unreachable",
309321
description_placeholders={
310-
"host": self._host,
311-
"name": self._reconfig_entry.data.get(
312-
CONF_DEVICE_NAME, self._reconfig_entry.title
313-
),
314-
"port": self._port,
322+
"host": _format_host_for_display(self._host),
323+
"name": self._async_get_human_readable_name(),
324+
"port": str(self._port),
315325
},
316326
)
317327

tests/components/esphome/test_config_flow.py

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2391,12 +2391,24 @@ async def test_reconfig_success_with_new_ip_same_name(
23912391

23922392

23932393
@pytest.mark.usefixtures("mock_zeroconf", "mock_setup_entry")
2394-
async def test_reconfig_can_save_changed_unreachable_host(
2395-
hass: HomeAssistant, mock_client: APIClient
2394+
@pytest.mark.parametrize(
2395+
("host", "error", "placeholder_host"),
2396+
[
2397+
("127.0.0.2", APIConnectionError, "127.0.0.2"),
2398+
("2001:db8::2", ResolveAPIError, "[2001:db8::2]"),
2399+
],
2400+
)
2401+
async def test_reconfig_can_save_changed_unreachable_connection(
2402+
hass: HomeAssistant,
2403+
mock_client: APIClient,
2404+
host: str,
2405+
error: type[Exception],
2406+
placeholder_host: str,
23962407
) -> None:
2397-
"""Test reconfig can save a changed host when the device is unreachable."""
2408+
"""Test reconfig can save changed connection details when unreachable."""
23982409
entry = MockConfigEntry(
23992410
domain=DOMAIN,
2411+
title="Kitchen Sensor",
24002412
data={
24012413
CONF_HOST: "127.0.0.1",
24022414
CONF_PORT: 6053,
@@ -2410,17 +2422,17 @@ async def test_reconfig_can_save_changed_unreachable_host(
24102422

24112423
result = await entry.start_reconfigure_flow(hass)
24122424

2413-
mock_client.device_info.side_effect = APIConnectionError
2425+
mock_client.device_info.side_effect = error
24142426
result = await hass.config_entries.flow.async_configure(
2415-
result["flow_id"], user_input={CONF_HOST: "127.0.0.2", CONF_PORT: 6053}
2427+
result["flow_id"], user_input={CONF_HOST: host, CONF_PORT: 6053}
24162428
)
24172429

24182430
assert result["type"] is FlowResultType.FORM
24192431
assert result["step_id"] == "reconfigure_confirm_unreachable"
24202432
assert result["description_placeholders"] == {
2421-
"host": "127.0.0.2",
2422-
"name": "test",
2423-
"port": 6053,
2433+
"host": placeholder_host,
2434+
"name": "Kitchen Sensor",
2435+
"port": "6053",
24242436
}
24252437
assert entry.data[CONF_HOST] == "127.0.0.1"
24262438

@@ -2431,7 +2443,7 @@ async def test_reconfig_can_save_changed_unreachable_host(
24312443
assert result["type"] is FlowResultType.ABORT
24322444
assert result["reason"] == "reconfigure_successful"
24332445
assert entry.data == {
2434-
CONF_HOST: "127.0.0.2",
2446+
CONF_HOST: host,
24352447
CONF_PORT: 6053,
24362448
CONF_PASSWORD: "",
24372449
CONF_DEVICE_NAME: "test",

0 commit comments

Comments
 (0)