From 9239ace1c8fb346b95e5a5665d01cc6e35a4b7f5 Mon Sep 17 00:00:00 2001 From: Petar Petrov Date: Mon, 14 Apr 2025 11:24:01 +0300 Subject: [PATCH] Config flow progress in percent (#142737) * Config flow progress in percent * PR comments --- homeassistant/data_entry_flow.py | 9 +++++++++ tests/test_data_entry_flow.py | 17 +++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/homeassistant/data_entry_flow.py b/homeassistant/data_entry_flow.py index e2e31ffce29..9286f9c78f5 100644 --- a/homeassistant/data_entry_flow.py +++ b/homeassistant/data_entry_flow.py @@ -40,6 +40,7 @@ class FlowResultType(StrEnum): # Event that is fired when a flow is progressed via external or progress source. EVENT_DATA_ENTRY_FLOW_PROGRESSED = "data_entry_flow_progressed" +EVENT_DATA_ENTRY_FLOW_PROGRESS_UPDATE = "data_entry_flow_progress_update" FLOW_NOT_COMPLETE_STEPS = { FlowResultType.FORM, @@ -829,6 +830,14 @@ class FlowHandler(Generic[_FlowContextT, _FlowResultT, _HandlerT]): flow_result["step_id"] = step_id return flow_result + @callback + def async_update_progress(self, progress: float) -> None: + """Update the progress of a flow. `progress` must be between 0 and 1.""" + self.hass.bus.async_fire_internal( + EVENT_DATA_ENTRY_FLOW_PROGRESS_UPDATE, + {"handler": self.handler, "flow_id": self.flow_id, "progress": progress}, + ) + @callback def async_show_progress_done(self, *, next_step_id: str) -> _FlowResultT: """Mark the progress done.""" diff --git a/tests/test_data_entry_flow.py b/tests/test_data_entry_flow.py index 804b1fea405..961afd69c2d 100644 --- a/tests/test_data_entry_flow.py +++ b/tests/test_data_entry_flow.py @@ -464,6 +464,9 @@ async def test_show_progress(hass: HomeAssistant, manager: MockFlowManager) -> N """Test show progress logic.""" manager.hass = hass events = [] + progress_update_events = async_capture_events( + hass, data_entry_flow.EVENT_DATA_ENTRY_FLOW_PROGRESS_UPDATE + ) task_one_evt = asyncio.Event() task_two_evt = asyncio.Event() event_received_evt = asyncio.Event() @@ -486,7 +489,9 @@ async def test_show_progress(hass: HomeAssistant, manager: MockFlowManager) -> N await task_one_evt.wait() async def long_running_job_two() -> None: + self.async_update_progress(0.25) await task_two_evt.wait() + self.async_update_progress(0.75) self.data = {"title": "Hello"} uncompleted_task: asyncio.Task[None] | None = None @@ -545,6 +550,12 @@ async def test_show_progress(hass: HomeAssistant, manager: MockFlowManager) -> N result = await manager.async_configure(result["flow_id"]) assert result["type"] == data_entry_flow.FlowResultType.SHOW_PROGRESS assert result["progress_action"] == "task_two" + assert len(progress_update_events) == 1 + assert progress_update_events[0].data == { + "handler": "test", + "flow_id": result["flow_id"], + "progress": 0.25, + } # Set task two done and wait for event task_two_evt.set() @@ -556,6 +567,12 @@ async def test_show_progress(hass: HomeAssistant, manager: MockFlowManager) -> N "flow_id": result["flow_id"], "refresh": True, } + assert len(progress_update_events) == 2 + assert progress_update_events[1].data == { + "handler": "test", + "flow_id": result["flow_id"], + "progress": 0.75, + } # Frontend refreshes the flow result = await manager.async_configure(result["flow_id"])