Add reload support to schema options flow handler

This commit is contained in:
G Johansson
2025-08-26 19:47:27 +00:00
parent 87f0703be1
commit f3e2f99c8f
2 changed files with 87 additions and 1 deletions

View File

@@ -16,6 +16,7 @@ from homeassistant.config_entries import (
ConfigFlow, ConfigFlow,
ConfigFlowResult, ConfigFlowResult,
OptionsFlow, OptionsFlow,
OptionsFlowWithReload,
) )
from homeassistant.core import HomeAssistant, callback, split_entity_id from homeassistant.core import HomeAssistant, callback, split_entity_id
from homeassistant.data_entry_flow import UnknownHandler from homeassistant.data_entry_flow import UnknownHandler
@@ -330,6 +331,7 @@ class SchemaConfigFlowHandler(ConfigFlow, ABC):
config_flow: Mapping[str, SchemaFlowStep] config_flow: Mapping[str, SchemaFlowStep]
options_flow: Mapping[str, SchemaFlowStep] | None = None options_flow: Mapping[str, SchemaFlowStep] | None = None
options_flow_reloads: bool = False
VERSION = 1 VERSION = 1
@@ -345,6 +347,13 @@ class SchemaConfigFlowHandler(ConfigFlow, ABC):
if cls.options_flow is None: if cls.options_flow is None:
raise UnknownHandler raise UnknownHandler
if cls.options_flow_reloads is True:
return SchemaOptionsFlowHandlerWithReload(
config_entry,
cls.options_flow,
cls.async_options_flow_finished,
cls.async_setup_preview,
)
return SchemaOptionsFlowHandler( return SchemaOptionsFlowHandler(
config_entry, config_entry,
cls.options_flow, cls.options_flow,
@@ -498,6 +507,12 @@ class SchemaOptionsFlowHandler(OptionsFlow):
return super().async_create_entry(data=data, **kwargs) return super().async_create_entry(data=data, **kwargs)
class SchemaOptionsFlowHandlerWithReload(
SchemaOptionsFlowHandler, OptionsFlowWithReload
):
"""Handle a schema based options flow which automatically reloads."""
@callback @callback
def wrapped_entity_config_entry_title( def wrapped_entity_config_entry_title(
hass: HomeAssistant, entity_id_or_uuid: str hass: HomeAssistant, entity_id_or_uuid: str

View File

@@ -4,7 +4,7 @@ from __future__ import annotations
from collections.abc import Mapping from collections.abc import Mapping
from typing import Any from typing import Any
from unittest.mock import patch from unittest.mock import AsyncMock, patch
import pytest import pytest
import voluptuous as vol import voluptuous as vol
@@ -789,3 +789,74 @@ async def test_options_flow_omit_optional_keys(
"advanced_default": "a very reasonable default", "advanced_default": "a very reasonable default",
"optional_default": "a very reasonable default", "optional_default": "a very reasonable default",
} }
@pytest.mark.parametrize(
(
"new_options",
"expected_loads",
"expected_unloads",
),
[
({}, 1, 0),
({"some_string": "some_value"}, 2, 1),
],
ids=["should_not_reload", "should_reload"],
)
async def test_options_flow_with_automatic_reload(
hass: HomeAssistant,
manager: data_entry_flow.FlowManager,
new_options: dict[str, str],
expected_loads: int,
expected_unloads: int,
) -> None:
"""Test using options flow with automatic reloading."""
manager.hass = hass
OPTIONS_SCHEMA = vol.Schema({vol.Optional("some_string"): str})
OPTIONS_FLOW: dict[str, SchemaFlowFormStep | SchemaFlowMenuStep] = {
"init": SchemaFlowFormStep(OPTIONS_SCHEMA)
}
class TestFlow(MockSchemaConfigFlowHandler, domain="test"):
config_flow = {}
options_flow = OPTIONS_FLOW
options_flow_reloads = True
load_entry_mock = AsyncMock(return_value=True)
unload_entry_mock = AsyncMock(return_value=True)
mock_integration(
hass,
MockModule(
"test",
async_setup_entry=load_entry_mock,
async_unload_entry=unload_entry_mock,
),
)
mock_platform(hass, "test.config_flow", None)
config_entry = MockConfigEntry(
data={},
domain="test",
options={
"optional_no_default": "abc123",
"optional_default": "not default",
"advanced_no_default": "abc123",
"advanced_default": "not default",
},
)
config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(config_entry.entry_id)
assert len(load_entry_mock.mock_calls) == 1
# Start flow in basic mode
result = await hass.config_entries.options.async_init(config_entry.entry_id)
assert result["type"] == data_entry_flow.FlowResultType.FORM
result = await hass.config_entries.options.async_configure(
result["flow_id"], new_options
)
assert result["type"] == data_entry_flow.FlowResultType.CREATE_ENTRY
assert len(load_entry_mock.mock_calls) == expected_loads
assert len(unload_entry_mock.mock_calls) == expected_unloads