Add support for "alias" in script steps device, device_condition, and conditions (#46647)

Co-authored-by: Donnie <donniekarnsinsb@hotmail.com>
This commit is contained in:
Erik Montnemery 2021-02-21 04:21:09 +01:00 committed by GitHub
parent 3ad207a499
commit 2d70806035
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 146 additions and 72 deletions

View file

@ -888,9 +888,11 @@ def script_action(value: Any) -> dict:
SCRIPT_SCHEMA = vol.All(ensure_list, [script_action])
SCRIPT_ACTION_BASE_SCHEMA = {vol.Optional(CONF_ALIAS): string}
EVENT_SCHEMA = vol.Schema(
{
vol.Optional(CONF_ALIAS): string,
**SCRIPT_ACTION_BASE_SCHEMA,
vol.Required(CONF_EVENT): string,
vol.Optional(CONF_EVENT_DATA): vol.All(dict, template_complex),
vol.Optional(CONF_EVENT_DATA_TEMPLATE): vol.All(dict, template_complex),
@ -900,7 +902,7 @@ EVENT_SCHEMA = vol.Schema(
SERVICE_SCHEMA = vol.All(
vol.Schema(
{
vol.Optional(CONF_ALIAS): string,
**SCRIPT_ACTION_BASE_SCHEMA,
vol.Exclusive(CONF_SERVICE, "service name"): vol.Any(
service, dynamic_template
),
@ -920,9 +922,12 @@ NUMERIC_STATE_THRESHOLD_SCHEMA = vol.Any(
vol.Coerce(float), vol.All(str, entity_domain("input_number"))
)
CONDITION_BASE_SCHEMA = {vol.Optional(CONF_ALIAS): string}
NUMERIC_STATE_CONDITION_SCHEMA = vol.All(
vol.Schema(
{
**CONDITION_BASE_SCHEMA,
vol.Required(CONF_CONDITION): "numeric_state",
vol.Required(CONF_ENTITY_ID): entity_ids,
vol.Optional(CONF_ATTRIBUTE): str,
@ -935,6 +940,7 @@ NUMERIC_STATE_CONDITION_SCHEMA = vol.All(
)
STATE_CONDITION_BASE_SCHEMA = {
**CONDITION_BASE_SCHEMA,
vol.Required(CONF_CONDITION): "state",
vol.Required(CONF_ENTITY_ID): entity_ids,
vol.Optional(CONF_ATTRIBUTE): str,
@ -975,6 +981,7 @@ def STATE_CONDITION_SCHEMA(value: Any) -> dict: # pylint: disable=invalid-name
SUN_CONDITION_SCHEMA = vol.All(
vol.Schema(
{
**CONDITION_BASE_SCHEMA,
vol.Required(CONF_CONDITION): "sun",
vol.Optional("before"): sun_event,
vol.Optional("before_offset"): time_period,
@ -989,6 +996,7 @@ SUN_CONDITION_SCHEMA = vol.All(
TEMPLATE_CONDITION_SCHEMA = vol.Schema(
{
**CONDITION_BASE_SCHEMA,
vol.Required(CONF_CONDITION): "template",
vol.Required(CONF_VALUE_TEMPLATE): template,
}
@ -997,6 +1005,7 @@ TEMPLATE_CONDITION_SCHEMA = vol.Schema(
TIME_CONDITION_SCHEMA = vol.All(
vol.Schema(
{
**CONDITION_BASE_SCHEMA,
vol.Required(CONF_CONDITION): "time",
"before": vol.Any(time, vol.All(str, entity_domain("input_datetime"))),
"after": vol.Any(time, vol.All(str, entity_domain("input_datetime"))),
@ -1008,6 +1017,7 @@ TIME_CONDITION_SCHEMA = vol.All(
ZONE_CONDITION_SCHEMA = vol.Schema(
{
**CONDITION_BASE_SCHEMA,
vol.Required(CONF_CONDITION): "zone",
vol.Required(CONF_ENTITY_ID): entity_ids,
"zone": entity_ids,
@ -1019,6 +1029,7 @@ ZONE_CONDITION_SCHEMA = vol.Schema(
AND_CONDITION_SCHEMA = vol.Schema(
{
**CONDITION_BASE_SCHEMA,
vol.Required(CONF_CONDITION): "and",
vol.Required(CONF_CONDITIONS): vol.All(
ensure_list,
@ -1030,6 +1041,7 @@ AND_CONDITION_SCHEMA = vol.Schema(
OR_CONDITION_SCHEMA = vol.Schema(
{
**CONDITION_BASE_SCHEMA,
vol.Required(CONF_CONDITION): "or",
vol.Required(CONF_CONDITIONS): vol.All(
ensure_list,
@ -1041,6 +1053,7 @@ OR_CONDITION_SCHEMA = vol.Schema(
NOT_CONDITION_SCHEMA = vol.Schema(
{
**CONDITION_BASE_SCHEMA,
vol.Required(CONF_CONDITION): "not",
vol.Required(CONF_CONDITIONS): vol.All(
ensure_list,
@ -1052,6 +1065,7 @@ NOT_CONDITION_SCHEMA = vol.Schema(
DEVICE_CONDITION_BASE_SCHEMA = vol.Schema(
{
**CONDITION_BASE_SCHEMA,
vol.Required(CONF_CONDITION): "device",
vol.Required(CONF_DEVICE_ID): str,
vol.Required(CONF_DOMAIN): str,
@ -1087,14 +1101,14 @@ TRIGGER_SCHEMA = vol.All(
_SCRIPT_DELAY_SCHEMA = vol.Schema(
{
vol.Optional(CONF_ALIAS): string,
**SCRIPT_ACTION_BASE_SCHEMA,
vol.Required(CONF_DELAY): positive_time_period_template,
}
)
_SCRIPT_WAIT_TEMPLATE_SCHEMA = vol.Schema(
{
vol.Optional(CONF_ALIAS): string,
**SCRIPT_ACTION_BASE_SCHEMA,
vol.Required(CONF_WAIT_TEMPLATE): template,
vol.Optional(CONF_TIMEOUT): positive_time_period_template,
vol.Optional(CONF_CONTINUE_ON_TIMEOUT): boolean,
@ -1102,16 +1116,22 @@ _SCRIPT_WAIT_TEMPLATE_SCHEMA = vol.Schema(
)
DEVICE_ACTION_BASE_SCHEMA = vol.Schema(
{vol.Required(CONF_DEVICE_ID): string, vol.Required(CONF_DOMAIN): str}
{
**SCRIPT_ACTION_BASE_SCHEMA,
vol.Required(CONF_DEVICE_ID): string,
vol.Required(CONF_DOMAIN): str,
}
)
DEVICE_ACTION_SCHEMA = DEVICE_ACTION_BASE_SCHEMA.extend({}, extra=vol.ALLOW_EXTRA)
_SCRIPT_SCENE_SCHEMA = vol.Schema({vol.Required(CONF_SCENE): entity_domain("scene")})
_SCRIPT_SCENE_SCHEMA = vol.Schema(
{**SCRIPT_ACTION_BASE_SCHEMA, vol.Required(CONF_SCENE): entity_domain("scene")}
)
_SCRIPT_REPEAT_SCHEMA = vol.Schema(
{
vol.Optional(CONF_ALIAS): string,
**SCRIPT_ACTION_BASE_SCHEMA,
vol.Required(CONF_REPEAT): vol.All(
{
vol.Exclusive(CONF_COUNT, "repeat"): vol.Any(vol.Coerce(int), template),
@ -1130,11 +1150,12 @@ _SCRIPT_REPEAT_SCHEMA = vol.Schema(
_SCRIPT_CHOOSE_SCHEMA = vol.Schema(
{
vol.Optional(CONF_ALIAS): string,
**SCRIPT_ACTION_BASE_SCHEMA,
vol.Required(CONF_CHOOSE): vol.All(
ensure_list,
[
{
vol.Optional(CONF_ALIAS): string,
vol.Required(CONF_CONDITIONS): vol.All(
ensure_list, [CONDITION_SCHEMA]
),
@ -1148,7 +1169,7 @@ _SCRIPT_CHOOSE_SCHEMA = vol.Schema(
_SCRIPT_WAIT_FOR_TRIGGER_SCHEMA = vol.Schema(
{
vol.Optional(CONF_ALIAS): string,
**SCRIPT_ACTION_BASE_SCHEMA,
vol.Required(CONF_WAIT_FOR_TRIGGER): TRIGGER_SCHEMA,
vol.Optional(CONF_TIMEOUT): positive_time_period_template,
vol.Optional(CONF_CONTINUE_ON_TIMEOUT): boolean,
@ -1157,7 +1178,7 @@ _SCRIPT_WAIT_FOR_TRIGGER_SCHEMA = vol.Schema(
_SCRIPT_SET_SCHEMA = vol.Schema(
{
vol.Optional(CONF_ALIAS): string,
**SCRIPT_ACTION_BASE_SCHEMA,
vol.Required(CONF_VARIABLES): SCRIPT_VARIABLES_SCHEMA,
}
)

View file

@ -18,7 +18,7 @@ from typing import (
cast,
)
from async_timeout import timeout
import async_timeout
import voluptuous as vol
from homeassistant import exceptions
@ -235,6 +235,13 @@ class _ScriptRun:
msg, *args, level=level, **kwargs
)
def _step_log(self, default_message, timeout=None):
self._script.last_action = self._action.get(CONF_ALIAS, default_message)
_timeout = (
"" if timeout is None else f" (timeout: {timedelta(seconds=timeout)})"
)
self._log("Executing step %s%s", self._script.last_action, _timeout)
async def async_run(self) -> None:
"""Run script."""
try:
@ -327,13 +334,12 @@ class _ScriptRun:
"""Handle delay."""
delay = self._get_pos_time_period_template(CONF_DELAY)
self._script.last_action = self._action.get(CONF_ALIAS, f"delay {delay}")
self._log("Executing step %s", self._script.last_action)
self._step_log(f"delay {delay}")
delay = delay.total_seconds()
self._changed()
try:
async with timeout(delay):
async with async_timeout.timeout(delay):
await self._stop.wait()
except asyncio.TimeoutError:
pass
@ -341,18 +347,13 @@ class _ScriptRun:
async def _async_wait_template_step(self):
"""Handle a wait template."""
if CONF_TIMEOUT in self._action:
delay = self._get_pos_time_period_template(CONF_TIMEOUT).total_seconds()
timeout = self._get_pos_time_period_template(CONF_TIMEOUT).total_seconds()
else:
delay = None
timeout = None
self._script.last_action = self._action.get(CONF_ALIAS, "wait template")
self._log(
"Executing step %s%s",
self._script.last_action,
"" if delay is None else f" (timeout: {timedelta(seconds=delay)})",
)
self._step_log("wait template", timeout)
self._variables["wait"] = {"remaining": delay, "completed": False}
self._variables["wait"] = {"remaining": timeout, "completed": False}
wait_template = self._action[CONF_WAIT_TEMPLATE]
wait_template.hass = self._hass
@ -366,7 +367,7 @@ class _ScriptRun:
def async_script_wait(entity_id, from_s, to_s):
"""Handle script after template condition is true."""
self._variables["wait"] = {
"remaining": to_context.remaining if to_context else delay,
"remaining": to_context.remaining if to_context else timeout,
"completed": True,
}
done.set()
@ -382,7 +383,7 @@ class _ScriptRun:
self._hass.async_create_task(flag.wait()) for flag in (self._stop, done)
]
try:
async with timeout(delay) as to_context:
async with async_timeout.timeout(timeout) as to_context:
await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
except asyncio.TimeoutError as ex:
if not self._action.get(CONF_CONTINUE_ON_TIMEOUT, True):
@ -431,8 +432,7 @@ class _ScriptRun:
async def _async_call_service_step(self):
"""Call the service specified in the action."""
self._script.last_action = self._action.get(CONF_ALIAS, "call service")
self._log("Executing step %s", self._script.last_action)
self._step_log("call service")
params = service.async_prepare_call_from_config(
self._hass, self._action, self._variables
@ -467,8 +467,7 @@ class _ScriptRun:
async def _async_device_step(self):
"""Perform the device automation specified in the action."""
self._script.last_action = self._action.get(CONF_ALIAS, "device automation")
self._log("Executing step %s", self._script.last_action)
self._step_log("device automation")
platform = await device_automation.async_get_device_automation_platform(
self._hass, self._action[CONF_DOMAIN], "action"
)
@ -478,8 +477,7 @@ class _ScriptRun:
async def _async_scene_step(self):
"""Activate the scene specified in the action."""
self._script.last_action = self._action.get(CONF_ALIAS, "activate scene")
self._log("Executing step %s", self._script.last_action)
self._step_log("activate scene")
await self._hass.services.async_call(
scene.DOMAIN,
SERVICE_TURN_ON,
@ -490,10 +488,7 @@ class _ScriptRun:
async def _async_event_step(self):
"""Fire an event."""
self._script.last_action = self._action.get(
CONF_ALIAS, self._action[CONF_EVENT]
)
self._log("Executing step %s", self._script.last_action)
self._step_log(self._action.get(CONF_ALIAS, self._action[CONF_EVENT]))
event_data = {}
for conf in [CONF_EVENT_DATA, CONF_EVENT_DATA_TEMPLATE]:
if conf not in self._action:
@ -627,25 +622,20 @@ class _ScriptRun:
async def _async_wait_for_trigger_step(self):
"""Wait for a trigger event."""
if CONF_TIMEOUT in self._action:
delay = self._get_pos_time_period_template(CONF_TIMEOUT).total_seconds()
timeout = self._get_pos_time_period_template(CONF_TIMEOUT).total_seconds()
else:
delay = None
timeout = None
self._script.last_action = self._action.get(CONF_ALIAS, "wait for trigger")
self._log(
"Executing step %s%s",
self._script.last_action,
"" if delay is None else f" (timeout: {timedelta(seconds=delay)})",
)
self._step_log("wait for trigger", timeout)
variables = {**self._variables}
self._variables["wait"] = {"remaining": delay, "trigger": None}
self._variables["wait"] = {"remaining": timeout, "trigger": None}
done = asyncio.Event()
async def async_done(variables, context=None):
self._variables["wait"] = {
"remaining": to_context.remaining if to_context else delay,
"remaining": to_context.remaining if to_context else timeout,
"trigger": variables["trigger"],
}
done.set()
@ -671,7 +661,7 @@ class _ScriptRun:
self._hass.async_create_task(flag.wait()) for flag in (self._stop, done)
]
try:
async with timeout(delay) as to_context:
async with async_timeout.timeout(timeout) as to_context:
await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
except asyncio.TimeoutError as ex:
if not self._action.get(CONF_CONTINUE_ON_TIMEOUT, True):
@ -685,8 +675,7 @@ class _ScriptRun:
async def _async_variables_step(self):
"""Set a variable value."""
self._script.last_action = self._action.get(CONF_ALIAS, "setting variables")
self._log("Executing step %s", self._script.last_action)
self._step_log("setting variables")
self._variables = self._action[CONF_VARIABLES].async_render(
self._hass, self._variables, render_as_defaults=False
)
@ -1111,10 +1100,11 @@ class Script:
await self._async_get_condition(config)
for config in choice.get(CONF_CONDITIONS, [])
]
choice_name = choice.get(CONF_ALIAS, f"choice {idx}")
sub_script = Script(
self._hass,
choice[CONF_SEQUENCE],
f"{self.name}: {step_name}: choice {idx}",
f"{self.name}: {step_name}: {choice_name}",
self.domain,
running_description=self.running_description,
script_mode=SCRIPT_MODE_PARALLEL,

View file

@ -34,6 +34,7 @@ async def test_and_condition(hass):
test = await condition.async_from_config(
hass,
{
"alias": "And Condition",
"condition": "and",
"conditions": [
{
@ -71,6 +72,7 @@ async def test_and_condition_with_template(hass):
"condition": "and",
"conditions": [
{
"alias": "Template Condition",
"condition": "template",
"value_template": '{{ states.sensor.temperature.state == "100" }}',
},
@ -98,6 +100,7 @@ async def test_or_condition(hass):
test = await condition.async_from_config(
hass,
{
"alias": "Or Condition",
"condition": "or",
"conditions": [
{
@ -159,6 +162,7 @@ async def test_not_condition(hass):
test = await condition.async_from_config(
hass,
{
"alias": "Not Condition",
"condition": "not",
"conditions": [
{
@ -226,36 +230,45 @@ async def test_not_condition_with_template(hass):
async def test_time_window(hass):
"""Test time condition windows."""
sixam = dt.parse_time("06:00:00")
sixpm = dt.parse_time("18:00:00")
sixam = "06:00:00"
sixpm = "18:00:00"
test1 = await condition.async_from_config(
hass,
{"alias": "Time Cond", "condition": "time", "after": sixam, "before": sixpm},
)
test2 = await condition.async_from_config(
hass,
{"alias": "Time Cond", "condition": "time", "after": sixpm, "before": sixam},
)
with patch(
"homeassistant.helpers.condition.dt_util.now",
return_value=dt.now().replace(hour=3),
):
assert not condition.time(hass, after=sixam, before=sixpm)
assert condition.time(hass, after=sixpm, before=sixam)
assert not test1(hass)
assert test2(hass)
with patch(
"homeassistant.helpers.condition.dt_util.now",
return_value=dt.now().replace(hour=9),
):
assert condition.time(hass, after=sixam, before=sixpm)
assert not condition.time(hass, after=sixpm, before=sixam)
assert test1(hass)
assert not test2(hass)
with patch(
"homeassistant.helpers.condition.dt_util.now",
return_value=dt.now().replace(hour=15),
):
assert condition.time(hass, after=sixam, before=sixpm)
assert not condition.time(hass, after=sixpm, before=sixam)
assert test1(hass)
assert not test2(hass)
with patch(
"homeassistant.helpers.condition.dt_util.now",
return_value=dt.now().replace(hour=21),
):
assert not condition.time(hass, after=sixam, before=sixpm)
assert condition.time(hass, after=sixpm, before=sixam)
assert not test1(hass)
assert test2(hass)
async def test_time_using_input_datetime(hass):
@ -439,6 +452,7 @@ async def test_multiple_states(hass):
"condition": "and",
"conditions": [
{
"alias": "State Condition",
"condition": "state",
"entity_id": "sensor.temperature",
"state": ["100", "200"],
@ -709,6 +723,7 @@ async def test_numeric_state_multiple_entities(hass):
"condition": "and",
"conditions": [
{
"alias": "Numeric State Condition",
"condition": "numeric_state",
"entity_id": ["sensor.temperature_1", "sensor.temperature_2"],
"below": 50,
@ -911,6 +926,7 @@ async def test_zone_multiple_entities(hass):
"condition": "and",
"conditions": [
{
"alias": "Zone Condition",
"condition": "zone",
"entity_id": ["device_tracker.person_1", "device_tracker.person_2"],
"zone": "zone.home",

View file

@ -358,6 +358,11 @@ def test_service_schema():
"service": "homeassistant.turn_on",
"entity_id": ["light.kitchen", "light.ceiling"],
},
{
"service": "light.turn_on",
"entity_id": "all",
"alias": "turn on kitchen lights",
},
)
for value in options:
cv.SERVICE_SCHEMA(value)

View file

@ -50,7 +50,10 @@ async def test_firing_event_basic(hass, caplog):
context = Context()
events = async_capture_events(hass, event)
sequence = cv.SCRIPT_SCHEMA({"event": event, "event_data": {"hello": "world"}})
alias = "event step"
sequence = cv.SCRIPT_SCHEMA(
{"alias": alias, "event": event, "event_data": {"hello": "world"}}
)
script_obj = script.Script(
hass, sequence, "Test Name", "test_domain", running_description="test script"
)
@ -63,6 +66,7 @@ async def test_firing_event_basic(hass, caplog):
assert events[0].data.get("hello") == "world"
assert ".test_name:" in caplog.text
assert "Test Name: Running test script" in caplog.text
assert f"Executing step {alias}" in caplog.text
async def test_firing_event_template(hass):
@ -107,12 +111,15 @@ async def test_firing_event_template(hass):
}
async def test_calling_service_basic(hass):
async def test_calling_service_basic(hass, caplog):
"""Test the calling of a service."""
context = Context()
calls = async_mock_service(hass, "test", "script")
sequence = cv.SCRIPT_SCHEMA({"service": "test.script", "data": {"hello": "world"}})
alias = "service step"
sequence = cv.SCRIPT_SCHEMA(
{"alias": alias, "service": "test.script", "data": {"hello": "world"}}
)
script_obj = script.Script(hass, sequence, "Test Name", "test_domain")
await script_obj.async_run(context=context)
@ -121,6 +128,7 @@ async def test_calling_service_basic(hass):
assert len(calls) == 1
assert calls[0].context is context
assert calls[0].data.get("hello") == "world"
assert f"Executing step {alias}" in caplog.text
async def test_calling_service_template(hass):
@ -250,12 +258,13 @@ async def test_multiple_runs_no_wait(hass):
assert len(calls) == 4
async def test_activating_scene(hass):
async def test_activating_scene(hass, caplog):
"""Test the activation of a scene."""
context = Context()
calls = async_mock_service(hass, scene.DOMAIN, SERVICE_TURN_ON)
sequence = cv.SCRIPT_SCHEMA({"scene": "scene.hello"})
alias = "scene step"
sequence = cv.SCRIPT_SCHEMA({"alias": alias, "scene": "scene.hello"})
script_obj = script.Script(hass, sequence, "Test Name", "test_domain")
await script_obj.async_run(context=context)
@ -264,6 +273,7 @@ async def test_activating_scene(hass):
assert len(calls) == 1
assert calls[0].context is context
assert calls[0].data.get(ATTR_ENTITY_ID) == "scene.hello"
assert f"Executing step {alias}" in caplog.text
@pytest.mark.parametrize("count", [1, 3])
@ -1063,14 +1073,16 @@ async def test_condition_warning(hass, caplog):
assert len(events) == 1
async def test_condition_basic(hass):
async def test_condition_basic(hass, caplog):
"""Test if we can use conditions in a script."""
event = "test_event"
events = async_capture_events(hass, event)
alias = "condition step"
sequence = cv.SCRIPT_SCHEMA(
[
{"event": event},
{
"alias": alias,
"condition": "template",
"value_template": "{{ states.test.entity.state == 'hello' }}",
},
@ -1083,6 +1095,8 @@ async def test_condition_basic(hass):
await script_obj.async_run(context=Context())
await hass.async_block_till_done()
assert f"Test condition {alias}: True" in caplog.text
caplog.clear()
assert len(events) == 2
hass.states.async_set("test.entity", "goodbye")
@ -1090,6 +1104,7 @@ async def test_condition_basic(hass):
await script_obj.async_run(context=Context())
await hass.async_block_till_done()
assert f"Test condition {alias}: False" in caplog.text
assert len(events) == 3
@ -1140,14 +1155,16 @@ async def test_condition_all_cached(hass):
assert len(script_obj._config_cache) == 2
async def test_repeat_count(hass):
async def test_repeat_count(hass, caplog):
"""Test repeat action w/ count option."""
event = "test_event"
events = async_capture_events(hass, event)
count = 3
alias = "condition step"
sequence = cv.SCRIPT_SCHEMA(
{
"alias": alias,
"repeat": {
"count": count,
"sequence": {
@ -1158,7 +1175,7 @@ async def test_repeat_count(hass):
"last": "{{ repeat.last }}",
},
},
}
},
}
)
script_obj = script.Script(hass, sequence, "Test Name", "test_domain")
@ -1171,6 +1188,7 @@ async def test_repeat_count(hass):
assert event.data.get("first") == (index == 0)
assert event.data.get("index") == index + 1
assert event.data.get("last") == (index == count - 1)
assert caplog.text.count(f"Repeating {alias}") == count
@pytest.mark.parametrize("condition", ["while", "until"])
@ -1470,26 +1488,44 @@ async def test_choose_warning(hass, caplog):
@pytest.mark.parametrize("var,result", [(1, "first"), (2, "second"), (3, "default")])
async def test_choose(hass, var, result):
async def test_choose(hass, caplog, var, result):
"""Test choose action."""
event = "test_event"
events = async_capture_events(hass, event)
alias = "choose step"
choice = {1: "choice one", 2: "choice two", 3: None}
aliases = {1: "sequence one", 2: "sequence two", 3: "default sequence"}
sequence = cv.SCRIPT_SCHEMA(
{
"alias": alias,
"choose": [
{
"alias": choice[1],
"conditions": {
"condition": "template",
"value_template": "{{ var == 1 }}",
},
"sequence": {"event": event, "event_data": {"choice": "first"}},
"sequence": {
"alias": aliases[1],
"event": event,
"event_data": {"choice": "first"},
},
},
{
"alias": choice[2],
"conditions": "{{ var == 2 }}",
"sequence": {"event": event, "event_data": {"choice": "second"}},
"sequence": {
"alias": aliases[2],
"event": event,
"event_data": {"choice": "second"},
},
},
],
"default": {"event": event, "event_data": {"choice": "default"}},
"default": {
"alias": aliases[3],
"event": event,
"event_data": {"choice": "default"},
},
}
)
script_obj = script.Script(hass, sequence, "Test Name", "test_domain")
@ -1499,6 +1535,10 @@ async def test_choose(hass, var, result):
assert len(events) == 1
assert events[0].data["choice"] == result
expected_choice = choice[var]
if var == 3:
expected_choice = "default"
assert f"{alias}: {expected_choice}: Executing step {aliases[var]}" in caplog.text
@pytest.mark.parametrize(
@ -2115,9 +2155,10 @@ async def test_started_action(hass, caplog):
async def test_set_variable(hass, caplog):
"""Test setting variables in scripts."""
alias = "variables step"
sequence = cv.SCRIPT_SCHEMA(
[
{"variables": {"variable": "value"}},
{"alias": alias, "variables": {"variable": "value"}},
{"service": "test.script", "data": {"value": "{{ variable }}"}},
]
)
@ -2129,6 +2170,7 @@ async def test_set_variable(hass, caplog):
await hass.async_block_till_done()
assert mock_calls[0].data["value"] == "value"
assert f"Executing step {alias}" in caplog.text
async def test_set_redefines_variable(hass, caplog):