Delete optional schema keys, when they are not present (#101755)

Co-authored-by: Erik Montnemery <erik@montnemery.com>
This commit is contained in:
Robert Resch 2023-10-10 21:08:54 +02:00 committed by GitHub
parent c76ce76824
commit b932c67eb7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 105 additions and 2 deletions

View file

@ -171,13 +171,37 @@ class SchemaCommonFlowHandler:
if user_input is not None:
# User input was validated successfully, update options
self._options.update(user_input)
self._update_and_remove_omitted_optional_keys(
self._options, user_input, data_schema
)
if user_input is not None or form_step.schema is None:
return await self._show_next_step_or_create_entry(form_step)
return await self._show_next_step(step_id)
def _update_and_remove_omitted_optional_keys(
self,
values: dict[str, Any],
user_input: dict[str, Any],
data_schema: vol.Schema | None,
) -> None:
values.update(user_input)
if data_schema and data_schema.schema:
for key in data_schema.schema:
if (
isinstance(key, vol.Optional)
and key not in user_input
and not (
# don't remove advanced keys, if they are hidden
key.description
and key.description.get("advanced")
and not self._handler.show_advanced_options
)
):
# Key not present, delete keys old value (if present) too
values.pop(key, None)
async def _show_next_step_or_create_entry(
self, form_step: SchemaFlowFormStep
) -> FlowResult:
@ -221,7 +245,9 @@ class SchemaCommonFlowHandler:
if user_input:
# We don't want to mutate the existing options
suggested_values = copy.deepcopy(suggested_values)
suggested_values.update(user_input)
self._update_and_remove_omitted_optional_keys(
suggested_values, user_input, await self._get_schema(form_step)
)
if data_schema.schema:
# Make a copy of the schema with suggested values set to saved options

View file

@ -671,3 +671,80 @@ async def test_options_flow_state(hass: HomeAssistant) -> None:
"idx_from_flow_state": "blublu",
"option1": "blabla",
}
async def test_options_flow_omit_optional_keys(
hass: HomeAssistant, manager: data_entry_flow.FlowManager
) -> None:
"""Test handling of advanced options in options flow."""
manager.hass = hass
OPTIONS_SCHEMA = vol.Schema(
{
vol.Optional("optional_no_default"): str,
vol.Optional("optional_default", default="a very reasonable default"): str,
vol.Optional("advanced_no_default", description={"advanced": True}): str,
vol.Optional(
"advanced_default",
default="a very reasonable default",
description={"advanced": True},
): str,
}
)
OPTIONS_FLOW: dict[str, SchemaFlowFormStep | SchemaFlowMenuStep] = {
"init": SchemaFlowFormStep(OPTIONS_SCHEMA)
}
class TestFlow(MockSchemaConfigFlowHandler, domain="test"):
config_flow = {}
options_flow = OPTIONS_FLOW
mock_integration(hass, MockModule("test"))
mock_entity_platform(hass, "config_flow.test", 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)
# 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
assert list(result["data_schema"].schema.keys()) == [
"optional_no_default",
"optional_default",
]
result = await hass.config_entries.options.async_configure(result["flow_id"], {})
assert result["type"] == data_entry_flow.FlowResultType.CREATE_ENTRY
assert result["data"] == {
"advanced_default": "not default",
"advanced_no_default": "abc123",
"optional_default": "a very reasonable default",
}
# Start flow in advanced mode
result = await hass.config_entries.options.async_init(
config_entry.entry_id, context={"show_advanced_options": True}
)
assert result["type"] == data_entry_flow.FlowResultType.FORM
assert list(result["data_schema"].schema.keys()) == [
"optional_no_default",
"optional_default",
"advanced_no_default",
"advanced_default",
]
result = await hass.config_entries.options.async_configure(result["flow_id"], {})
assert result["type"] == data_entry_flow.FlowResultType.CREATE_ENTRY
assert result["data"] == {
"advanced_default": "a very reasonable default",
"optional_default": "a very reasonable default",
}