mirror of
https://github.com/home-assistant/core.git
synced 2025-08-30 18:01:31 +02:00
Add reload support to schema options flow handler
This commit is contained in:
@@ -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
|
||||||
|
@@ -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
|
||||||
|
Reference in New Issue
Block a user