mirror of
https://github.com/basnijholt/adaptive-lighting.git
synced 2026-09-18 09:44:05 +02:00
Split options flow into Basic and Advanced steps
Users have complained about the overwhelming number of options (28+) in the configuration UI. This change splits the options into two steps: **Basic Settings (9 options):** - lights, min/max brightness, min/max color temp - sleep brightness, sleep color temp, transition, interval **Advanced Settings (20+ options):** - All other options (sunrise/sunset times, offsets, brightness modes, take_over_control, detect_non_ha_changes, etc.) The flow now works as: 1. User configures basic options 2. Menu appears: "Configure advanced options" or "Save and finish" 3. If advanced chosen, show advanced options form 4. Save combined options Changes: - Add BASIC_OPTIONS constant to const.py - Refactor OptionsFlowHandler with async_step_init, async_step_advanced, async_step_finish methods - Update strings.json with menu_options and advanced step - Update all 34 translation files with translated menu/titles - Update tests for multi-step flow Note for Weblate: After merging, run "Rescan all translation files" to pick up the new structure. Existing translations are preserved.
This commit is contained in:
parent
1968e1a9a6
commit
f94fb6a85e
38 changed files with 1003 additions and 375 deletions
|
|
@ -1,6 +1,7 @@
|
|||
"""Test Adaptive Lighting config flow."""
|
||||
|
||||
from homeassistant.components.adaptive_lighting.const import (
|
||||
BASIC_OPTIONS,
|
||||
CONF_SUNRISE_TIME,
|
||||
CONF_SUNSET_TIME,
|
||||
DEFAULT_NAME,
|
||||
|
|
@ -16,6 +17,12 @@ from tests.common import MockConfigEntry
|
|||
|
||||
DEFAULT_DATA = {key: default for key, default, _ in VALIDATION_TUPLES}
|
||||
|
||||
# Split DEFAULT_DATA into basic and advanced options
|
||||
BASIC_DATA = {key: value for key, value in DEFAULT_DATA.items() if key in BASIC_OPTIONS}
|
||||
ADVANCED_DATA = {
|
||||
key: value for key, value in DEFAULT_DATA.items() if key not in BASIC_OPTIONS
|
||||
}
|
||||
|
||||
|
||||
async def test_flow_manual_configuration(hass):
|
||||
"""Test that config flow works."""
|
||||
|
|
@ -53,7 +60,7 @@ async def test_import_success(hass):
|
|||
|
||||
|
||||
async def test_options(hass):
|
||||
"""Test updating options."""
|
||||
"""Test updating options with multi-step flow."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
title=DEFAULT_NAME,
|
||||
|
|
@ -64,24 +71,45 @@ async def test_options(hass):
|
|||
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
|
||||
# Step 1: Init with basic options
|
||||
result = await hass.config_entries.options.async_init(entry.entry_id)
|
||||
assert result["type"] == FlowResultType.FORM
|
||||
assert result["step_id"] == "init"
|
||||
|
||||
data = DEFAULT_DATA.copy()
|
||||
data[CONF_SUNRISE_TIME] = NONE_STR
|
||||
data[CONF_SUNSET_TIME] = NONE_STR
|
||||
# Submit basic options - this should show the menu
|
||||
result = await hass.config_entries.options.async_configure(
|
||||
result["flow_id"],
|
||||
user_input=data,
|
||||
user_input=BASIC_DATA.copy(),
|
||||
)
|
||||
assert result["type"] == FlowResultType.MENU
|
||||
assert result["step_id"] == "init"
|
||||
|
||||
# Choose to go to advanced options
|
||||
result = await hass.config_entries.options.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={"next_step_id": "advanced"},
|
||||
)
|
||||
assert result["type"] == FlowResultType.FORM
|
||||
assert result["step_id"] == "advanced"
|
||||
|
||||
# Submit advanced options
|
||||
advanced_data = ADVANCED_DATA.copy()
|
||||
advanced_data[CONF_SUNRISE_TIME] = NONE_STR
|
||||
advanced_data[CONF_SUNSET_TIME] = NONE_STR
|
||||
result = await hass.config_entries.options.async_configure(
|
||||
result["flow_id"],
|
||||
user_input=advanced_data,
|
||||
)
|
||||
assert result["type"] == FlowResultType.CREATE_ENTRY
|
||||
for key, value in data.items():
|
||||
|
||||
# Verify all data is saved (basic + advanced)
|
||||
expected_data = {**BASIC_DATA, **advanced_data}
|
||||
for key, value in expected_data.items():
|
||||
assert result["data"][key] == value
|
||||
|
||||
|
||||
async def test_incorrect_options(hass):
|
||||
"""Test updating incorrect options."""
|
||||
async def test_options_finish_without_advanced(hass):
|
||||
"""Test updating options and finishing without advanced step."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
title=DEFAULT_NAME,
|
||||
|
|
@ -92,14 +120,70 @@ async def test_incorrect_options(hass):
|
|||
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
|
||||
# Step 1: Init with basic options
|
||||
result = await hass.config_entries.options.async_init(entry.entry_id)
|
||||
data = DEFAULT_DATA.copy()
|
||||
data[CONF_SUNRISE_TIME] = "yolo"
|
||||
data[CONF_SUNSET_TIME] = "yolo"
|
||||
assert result["type"] == FlowResultType.FORM
|
||||
assert result["step_id"] == "init"
|
||||
|
||||
# Submit basic options - this should show the menu
|
||||
result = await hass.config_entries.options.async_configure(
|
||||
result["flow_id"],
|
||||
user_input=data,
|
||||
user_input=BASIC_DATA.copy(),
|
||||
)
|
||||
assert result["type"] == FlowResultType.MENU
|
||||
|
||||
# Choose to finish (skip advanced options)
|
||||
result = await hass.config_entries.options.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={"next_step_id": "finish"},
|
||||
)
|
||||
assert result["type"] == FlowResultType.CREATE_ENTRY
|
||||
|
||||
# Verify only basic data is saved
|
||||
for key, value in BASIC_DATA.items():
|
||||
assert result["data"][key] == value
|
||||
|
||||
|
||||
async def test_incorrect_options(hass):
|
||||
"""Test updating incorrect options in advanced step."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
title=DEFAULT_NAME,
|
||||
data={CONF_NAME: DEFAULT_NAME},
|
||||
options={},
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
|
||||
# Step 1: Init with basic options
|
||||
result = await hass.config_entries.options.async_init(entry.entry_id)
|
||||
result = await hass.config_entries.options.async_configure(
|
||||
result["flow_id"],
|
||||
user_input=BASIC_DATA.copy(),
|
||||
)
|
||||
assert result["type"] == FlowResultType.MENU
|
||||
|
||||
# Choose to go to advanced options
|
||||
result = await hass.config_entries.options.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={"next_step_id": "advanced"},
|
||||
)
|
||||
assert result["type"] == FlowResultType.FORM
|
||||
assert result["step_id"] == "advanced"
|
||||
|
||||
# Submit invalid advanced options
|
||||
advanced_data = ADVANCED_DATA.copy()
|
||||
advanced_data[CONF_SUNRISE_TIME] = "yolo"
|
||||
advanced_data[CONF_SUNSET_TIME] = "yolo"
|
||||
result = await hass.config_entries.options.async_configure(
|
||||
result["flow_id"],
|
||||
user_input=advanced_data,
|
||||
)
|
||||
# Should show form again with errors
|
||||
assert result["type"] == FlowResultType.FORM
|
||||
assert result["step_id"] == "advanced"
|
||||
assert result["errors"] == {"base": "option_error"}
|
||||
|
||||
|
||||
async def test_import_twice(hass):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue