Add a preview to template config flow for alarm control panel, image, and select platforms (#148441)

This commit is contained in:
Petro31 2025-07-17 17:19:45 -04:00 committed by GitHub
parent aacaa9a20f
commit 3c87a3e892
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 71 additions and 7 deletions

View File

@ -206,6 +206,18 @@ async def async_setup_platform(
) )
@callback
def async_create_preview_alarm_control_panel(
hass: HomeAssistant, name: str, config: dict[str, Any]
) -> StateAlarmControlPanelEntity:
"""Create a preview alarm control panel."""
updated_config = rewrite_options_to_modern_conf(config)
validated_config = ALARM_CONTROL_PANEL_CONFIG_SCHEMA(
updated_config | {CONF_NAME: name}
)
return StateAlarmControlPanelEntity(hass, validated_config, None)
class AbstractTemplateAlarmControlPanel( class AbstractTemplateAlarmControlPanel(
AbstractTemplateEntity, AlarmControlPanelEntity, RestoreEntity AbstractTemplateEntity, AlarmControlPanelEntity, RestoreEntity
): ):

View File

@ -50,6 +50,7 @@ from .alarm_control_panel import (
CONF_DISARM_ACTION, CONF_DISARM_ACTION,
CONF_TRIGGER_ACTION, CONF_TRIGGER_ACTION,
TemplateCodeFormat, TemplateCodeFormat,
async_create_preview_alarm_control_panel,
) )
from .binary_sensor import async_create_preview_binary_sensor from .binary_sensor import async_create_preview_binary_sensor
from .const import CONF_PRESS, CONF_TURN_OFF, CONF_TURN_ON, DOMAIN from .const import CONF_PRESS, CONF_TURN_OFF, CONF_TURN_ON, DOMAIN
@ -63,7 +64,7 @@ from .number import (
DEFAULT_STEP, DEFAULT_STEP,
async_create_preview_number, async_create_preview_number,
) )
from .select import CONF_OPTIONS, CONF_SELECT_OPTION from .select import CONF_OPTIONS, CONF_SELECT_OPTION, async_create_preview_select
from .sensor import async_create_preview_sensor from .sensor import async_create_preview_sensor
from .switch import async_create_preview_switch from .switch import async_create_preview_switch
from .template_entity import TemplateEntity from .template_entity import TemplateEntity
@ -319,6 +320,7 @@ CONFIG_FLOW = {
"user": SchemaFlowMenuStep(TEMPLATE_TYPES), "user": SchemaFlowMenuStep(TEMPLATE_TYPES),
Platform.ALARM_CONTROL_PANEL: SchemaFlowFormStep( Platform.ALARM_CONTROL_PANEL: SchemaFlowFormStep(
config_schema(Platform.ALARM_CONTROL_PANEL), config_schema(Platform.ALARM_CONTROL_PANEL),
preview="template",
validate_user_input=validate_user_input(Platform.ALARM_CONTROL_PANEL), validate_user_input=validate_user_input(Platform.ALARM_CONTROL_PANEL),
), ),
Platform.BINARY_SENSOR: SchemaFlowFormStep( Platform.BINARY_SENSOR: SchemaFlowFormStep(
@ -332,6 +334,7 @@ CONFIG_FLOW = {
), ),
Platform.IMAGE: SchemaFlowFormStep( Platform.IMAGE: SchemaFlowFormStep(
config_schema(Platform.IMAGE), config_schema(Platform.IMAGE),
preview="template",
validate_user_input=validate_user_input(Platform.IMAGE), validate_user_input=validate_user_input(Platform.IMAGE),
), ),
Platform.NUMBER: SchemaFlowFormStep( Platform.NUMBER: SchemaFlowFormStep(
@ -341,6 +344,7 @@ CONFIG_FLOW = {
), ),
Platform.SELECT: SchemaFlowFormStep( Platform.SELECT: SchemaFlowFormStep(
config_schema(Platform.SELECT), config_schema(Platform.SELECT),
preview="template",
validate_user_input=validate_user_input(Platform.SELECT), validate_user_input=validate_user_input(Platform.SELECT),
), ),
Platform.SENSOR: SchemaFlowFormStep( Platform.SENSOR: SchemaFlowFormStep(
@ -360,6 +364,7 @@ OPTIONS_FLOW = {
"init": SchemaFlowFormStep(next_step=choose_options_step), "init": SchemaFlowFormStep(next_step=choose_options_step),
Platform.ALARM_CONTROL_PANEL: SchemaFlowFormStep( Platform.ALARM_CONTROL_PANEL: SchemaFlowFormStep(
options_schema(Platform.ALARM_CONTROL_PANEL), options_schema(Platform.ALARM_CONTROL_PANEL),
preview="template",
validate_user_input=validate_user_input(Platform.ALARM_CONTROL_PANEL), validate_user_input=validate_user_input(Platform.ALARM_CONTROL_PANEL),
), ),
Platform.BINARY_SENSOR: SchemaFlowFormStep( Platform.BINARY_SENSOR: SchemaFlowFormStep(
@ -373,6 +378,7 @@ OPTIONS_FLOW = {
), ),
Platform.IMAGE: SchemaFlowFormStep( Platform.IMAGE: SchemaFlowFormStep(
options_schema(Platform.IMAGE), options_schema(Platform.IMAGE),
preview="template",
validate_user_input=validate_user_input(Platform.IMAGE), validate_user_input=validate_user_input(Platform.IMAGE),
), ),
Platform.NUMBER: SchemaFlowFormStep( Platform.NUMBER: SchemaFlowFormStep(
@ -382,6 +388,7 @@ OPTIONS_FLOW = {
), ),
Platform.SELECT: SchemaFlowFormStep( Platform.SELECT: SchemaFlowFormStep(
options_schema(Platform.SELECT), options_schema(Platform.SELECT),
preview="template",
validate_user_input=validate_user_input(Platform.SELECT), validate_user_input=validate_user_input(Platform.SELECT),
), ),
Platform.SENSOR: SchemaFlowFormStep( Platform.SENSOR: SchemaFlowFormStep(
@ -400,10 +407,12 @@ CREATE_PREVIEW_ENTITY: dict[
str, str,
Callable[[HomeAssistant, str, dict[str, Any]], TemplateEntity], Callable[[HomeAssistant, str, dict[str, Any]], TemplateEntity],
] = { ] = {
"binary_sensor": async_create_preview_binary_sensor, Platform.ALARM_CONTROL_PANEL: async_create_preview_alarm_control_panel,
"number": async_create_preview_number, Platform.BINARY_SENSOR: async_create_preview_binary_sensor,
"sensor": async_create_preview_sensor, Platform.NUMBER: async_create_preview_number,
"switch": async_create_preview_switch, Platform.SELECT: async_create_preview_select,
Platform.SENSOR: async_create_preview_sensor,
Platform.SWITCH: async_create_preview_switch,
} }

View File

@ -90,6 +90,15 @@ async def async_setup_entry(
async_add_entities([TemplateSelect(hass, validated_config, config_entry.entry_id)]) async_add_entities([TemplateSelect(hass, validated_config, config_entry.entry_id)])
@callback
def async_create_preview_select(
hass: HomeAssistant, name: str, config: dict[str, Any]
) -> TemplateSelect:
"""Create a preview select."""
validated_config = SELECT_CONFIG_SCHEMA(config | {CONF_NAME: name})
return TemplateSelect(hass, validated_config, None)
class AbstractTemplateSelect(AbstractTemplateEntity, SelectEntity): class AbstractTemplateSelect(AbstractTemplateEntity, SelectEntity):
"""Representation of a template select features.""" """Representation of a template select features."""

View File

@ -23,9 +23,10 @@ from homeassistant.core import Event, HomeAssistant, State, callback
from homeassistant.helpers import device_registry as dr, entity_registry as er from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from .conftest import ConfigurationStyle from .conftest import ConfigurationStyle, async_get_flow_preview_state
from tests.common import MockConfigEntry, assert_setup_component, mock_restore_cache from tests.common import MockConfigEntry, assert_setup_component, mock_restore_cache
from tests.conftest import WebSocketGenerator
TEST_OBJECT_ID = "test_template_panel" TEST_OBJECT_ID = "test_template_panel"
TEST_ENTITY_ID = f"alarm_control_panel.{TEST_OBJECT_ID}" TEST_ENTITY_ID = f"alarm_control_panel.{TEST_OBJECT_ID}"
@ -915,3 +916,19 @@ async def test_device_id(
template_entity = entity_registry.async_get("alarm_control_panel.my_template") template_entity = entity_registry.async_get("alarm_control_panel.my_template")
assert template_entity is not None assert template_entity is not None
assert template_entity.device_id == device_entry.id assert template_entity.device_id == device_entry.id
async def test_flow_preview(
hass: HomeAssistant,
hass_ws_client: WebSocketGenerator,
) -> None:
"""Test the config flow preview."""
state = await async_get_flow_preview_state(
hass,
hass_ws_client,
ALARM_DOMAIN,
{"name": "My template", "state": "{{ 'disarmed' }}"},
)
assert state["state"] == AlarmControlPanelState.DISARMED

View File

@ -35,9 +35,10 @@ from homeassistant.core import Context, HomeAssistant, ServiceCall
from homeassistant.helpers import device_registry as dr, entity_registry as er from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from .conftest import ConfigurationStyle from .conftest import ConfigurationStyle, async_get_flow_preview_state
from tests.common import MockConfigEntry, assert_setup_component, async_capture_events from tests.common import MockConfigEntry, assert_setup_component, async_capture_events
from tests.conftest import WebSocketGenerator
_TEST_OBJECT_ID = "template_select" _TEST_OBJECT_ID = "template_select"
_TEST_SELECT = f"select.{_TEST_OBJECT_ID}" _TEST_SELECT = f"select.{_TEST_OBJECT_ID}"
@ -645,3 +646,19 @@ async def test_availability(hass: HomeAssistant) -> None:
state = hass.states.get(_TEST_SELECT) state = hass.states.get(_TEST_SELECT)
assert state.state == "yes" assert state.state == "yes"
async def test_flow_preview(
hass: HomeAssistant,
hass_ws_client: WebSocketGenerator,
) -> None:
"""Test the config flow preview."""
state = await async_get_flow_preview_state(
hass,
hass_ws_client,
select.DOMAIN,
{"name": "My template", **TEST_OPTIONS},
)
assert state["state"] == "test"