mirror of
https://github.com/home-assistant/core.git
synced 2026-09-27 01:46:11 -04:00
Handle gone next flow in improv_ble provisioning (#182147)
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude
parent
0349bfc8bc
commit
25fc54e50e
@@ -28,7 +28,7 @@ from homeassistant.config_entries import (
|
||||
)
|
||||
from homeassistant.const import CONF_ADDRESS
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.data_entry_flow import AbortFlow
|
||||
from homeassistant.data_entry_flow import AbortFlow, UnknownFlow
|
||||
from homeassistant.helpers.device_registry import format_mac
|
||||
|
||||
from . import async_get_provisioning_futures
|
||||
@@ -407,11 +407,17 @@ class ImprovBLEConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
|
||||
if next_flow_id:
|
||||
_LOGGER.debug("Received next flow ID: %s", next_flow_id)
|
||||
self._provision_result = self.async_abort(
|
||||
reason="provision_successful",
|
||||
next_flow=(FlowType.CONFIG_FLOW, next_flow_id),
|
||||
)
|
||||
return
|
||||
try:
|
||||
self._provision_result = self.async_abort(
|
||||
reason="provision_successful",
|
||||
next_flow=(FlowType.CONFIG_FLOW, next_flow_id),
|
||||
)
|
||||
except UnknownFlow:
|
||||
# The other integration aborted its flow, for example
|
||||
# because the device is already configured
|
||||
_LOGGER.debug("Next flow %s is gone", next_flow_id)
|
||||
else:
|
||||
return
|
||||
|
||||
if redirect_url:
|
||||
self._provision_result = self.async_abort(
|
||||
|
||||
@@ -1108,6 +1108,91 @@ async def test_flow_chaining_with_redirect_url(hass: HomeAssistant) -> None:
|
||||
assert result["next_flow"] == (FlowType.CONFIG_FLOW, esphome_flow_id)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("redirect_url", "expected_reason"),
|
||||
[
|
||||
pytest.param(None, "provision_successful", id="no_redirect_url"),
|
||||
pytest.param(
|
||||
"http://blabla.local", "provision_successful_url", id="redirect_url"
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_flow_chaining_next_flow_gone(
|
||||
hass: HomeAssistant, redirect_url: str | None, expected_reason: str
|
||||
) -> None:
|
||||
"""Test the next flow is aborted before provisioning completes."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": config_entries.SOURCE_BLUETOOTH},
|
||||
data=IMPROV_BLE_DISCOVERY_INFO,
|
||||
)
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["step_id"] == "bluetooth_confirm"
|
||||
|
||||
# Confirm bluetooth setup
|
||||
result = await hass.config_entries.flow.async_configure(result["flow_id"])
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["step_id"] == "bluetooth_confirm"
|
||||
|
||||
# Start provisioning
|
||||
with (
|
||||
patch(
|
||||
f"{IMPROV_BLE}.config_flow.ImprovBLEClient.can_identify",
|
||||
return_value=False,
|
||||
new_callable=PropertyMock,
|
||||
),
|
||||
patch(f"{IMPROV_BLE}.config_flow.ImprovBLEClient.ensure_connected"),
|
||||
):
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{CONF_ADDRESS: IMPROV_BLE_DISCOVERY_INFO.address},
|
||||
)
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["step_id"] == "provision"
|
||||
|
||||
with (
|
||||
patch(
|
||||
f"{IMPROV_BLE}.config_flow.ImprovBLEClient.need_authorization",
|
||||
return_value=False,
|
||||
),
|
||||
patch(
|
||||
f"{IMPROV_BLE}.config_flow.ImprovBLEClient.provision",
|
||||
return_value=redirect_url,
|
||||
),
|
||||
):
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], {"ssid": "TestNetwork", "password": "secret"}
|
||||
)
|
||||
assert result["type"] is FlowResultType.SHOW_PROGRESS
|
||||
assert result["progress_action"] == "provisioning"
|
||||
assert result["step_id"] == "do_provision"
|
||||
|
||||
# Yield to allow the background task to create the future
|
||||
await asyncio.sleep(0) # task is created with eager_start=False
|
||||
|
||||
# Create a dummy target flow using a different device address
|
||||
target_result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": config_entries.SOURCE_BLUETOOTH},
|
||||
data=IMPROV_BLE_DISCOVERY_INFO_TARGET1,
|
||||
)
|
||||
next_config_flow_id = target_result["flow_id"]
|
||||
|
||||
# Simulate another integration registering a flow which it then aborts,
|
||||
# for example because the device is already configured
|
||||
improv_ble.async_register_next_flow(
|
||||
hass, IMPROV_BLE_DISCOVERY_INFO.address, next_config_flow_id
|
||||
)
|
||||
hass.config_entries.flow.async_abort(next_config_flow_id)
|
||||
|
||||
await hass.async_block_till_done()
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(result["flow_id"])
|
||||
assert result["type"] is FlowResultType.ABORT
|
||||
assert result["reason"] == expected_reason
|
||||
assert "next_flow" not in result
|
||||
|
||||
|
||||
async def test_flow_chaining_future_already_done(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
|
||||
) -> None:
|
||||
|
||||
Reference in New Issue
Block a user