Add config flow for platform switch in Template (#121639)
parent
f94b28f72d
commit
52454f5218
|
@ -25,6 +25,7 @@ from homeassistant.const import (
|
||||||
CONF_STATE,
|
CONF_STATE,
|
||||||
CONF_UNIT_OF_MEASUREMENT,
|
CONF_UNIT_OF_MEASUREMENT,
|
||||||
CONF_URL,
|
CONF_URL,
|
||||||
|
CONF_VALUE_TEMPLATE,
|
||||||
CONF_VERIFY_SSL,
|
CONF_VERIFY_SSL,
|
||||||
Platform,
|
Platform,
|
||||||
)
|
)
|
||||||
|
@ -39,8 +40,9 @@ from homeassistant.helpers.schema_config_entry_flow import (
|
||||||
)
|
)
|
||||||
|
|
||||||
from .binary_sensor import async_create_preview_binary_sensor
|
from .binary_sensor import async_create_preview_binary_sensor
|
||||||
from .const import CONF_PRESS, DOMAIN
|
from .const import CONF_PRESS, CONF_TURN_OFF, CONF_TURN_ON, DOMAIN
|
||||||
from .sensor import async_create_preview_sensor
|
from .sensor import async_create_preview_sensor
|
||||||
|
from .switch import async_create_preview_switch
|
||||||
from .template_entity import TemplateEntity
|
from .template_entity import TemplateEntity
|
||||||
|
|
||||||
_SCHEMA_STATE: dict[vol.Marker, Any] = {
|
_SCHEMA_STATE: dict[vol.Marker, Any] = {
|
||||||
|
@ -132,6 +134,13 @@ def generate_schema(domain: str, flow_type: str) -> vol.Schema:
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if domain == Platform.SWITCH:
|
||||||
|
schema |= {
|
||||||
|
vol.Required(CONF_VALUE_TEMPLATE): selector.TemplateSelector(),
|
||||||
|
vol.Optional(CONF_TURN_ON): selector.ActionSelector(),
|
||||||
|
vol.Optional(CONF_TURN_OFF): selector.ActionSelector(),
|
||||||
|
}
|
||||||
|
|
||||||
schema[vol.Optional(CONF_DEVICE_ID)] = selector.DeviceSelector()
|
schema[vol.Optional(CONF_DEVICE_ID)] = selector.DeviceSelector()
|
||||||
|
|
||||||
return vol.Schema(schema)
|
return vol.Schema(schema)
|
||||||
|
@ -224,6 +233,7 @@ TEMPLATE_TYPES = [
|
||||||
"button",
|
"button",
|
||||||
"image",
|
"image",
|
||||||
"sensor",
|
"sensor",
|
||||||
|
"switch",
|
||||||
]
|
]
|
||||||
|
|
||||||
CONFIG_FLOW = {
|
CONFIG_FLOW = {
|
||||||
|
@ -246,6 +256,11 @@ CONFIG_FLOW = {
|
||||||
preview="template",
|
preview="template",
|
||||||
validate_user_input=validate_user_input(Platform.SENSOR),
|
validate_user_input=validate_user_input(Platform.SENSOR),
|
||||||
),
|
),
|
||||||
|
Platform.SWITCH: SchemaFlowFormStep(
|
||||||
|
config_schema(Platform.SWITCH),
|
||||||
|
preview="template",
|
||||||
|
validate_user_input=validate_user_input(Platform.SWITCH),
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -269,6 +284,11 @@ OPTIONS_FLOW = {
|
||||||
preview="template",
|
preview="template",
|
||||||
validate_user_input=validate_user_input(Platform.SENSOR),
|
validate_user_input=validate_user_input(Platform.SENSOR),
|
||||||
),
|
),
|
||||||
|
Platform.SWITCH: SchemaFlowFormStep(
|
||||||
|
options_schema(Platform.SWITCH),
|
||||||
|
preview="template",
|
||||||
|
validate_user_input=validate_user_input(Platform.SWITCH),
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
CREATE_PREVIEW_ENTITY: dict[
|
CREATE_PREVIEW_ENTITY: dict[
|
||||||
|
@ -277,6 +297,7 @@ CREATE_PREVIEW_ENTITY: dict[
|
||||||
] = {
|
] = {
|
||||||
"binary_sensor": async_create_preview_binary_sensor,
|
"binary_sensor": async_create_preview_binary_sensor,
|
||||||
"sensor": async_create_preview_sensor,
|
"sensor": async_create_preview_sensor,
|
||||||
|
"switch": async_create_preview_switch,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -34,3 +34,5 @@ CONF_ATTRIBUTE_TEMPLATES = "attribute_templates"
|
||||||
CONF_PICTURE = "picture"
|
CONF_PICTURE = "picture"
|
||||||
CONF_PRESS = "press"
|
CONF_PRESS = "press"
|
||||||
CONF_OBJECT_ID = "object_id"
|
CONF_OBJECT_ID = "object_id"
|
||||||
|
CONF_TURN_OFF = "turn_off"
|
||||||
|
CONF_TURN_ON = "turn_on"
|
||||||
|
|
|
@ -57,9 +57,23 @@
|
||||||
"binary_sensor": "Template a binary sensor",
|
"binary_sensor": "Template a binary sensor",
|
||||||
"button": "Template a button",
|
"button": "Template a button",
|
||||||
"image": "Template a image",
|
"image": "Template a image",
|
||||||
"sensor": "Template a sensor"
|
"sensor": "Template a sensor",
|
||||||
|
"switch": "Template a switch"
|
||||||
},
|
},
|
||||||
"title": "Template helper"
|
"title": "Template helper"
|
||||||
|
},
|
||||||
|
"switch": {
|
||||||
|
"data": {
|
||||||
|
"device_id": "[%key:common::config_flow::data::device%]",
|
||||||
|
"name": "[%key:common::config_flow::data::name%]",
|
||||||
|
"turn_off": "Actions on turn off",
|
||||||
|
"turn_on": "Actions on turn on",
|
||||||
|
"state": "[%key:component::template::config::step::sensor::data::state%]"
|
||||||
|
},
|
||||||
|
"data_description": {
|
||||||
|
"device_id": "[%key:component::template::config::step::sensor::data_description::device_id%]"
|
||||||
|
},
|
||||||
|
"title": "Template switch"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -108,6 +122,19 @@
|
||||||
"device_id": "[%key:component::template::config::step::sensor::data_description::device_id%]"
|
"device_id": "[%key:component::template::config::step::sensor::data_description::device_id%]"
|
||||||
},
|
},
|
||||||
"title": "[%key:component::template::config::step::sensor::title%]"
|
"title": "[%key:component::template::config::step::sensor::title%]"
|
||||||
|
},
|
||||||
|
"switch": {
|
||||||
|
"data": {
|
||||||
|
"device_id": "[%key:common::config_flow::data::device%]",
|
||||||
|
"name": "[%key:common::config_flow::data::name%]",
|
||||||
|
"state": "[%key:component::template::config::step::sensor::data::state%]",
|
||||||
|
"turn_off": "[%key:component::template::config::step::switch::data::turn_off%]",
|
||||||
|
"turn_on": "[%key:component::template::config::step::switch::data::turn_on%]"
|
||||||
|
},
|
||||||
|
"data_description": {
|
||||||
|
"device_id": "[%key:component::template::config::step::sensor::data_description::device_id%]"
|
||||||
|
},
|
||||||
|
"title": "[%key:component::template::config::step::switch::title%]"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -11,9 +11,12 @@ from homeassistant.components.switch import (
|
||||||
PLATFORM_SCHEMA as SWITCH_PLATFORM_SCHEMA,
|
PLATFORM_SCHEMA as SWITCH_PLATFORM_SCHEMA,
|
||||||
SwitchEntity,
|
SwitchEntity,
|
||||||
)
|
)
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_ENTITY_ID,
|
ATTR_ENTITY_ID,
|
||||||
ATTR_FRIENDLY_NAME,
|
ATTR_FRIENDLY_NAME,
|
||||||
|
CONF_DEVICE_ID,
|
||||||
|
CONF_NAME,
|
||||||
CONF_SWITCHES,
|
CONF_SWITCHES,
|
||||||
CONF_UNIQUE_ID,
|
CONF_UNIQUE_ID,
|
||||||
CONF_VALUE_TEMPLATE,
|
CONF_VALUE_TEMPLATE,
|
||||||
|
@ -22,14 +25,15 @@ from homeassistant.const import (
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.exceptions import TemplateError
|
from homeassistant.exceptions import TemplateError
|
||||||
import homeassistant.helpers.config_validation as cv
|
from homeassistant.helpers import config_validation as cv, selector
|
||||||
|
from homeassistant.helpers.device import async_device_info_to_link_from_device_id
|
||||||
from homeassistant.helpers.entity import async_generate_entity_id
|
from homeassistant.helpers.entity import async_generate_entity_id
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.restore_state import RestoreEntity
|
from homeassistant.helpers.restore_state import RestoreEntity
|
||||||
from homeassistant.helpers.script import Script
|
from homeassistant.helpers.script import Script
|
||||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||||
|
|
||||||
from .const import DOMAIN
|
from .const import CONF_TURN_OFF, CONF_TURN_ON, DOMAIN
|
||||||
from .template_entity import (
|
from .template_entity import (
|
||||||
TEMPLATE_ENTITY_COMMON_SCHEMA_LEGACY,
|
TEMPLATE_ENTITY_COMMON_SCHEMA_LEGACY,
|
||||||
TemplateEntity,
|
TemplateEntity,
|
||||||
|
@ -38,16 +42,13 @@ from .template_entity import (
|
||||||
|
|
||||||
_VALID_STATES = [STATE_ON, STATE_OFF, "true", "false"]
|
_VALID_STATES = [STATE_ON, STATE_OFF, "true", "false"]
|
||||||
|
|
||||||
ON_ACTION = "turn_on"
|
|
||||||
OFF_ACTION = "turn_off"
|
|
||||||
|
|
||||||
SWITCH_SCHEMA = vol.All(
|
SWITCH_SCHEMA = vol.All(
|
||||||
cv.deprecated(ATTR_ENTITY_ID),
|
cv.deprecated(ATTR_ENTITY_ID),
|
||||||
vol.Schema(
|
vol.Schema(
|
||||||
{
|
{
|
||||||
vol.Optional(CONF_VALUE_TEMPLATE): cv.template,
|
vol.Optional(CONF_VALUE_TEMPLATE): cv.template,
|
||||||
vol.Required(ON_ACTION): cv.SCRIPT_SCHEMA,
|
vol.Required(CONF_TURN_ON): cv.SCRIPT_SCHEMA,
|
||||||
vol.Required(OFF_ACTION): cv.SCRIPT_SCHEMA,
|
vol.Required(CONF_TURN_OFF): cv.SCRIPT_SCHEMA,
|
||||||
vol.Optional(ATTR_FRIENDLY_NAME): cv.string,
|
vol.Optional(ATTR_FRIENDLY_NAME): cv.string,
|
||||||
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
||||||
vol.Optional(CONF_UNIQUE_ID): cv.string,
|
vol.Optional(CONF_UNIQUE_ID): cv.string,
|
||||||
|
@ -59,6 +60,16 @@ PLATFORM_SCHEMA = SWITCH_PLATFORM_SCHEMA.extend(
|
||||||
{vol.Required(CONF_SWITCHES): cv.schema_with_slug_keys(SWITCH_SCHEMA)}
|
{vol.Required(CONF_SWITCHES): cv.schema_with_slug_keys(SWITCH_SCHEMA)}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
SWICTH_CONFIG_SCHEMA = vol.Schema(
|
||||||
|
{
|
||||||
|
vol.Required(CONF_NAME): cv.template,
|
||||||
|
vol.Required(CONF_VALUE_TEMPLATE): cv.template,
|
||||||
|
vol.Optional(CONF_TURN_ON): selector.ActionSelector(),
|
||||||
|
vol.Optional(CONF_TURN_OFF): selector.ActionSelector(),
|
||||||
|
vol.Optional(CONF_DEVICE_ID): selector.DeviceSelector(),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def _async_create_entities(hass, config):
|
async def _async_create_entities(hass, config):
|
||||||
"""Create the Template switches."""
|
"""Create the Template switches."""
|
||||||
|
@ -90,6 +101,29 @@ async def async_setup_platform(
|
||||||
async_add_entities(await _async_create_entities(hass, config))
|
async_add_entities(await _async_create_entities(hass, config))
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
config_entry: ConfigEntry,
|
||||||
|
async_add_entities: AddEntitiesCallback,
|
||||||
|
) -> None:
|
||||||
|
"""Initialize config entry."""
|
||||||
|
_options = dict(config_entry.options)
|
||||||
|
_options.pop("template_type")
|
||||||
|
validated_config = SWICTH_CONFIG_SCHEMA(_options)
|
||||||
|
async_add_entities(
|
||||||
|
[SwitchTemplate(hass, None, validated_config, config_entry.entry_id)]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def async_create_preview_switch(
|
||||||
|
hass: HomeAssistant, name: str, config: dict[str, Any]
|
||||||
|
) -> SwitchTemplate:
|
||||||
|
"""Create a preview switch."""
|
||||||
|
validated_config = SWICTH_CONFIG_SCHEMA(config | {CONF_NAME: name})
|
||||||
|
return SwitchTemplate(hass, None, validated_config, None)
|
||||||
|
|
||||||
|
|
||||||
class SwitchTemplate(TemplateEntity, SwitchEntity, RestoreEntity):
|
class SwitchTemplate(TemplateEntity, SwitchEntity, RestoreEntity):
|
||||||
"""Representation of a Template switch."""
|
"""Representation of a Template switch."""
|
||||||
|
|
||||||
|
@ -106,15 +140,28 @@ class SwitchTemplate(TemplateEntity, SwitchEntity, RestoreEntity):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
hass, config=config, fallback_name=object_id, unique_id=unique_id
|
hass, config=config, fallback_name=object_id, unique_id=unique_id
|
||||||
)
|
)
|
||||||
|
if object_id is not None:
|
||||||
self.entity_id = async_generate_entity_id(
|
self.entity_id = async_generate_entity_id(
|
||||||
ENTITY_ID_FORMAT, object_id, hass=hass
|
ENTITY_ID_FORMAT, object_id, hass=hass
|
||||||
)
|
)
|
||||||
friendly_name = self._attr_name
|
friendly_name = self._attr_name
|
||||||
self._template = config.get(CONF_VALUE_TEMPLATE)
|
self._template = config.get(CONF_VALUE_TEMPLATE)
|
||||||
self._on_script = Script(hass, config[ON_ACTION], friendly_name, DOMAIN)
|
self._on_script = (
|
||||||
self._off_script = Script(hass, config[OFF_ACTION], friendly_name, DOMAIN)
|
Script(hass, config.get(CONF_TURN_ON), friendly_name, DOMAIN)
|
||||||
|
if config.get(CONF_TURN_ON) is not None
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
self._off_script = (
|
||||||
|
Script(hass, config.get(CONF_TURN_OFF), friendly_name, DOMAIN)
|
||||||
|
if config.get(CONF_TURN_OFF) is not None
|
||||||
|
else None
|
||||||
|
)
|
||||||
self._state: bool | None = False
|
self._state: bool | None = False
|
||||||
self._attr_assumed_state = self._template is None
|
self._attr_assumed_state = self._template is None
|
||||||
|
self._attr_device_info = async_device_info_to_link_from_device_id(
|
||||||
|
hass,
|
||||||
|
config.get(CONF_DEVICE_ID),
|
||||||
|
)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _update_state(self, result):
|
def _update_state(self, result):
|
||||||
|
@ -159,6 +206,7 @@ class SwitchTemplate(TemplateEntity, SwitchEntity, RestoreEntity):
|
||||||
|
|
||||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||||
"""Fire the on action."""
|
"""Fire the on action."""
|
||||||
|
if self._on_script:
|
||||||
await self.async_run_script(self._on_script, context=self._context)
|
await self.async_run_script(self._on_script, context=self._context)
|
||||||
if self._template is None:
|
if self._template is None:
|
||||||
self._state = True
|
self._state = True
|
||||||
|
@ -166,6 +214,7 @@ class SwitchTemplate(TemplateEntity, SwitchEntity, RestoreEntity):
|
||||||
|
|
||||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||||
"""Fire the off action."""
|
"""Fire the off action."""
|
||||||
|
if self._off_script:
|
||||||
await self.async_run_script(self._off_script, context=self._context)
|
await self.async_run_script(self._off_script, context=self._context)
|
||||||
if self._template is None:
|
if self._template is None:
|
||||||
self._state = False
|
self._state = False
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
# serializer version: 1
|
||||||
|
# name: test_setup_config_entry
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'friendly_name': 'My template',
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'switch.my_template',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': 'on',
|
||||||
|
})
|
||||||
|
# ---
|
|
@ -91,6 +91,16 @@ from tests.typing import WebSocketGenerator
|
||||||
{"verify_ssl": True},
|
{"verify_ssl": True},
|
||||||
{},
|
{},
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"switch",
|
||||||
|
{"value_template": "{{ states('switch.one') }}"},
|
||||||
|
"on",
|
||||||
|
{"one": "on", "two": "off"},
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@pytest.mark.freeze_time("2024-07-09 00:00:00+00:00")
|
@pytest.mark.freeze_time("2024-07-09 00:00:00+00:00")
|
||||||
|
@ -186,6 +196,12 @@ async def test_config_flow(
|
||||||
{},
|
{},
|
||||||
{},
|
{},
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"switch",
|
||||||
|
{"value_template": "{{ false }}"},
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"button",
|
"button",
|
||||||
{},
|
{},
|
||||||
|
@ -295,6 +311,7 @@ def get_suggested(schema, key):
|
||||||
"input_states",
|
"input_states",
|
||||||
"extra_options",
|
"extra_options",
|
||||||
"options_options",
|
"options_options",
|
||||||
|
"key_template",
|
||||||
),
|
),
|
||||||
[
|
[
|
||||||
(
|
(
|
||||||
|
@ -309,6 +326,7 @@ def get_suggested(schema, key):
|
||||||
{"one": "on", "two": "off"},
|
{"one": "on", "two": "off"},
|
||||||
{},
|
{},
|
||||||
{},
|
{},
|
||||||
|
"state",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"sensor",
|
"sensor",
|
||||||
|
@ -322,6 +340,7 @@ def get_suggested(schema, key):
|
||||||
{"one": "30.0", "two": "20.0"},
|
{"one": "30.0", "two": "20.0"},
|
||||||
{},
|
{},
|
||||||
{},
|
{},
|
||||||
|
"state",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"button",
|
"button",
|
||||||
|
@ -348,6 +367,7 @@ def get_suggested(schema, key):
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
"state",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"image",
|
"image",
|
||||||
|
@ -364,6 +384,17 @@ def get_suggested(schema, key):
|
||||||
"url": "{{ states('sensor.two') }}",
|
"url": "{{ states('sensor.two') }}",
|
||||||
"verify_ssl": True,
|
"verify_ssl": True,
|
||||||
},
|
},
|
||||||
|
"url",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"switch",
|
||||||
|
{"value_template": "{{ states('switch.one') }}"},
|
||||||
|
{"value_template": "{{ states('switch.two') }}"},
|
||||||
|
["on", "off"],
|
||||||
|
{"one": "on", "two": "off"},
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
"value_template",
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -377,6 +408,7 @@ async def test_options(
|
||||||
input_states,
|
input_states,
|
||||||
extra_options,
|
extra_options,
|
||||||
options_options,
|
options_options,
|
||||||
|
key_template,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test reconfiguring."""
|
"""Test reconfiguring."""
|
||||||
input_entities = ["one", "two"]
|
input_entities = ["one", "two"]
|
||||||
|
@ -411,13 +443,16 @@ async def test_options(
|
||||||
assert result["type"] is FlowResultType.FORM
|
assert result["type"] is FlowResultType.FORM
|
||||||
assert result["step_id"] == template_type
|
assert result["step_id"] == template_type
|
||||||
assert get_suggested(
|
assert get_suggested(
|
||||||
result["data_schema"].schema, "state"
|
result["data_schema"].schema, key_template
|
||||||
) == old_state_template.get("state")
|
) == old_state_template.get(key_template)
|
||||||
assert "name" not in result["data_schema"].schema
|
assert "name" not in result["data_schema"].schema
|
||||||
|
|
||||||
result = await hass.config_entries.options.async_configure(
|
result = await hass.config_entries.options.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
user_input={**new_state_template, **options_options},
|
user_input={
|
||||||
|
**new_state_template,
|
||||||
|
**options_options,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||||
assert result["data"] == {
|
assert result["data"] == {
|
||||||
|
@ -455,7 +490,7 @@ async def test_options(
|
||||||
assert result["step_id"] == template_type
|
assert result["step_id"] == template_type
|
||||||
|
|
||||||
assert get_suggested(result["data_schema"].schema, "name") is None
|
assert get_suggested(result["data_schema"].schema, "name") is None
|
||||||
assert get_suggested(result["data_schema"].schema, "state") is None
|
assert get_suggested(result["data_schema"].schema, key_template) is None
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
|
@ -1095,6 +1130,12 @@ async def test_option_flow_sensor_preview_config_entry_removed(
|
||||||
{},
|
{},
|
||||||
{},
|
{},
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"switch",
|
||||||
|
{"value_template": "{{ false }}"},
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
async def test_options_flow_change_device(
|
async def test_options_flow_change_device(
|
||||||
|
|
|
@ -314,6 +314,16 @@ async def async_yaml_patch_helper(hass, filename):
|
||||||
},
|
},
|
||||||
{},
|
{},
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
{
|
||||||
|
"template_type": "switch",
|
||||||
|
"name": "My template",
|
||||||
|
"value_template": "{{ true }}",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value_template": "{{ true }}",
|
||||||
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
async def test_change_device(
|
async def test_change_device(
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
"""The tests for the Template switch platform."""
|
"""The tests for the Template switch platform."""
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
from syrupy.assertion import SnapshotAssertion
|
||||||
|
|
||||||
from homeassistant import setup
|
from homeassistant import setup
|
||||||
|
from homeassistant.components import template
|
||||||
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
|
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_ENTITY_ID,
|
ATTR_ENTITY_ID,
|
||||||
|
@ -13,9 +15,15 @@ from homeassistant.const import (
|
||||||
STATE_UNAVAILABLE,
|
STATE_UNAVAILABLE,
|
||||||
)
|
)
|
||||||
from homeassistant.core import CoreState, HomeAssistant, ServiceCall, State
|
from homeassistant.core import CoreState, HomeAssistant, ServiceCall, State
|
||||||
|
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 tests.common import assert_setup_component, mock_component, mock_restore_cache
|
from tests.common import (
|
||||||
|
MockConfigEntry,
|
||||||
|
assert_setup_component,
|
||||||
|
mock_component,
|
||||||
|
mock_restore_cache,
|
||||||
|
)
|
||||||
|
|
||||||
OPTIMISTIC_SWITCH_CONFIG = {
|
OPTIMISTIC_SWITCH_CONFIG = {
|
||||||
"turn_on": {
|
"turn_on": {
|
||||||
|
@ -35,6 +43,38 @@ OPTIMISTIC_SWITCH_CONFIG = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def test_setup_config_entry(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
snapshot: SnapshotAssertion,
|
||||||
|
) -> None:
|
||||||
|
"""Test the config flow."""
|
||||||
|
|
||||||
|
hass.states.async_set(
|
||||||
|
"switch.one",
|
||||||
|
"on",
|
||||||
|
{},
|
||||||
|
)
|
||||||
|
|
||||||
|
template_config_entry = MockConfigEntry(
|
||||||
|
data={},
|
||||||
|
domain=template.DOMAIN,
|
||||||
|
options={
|
||||||
|
"name": "My template",
|
||||||
|
"value_template": "{{ states('switch.one') }}",
|
||||||
|
"template_type": SWITCH_DOMAIN,
|
||||||
|
},
|
||||||
|
title="My template",
|
||||||
|
)
|
||||||
|
template_config_entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
assert await hass.config_entries.async_setup(template_config_entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
state = hass.states.get("switch.my_template")
|
||||||
|
assert state is not None
|
||||||
|
assert state == snapshot
|
||||||
|
|
||||||
|
|
||||||
async def test_template_state_text(hass: HomeAssistant) -> None:
|
async def test_template_state_text(hass: HomeAssistant) -> None:
|
||||||
"""Test the state text of a template."""
|
"""Test the state text of a template."""
|
||||||
with assert_setup_component(1, "switch"):
|
with assert_setup_component(1, "switch"):
|
||||||
|
@ -655,3 +695,42 @@ async def test_unique_id(hass: HomeAssistant) -> None:
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert len(hass.states.async_all("switch")) == 1
|
assert len(hass.states.async_all("switch")) == 1
|
||||||
|
|
||||||
|
|
||||||
|
async def test_device_id(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
device_registry: dr.DeviceRegistry,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
) -> None:
|
||||||
|
"""Test for device for Template."""
|
||||||
|
|
||||||
|
device_config_entry = MockConfigEntry()
|
||||||
|
device_config_entry.add_to_hass(hass)
|
||||||
|
device_entry = device_registry.async_get_or_create(
|
||||||
|
config_entry_id=device_config_entry.entry_id,
|
||||||
|
identifiers={("test", "identifier_test")},
|
||||||
|
connections={("mac", "30:31:32:33:34:35")},
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert device_entry is not None
|
||||||
|
assert device_entry.id is not None
|
||||||
|
|
||||||
|
template_config_entry = MockConfigEntry(
|
||||||
|
data={},
|
||||||
|
domain=template.DOMAIN,
|
||||||
|
options={
|
||||||
|
"name": "My template",
|
||||||
|
"value_template": "{{ true }}",
|
||||||
|
"template_type": "switch",
|
||||||
|
"device_id": device_entry.id,
|
||||||
|
},
|
||||||
|
title="My template",
|
||||||
|
)
|
||||||
|
template_config_entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
assert await hass.config_entries.async_setup(template_config_entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
template_entity = entity_registry.async_get("switch.my_template")
|
||||||
|
assert template_entity is not None
|
||||||
|
assert template_entity.device_id == device_entry.id
|
||||||
|
|
Loading…
Reference in New Issue