Change trigger platform key to trigger (#124357)

* fix

* Fix

* Fix

* Update homeassistant/helpers/config_validation.py

Co-authored-by: Erik Montnemery <erik@montnemery.com>

* Fix

* Fix

* Fix

* Fix

* Add more tests

* Fix

* Fix tests

* Add tests

* Let's see what the CI does

* It fails on the code that tested the thing ofc

* It fails on the code that tested the thing ofc

* Revert test thingy

* Now the test works again, lovely

* Another one

* Fix websocket thingy

* Only copy when needed

* Improve comment

* Remove test

* Fix docstring

* I think this now also work since this transforms trigger to platform

* Add comment

* Update homeassistant/helpers/config_validation.py

Co-authored-by: Erik Montnemery <erik@montnemery.com>

* Update homeassistant/helpers/config_validation.py

Co-authored-by: Erik Montnemery <erik@montnemery.com>

* Update homeassistant/helpers/config_validation.py

Co-authored-by: Erik Montnemery <erik@montnemery.com>

* Check for mapping

* Add test

* Update homeassistant/helpers/config_validation.py

Co-authored-by: Erik Montnemery <erik@montnemery.com>

* Update test to also test for trigger keys

---------

Co-authored-by: Erik Montnemery <erik@montnemery.com>
This commit is contained in:
Joost Lekkerkerker 2024-09-25 14:19:58 +02:00 committed by GitHub
parent 9d29307532
commit a1906b434f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 185 additions and 58 deletions

View file

@ -481,8 +481,11 @@ async def websocket_device_automation_get_condition_capabilities(
@websocket_api.websocket_command( @websocket_api.websocket_command(
{ {
vol.Required("type"): "device_automation/trigger/capabilities", vol.Required("type"): "device_automation/trigger/capabilities",
vol.Required("trigger"): DEVICE_TRIGGER_BASE_SCHEMA.extend( # The frontend responds with `trigger` as key, while the
{}, extra=vol.ALLOW_EXTRA # `DEVICE_TRIGGER_BASE_SCHEMA` expects `platform1` as key.
vol.Required("trigger"): vol.All(
cv._backward_compat_trigger_schema, # noqa: SLF001
DEVICE_TRIGGER_BASE_SCHEMA.extend({}, extra=vol.ALLOW_EXTRA),
), ),
} }
) )

View file

@ -282,6 +282,7 @@ CONF_THEN: Final = "then"
CONF_TIMEOUT: Final = "timeout" CONF_TIMEOUT: Final = "timeout"
CONF_TIME_ZONE: Final = "time_zone" CONF_TIME_ZONE: Final = "time_zone"
CONF_TOKEN: Final = "token" CONF_TOKEN: Final = "token"
CONF_TRIGGER: Final = "trigger"
CONF_TRIGGERS: Final = "triggers" CONF_TRIGGERS: Final = "triggers"
CONF_TRIGGER_TIME: Final = "trigger_time" CONF_TRIGGER_TIME: Final = "trigger_time"
CONF_TTL: Final = "ttl" CONF_TTL: Final = "ttl"

View file

@ -4,7 +4,7 @@
# with PEP 695 syntax. Fixed in Python 3.13. # with PEP 695 syntax. Fixed in Python 3.13.
# from __future__ import annotations # from __future__ import annotations
from collections.abc import Callable, Hashable from collections.abc import Callable, Hashable, Mapping
import contextlib import contextlib
from contextvars import ContextVar from contextvars import ContextVar
from datetime import ( from datetime import (
@ -81,6 +81,7 @@ from homeassistant.const import (
CONF_TARGET, CONF_TARGET,
CONF_THEN, CONF_THEN,
CONF_TIMEOUT, CONF_TIMEOUT,
CONF_TRIGGER,
CONF_TRIGGERS, CONF_TRIGGERS,
CONF_UNTIL, CONF_UNTIL,
CONF_VALUE_TEMPLATE, CONF_VALUE_TEMPLATE,
@ -1769,6 +1770,30 @@ CONDITION_ACTION_SCHEMA: vol.Schema = vol.Schema(
) )
) )
def _backward_compat_trigger_schema(value: Any | None) -> Any:
"""Rewrite trigger `trigger` to `platform`.
`platform` has been renamed to `trigger` in user documentation and in the automation
editor. The Python trigger implementation still uses `platform`, so we need to
rename `trigger` to `platform.
"""
if not isinstance(value, Mapping):
# If the value is not a mapping, we let that be handled by the TRIGGER_SCHEMA
return value
if CONF_TRIGGER in value:
if CONF_PLATFORM in value:
raise vol.Invalid(
"Cannot specify both 'platform' and 'trigger'. Please use 'trigger' only."
)
value = dict(value)
value[CONF_PLATFORM] = value.pop(CONF_TRIGGER)
return value
TRIGGER_BASE_SCHEMA = vol.Schema( TRIGGER_BASE_SCHEMA = vol.Schema(
{ {
vol.Optional(CONF_ALIAS): str, vol.Optional(CONF_ALIAS): str,
@ -1804,7 +1829,9 @@ def _base_trigger_validator(value: Any) -> Any:
TRIGGER_SCHEMA = vol.All( TRIGGER_SCHEMA = vol.All(
ensure_list, _base_trigger_list_flatten, [_base_trigger_validator] ensure_list,
_base_trigger_list_flatten,
[vol.All(_backward_compat_trigger_schema, _base_trigger_validator)],
) )
_SCRIPT_DELAY_SCHEMA = vol.Schema( _SCRIPT_DELAY_SCHEMA = vol.Schema(

View file

@ -602,7 +602,7 @@ def _selector_serializer(schema: Any) -> Any: # noqa: C901
return {"type": "string", "format": "time"} return {"type": "string", "format": "time"}
if isinstance(schema, selector.TriggerSelector): if isinstance(schema, selector.TriggerSelector):
return convert(cv.TRIGGER_SCHEMA) return {"type": "array", "items": {"type": "string"}}
if schema.config.get("multiple"): if schema.config.get("multiple"):
return {"type": "array", "items": {"type": "string"}} return {"type": "array", "items": {"type": "string"}}

View file

@ -1971,37 +1971,37 @@ async def test_extraction_functions(
{ {
"alias": "test1", "alias": "test1",
"triggers": [ "triggers": [
{"platform": "state", "entity_id": "sensor.trigger_state"}, {"trigger": "state", "entity_id": "sensor.trigger_state"},
{ {
"platform": "numeric_state", "trigger": "numeric_state",
"entity_id": "sensor.trigger_numeric_state", "entity_id": "sensor.trigger_numeric_state",
"above": 10, "above": 10,
}, },
{ {
"platform": "calendar", "trigger": "calendar",
"entity_id": "calendar.trigger_calendar", "entity_id": "calendar.trigger_calendar",
"event": "start", "event": "start",
}, },
{ {
"platform": "event", "trigger": "event",
"event_type": "state_changed", "event_type": "state_changed",
"event_data": {"entity_id": "sensor.trigger_event"}, "event_data": {"entity_id": "sensor.trigger_event"},
}, },
# entity_id is a list of strings (not supported) # entity_id is a list of strings (not supported)
{ {
"platform": "event", "trigger": "event",
"event_type": "state_changed", "event_type": "state_changed",
"event_data": {"entity_id": ["sensor.trigger_event2"]}, "event_data": {"entity_id": ["sensor.trigger_event2"]},
}, },
# entity_id is not a valid entity ID # entity_id is not a valid entity ID
{ {
"platform": "event", "trigger": "event",
"event_type": "state_changed", "event_type": "state_changed",
"event_data": {"entity_id": "abc"}, "event_data": {"entity_id": "abc"},
}, },
# entity_id is not a string # entity_id is not a string
{ {
"platform": "event", "trigger": "event",
"event_type": "state_changed", "event_type": "state_changed",
"event_data": {"entity_id": 123}, "event_data": {"entity_id": 123},
}, },
@ -2044,36 +2044,36 @@ async def test_extraction_functions(
"alias": "test2", "alias": "test2",
"triggers": [ "triggers": [
{ {
"platform": "device", "trigger": "device",
"domain": "light", "domain": "light",
"type": "turned_on", "type": "turned_on",
"entity_id": "light.trigger_2", "entity_id": "light.trigger_2",
"device_id": trigger_device_2.id, "device_id": trigger_device_2.id,
}, },
{ {
"platform": "tag", "trigger": "tag",
"tag_id": "1234", "tag_id": "1234",
"device_id": "device-trigger-tag1", "device_id": "device-trigger-tag1",
}, },
{ {
"platform": "tag", "trigger": "tag",
"tag_id": "1234", "tag_id": "1234",
"device_id": ["device-trigger-tag2", "device-trigger-tag3"], "device_id": ["device-trigger-tag2", "device-trigger-tag3"],
}, },
{ {
"platform": "event", "trigger": "event",
"event_type": "esphome.button_pressed", "event_type": "esphome.button_pressed",
"event_data": {"device_id": "device-trigger-event"}, "event_data": {"device_id": "device-trigger-event"},
}, },
# device_id is a list of strings (not supported) # device_id is a list of strings (not supported)
{ {
"platform": "event", "trigger": "event",
"event_type": "esphome.button_pressed", "event_type": "esphome.button_pressed",
"event_data": {"device_id": ["device-trigger-event2"]}, "event_data": {"device_id": ["device-trigger-event2"]},
}, },
# device_id is not a string # device_id is not a string
{ {
"platform": "event", "trigger": "event",
"event_type": "esphome.button_pressed", "event_type": "esphome.button_pressed",
"event_data": {"device_id": 123}, "event_data": {"device_id": 123},
}, },
@ -2114,19 +2114,19 @@ async def test_extraction_functions(
"alias": "test3", "alias": "test3",
"triggers": [ "triggers": [
{ {
"platform": "event", "trigger": "event",
"event_type": "esphome.button_pressed", "event_type": "esphome.button_pressed",
"event_data": {"area_id": "area-trigger-event"}, "event_data": {"area_id": "area-trigger-event"},
}, },
# area_id is a list of strings (not supported) # area_id is a list of strings (not supported)
{ {
"platform": "event", "trigger": "event",
"event_type": "esphome.button_pressed", "event_type": "esphome.button_pressed",
"event_data": {"area_id": ["area-trigger-event2"]}, "event_data": {"area_id": ["area-trigger-event2"]},
}, },
# area_id is not a string # area_id is not a string
{ {
"platform": "event", "trigger": "event",
"event_type": "esphome.button_pressed", "event_type": "esphome.button_pressed",
"event_data": {"area_id": 123}, "event_data": {"area_id": 123},
}, },
@ -2287,7 +2287,7 @@ async def test_automation_variables(
"event_type": "{{ trigger.event.event_type }}", "event_type": "{{ trigger.event.event_type }}",
"this_variables": "{{this.entity_id}}", "this_variables": "{{this.entity_id}}",
}, },
"triggers": {"platform": "event", "event_type": "test_event"}, "triggers": {"trigger": "event", "event_type": "test_event"},
"actions": { "actions": {
"action": "test.automation", "action": "test.automation",
"data": { "data": {
@ -2302,7 +2302,7 @@ async def test_automation_variables(
"variables": { "variables": {
"test_var": "defined_in_config", "test_var": "defined_in_config",
}, },
"trigger": {"platform": "event", "event_type": "test_event_2"}, "trigger": {"trigger": "event", "event_type": "test_event_2"},
"conditions": { "conditions": {
"condition": "template", "condition": "template",
"value_template": "{{ trigger.event.data.pass_condition }}", "value_template": "{{ trigger.event.data.pass_condition }}",
@ -2315,7 +2315,7 @@ async def test_automation_variables(
"variables": { "variables": {
"test_var": "{{ trigger.event.data.break + 1 }}", "test_var": "{{ trigger.event.data.break + 1 }}",
}, },
"triggers": {"platform": "event", "event_type": "test_event_3"}, "triggers": {"trigger": "event", "event_type": "test_event_3"},
"actions": { "actions": {
"action": "test.automation", "action": "test.automation",
}, },
@ -2371,7 +2371,7 @@ async def test_automation_trigger_variables(
"trigger_variables": { "trigger_variables": {
"test_var": "defined_in_config", "test_var": "defined_in_config",
}, },
"trigger": {"platform": "event", "event_type": "test_event"}, "trigger": {"trigger": "event", "event_type": "test_event"},
"action": { "action": {
"action": "test.automation", "action": "test.automation",
"data": { "data": {
@ -2389,7 +2389,7 @@ async def test_automation_trigger_variables(
"test_var": "defined_in_config", "test_var": "defined_in_config",
"this_trigger_variables": "{{this.entity_id}}", "this_trigger_variables": "{{this.entity_id}}",
}, },
"trigger": {"platform": "event", "event_type": "test_event_2"}, "trigger": {"trigger": "event", "event_type": "test_event_2"},
"action": { "action": {
"action": "test.automation", "action": "test.automation",
"data": { "data": {
@ -2436,7 +2436,7 @@ async def test_automation_bad_trigger_variables(
"trigger_variables": { "trigger_variables": {
"test_var": "{{ states('foo.bar') }}", "test_var": "{{ states('foo.bar') }}",
}, },
"trigger": {"platform": "event", "event_type": "test_event"}, "trigger": {"trigger": "event", "event_type": "test_event"},
"action": { "action": {
"action": "test.automation", "action": "test.automation",
}, },
@ -2463,7 +2463,7 @@ async def test_automation_this_var_always(
{ {
automation.DOMAIN: [ automation.DOMAIN: [
{ {
"trigger": {"platform": "event", "event_type": "test_event"}, "trigger": {"trigger": "event", "event_type": "test_event"},
"action": { "action": {
"action": "test.automation", "action": "test.automation",
"data": { "data": {
@ -2739,7 +2739,7 @@ async def test_trigger_service(hass: HomeAssistant, calls: list[ServiceCall]) ->
{ {
automation.DOMAIN: { automation.DOMAIN: {
"alias": "hello", "alias": "hello",
"trigger": {"platform": "event", "event_type": "test_event"}, "trigger": {"trigger": "event", "event_type": "test_event"},
"action": { "action": {
"action": "test.automation", "action": "test.automation",
"data_template": {"trigger": "{{ trigger }}"}, "data_template": {"trigger": "{{ trigger }}"},
@ -2771,9 +2771,9 @@ async def test_trigger_condition_implicit_id(
{ {
automation.DOMAIN: { automation.DOMAIN: {
"trigger": [ "trigger": [
{"platform": "event", "event_type": "test_event1"}, {"trigger": "event", "event_type": "test_event1"},
{"platform": "event", "event_type": "test_event2"}, {"trigger": "event", "event_type": "test_event2"},
{"platform": "event", "event_type": "test_event3"}, {"trigger": "event", "event_type": "test_event3"},
], ],
"action": { "action": {
"choose": [ "choose": [
@ -2823,8 +2823,8 @@ async def test_trigger_condition_explicit_id(
{ {
automation.DOMAIN: { automation.DOMAIN: {
"trigger": [ "trigger": [
{"platform": "event", "event_type": "test_event1", "id": "one"}, {"trigger": "event", "event_type": "test_event1", "id": "one"},
{"platform": "event", "event_type": "test_event2", "id": "two"}, {"trigger": "event", "event_type": "test_event2", "id": "two"},
], ],
"action": { "action": {
"choose": [ "choose": [
@ -2938,7 +2938,7 @@ async def test_recursive_automation_starting_script(
automation.DOMAIN: { automation.DOMAIN: {
"mode": automation_mode, "mode": automation_mode,
"trigger": [ "trigger": [
{"platform": "event", "event_type": "trigger_automation"}, {"trigger": "event", "event_type": "trigger_automation"},
], ],
"action": [ "action": [
{"action": "test.automation_started"}, {"action": "test.automation_started"},
@ -3020,7 +3020,7 @@ async def test_recursive_automation(
automation.DOMAIN: { automation.DOMAIN: {
"mode": automation_mode, "mode": automation_mode,
"trigger": [ "trigger": [
{"platform": "event", "event_type": "trigger_automation"}, {"trigger": "event", "event_type": "trigger_automation"},
], ],
"action": [ "action": [
{"event": "trigger_automation"}, {"event": "trigger_automation"},
@ -3082,7 +3082,7 @@ async def test_recursive_automation_restart_mode(
automation.DOMAIN: { automation.DOMAIN: {
"mode": SCRIPT_MODE_RESTART, "mode": SCRIPT_MODE_RESTART,
"trigger": [ "trigger": [
{"platform": "event", "event_type": "trigger_automation"}, {"trigger": "event", "event_type": "trigger_automation"},
], ],
"action": [ "action": [
{"event": "trigger_automation"}, {"event": "trigger_automation"},
@ -3121,7 +3121,7 @@ async def test_websocket_config(
"""Test config command.""" """Test config command."""
config = { config = {
"alias": "hello", "alias": "hello",
"triggers": {"platform": "event", "event_type": "test_event"}, "triggers": {"trigger": "event", "event_type": "test_event"},
"actions": {"action": "test.automation", "data": 100}, "actions": {"action": "test.automation", "data": 100},
} }
assert await async_setup_component( assert await async_setup_component(
@ -3191,7 +3191,7 @@ async def test_automation_turns_off_other_automation(hass: HomeAssistant) -> Non
automation.DOMAIN: [ automation.DOMAIN: [
{ {
"trigger": { "trigger": {
"platform": "state", "trigger": "state",
"entity_id": "binary_sensor.presence", "entity_id": "binary_sensor.presence",
"from": "on", "from": "on",
}, },
@ -3209,7 +3209,7 @@ async def test_automation_turns_off_other_automation(hass: HomeAssistant) -> Non
}, },
{ {
"trigger": { "trigger": {
"platform": "state", "trigger": "state",
"entity_id": "binary_sensor.presence", "entity_id": "binary_sensor.presence",
"from": "on", "from": "on",
"for": { "for": {
@ -3302,7 +3302,7 @@ async def test_two_automations_call_restart_script_same_time(
automation.DOMAIN: [ automation.DOMAIN: [
{ {
"trigger": { "trigger": {
"platform": "state", "trigger": "state",
"entity_id": "binary_sensor.presence", "entity_id": "binary_sensor.presence",
"to": "on", "to": "on",
}, },
@ -3314,7 +3314,7 @@ async def test_two_automations_call_restart_script_same_time(
}, },
{ {
"trigger": { "trigger": {
"platform": "state", "trigger": "state",
"entity_id": "binary_sensor.presence", "entity_id": "binary_sensor.presence",
"to": "on", "to": "on",
}, },
@ -3360,7 +3360,7 @@ async def test_two_automation_call_restart_script_right_after_each_other(
automation.DOMAIN: [ automation.DOMAIN: [
{ {
"trigger": { "trigger": {
"platform": "state", "trigger": "state",
"entity_id": ["input_boolean.test_1", "input_boolean.test_1"], "entity_id": ["input_boolean.test_1", "input_boolean.test_1"],
"from": "off", "from": "off",
"to": "on", "to": "on",
@ -3419,7 +3419,7 @@ async def test_action_backward_compatibility(
automation.DOMAIN, automation.DOMAIN,
{ {
automation.DOMAIN: { automation.DOMAIN: {
"trigger": {"platform": "event", "event_type": "test_event"}, "trigger": {"trigger": "event", "event_type": "test_event"},
"condition": { "condition": {
"condition": "template", "condition": "template",
"value_template": "{{ True }}", "value_template": "{{ True }}",
@ -3467,6 +3467,17 @@ async def test_action_backward_compatibility(
}, },
"Cannot specify both 'action' and 'actions'. Please use 'actions' only.", "Cannot specify both 'action' and 'actions'. Please use 'actions' only.",
), ),
(
{
"trigger": {
"platform": "event",
"trigger": "event",
"event_type": "test_event2",
},
"action": [],
},
"Cannot specify both 'platform' and 'trigger'. Please use 'trigger' only.",
),
], ],
) )
async def test_invalid_configuration( async def test_invalid_configuration(
@ -3483,3 +3494,28 @@ async def test_invalid_configuration(
) )
await hass.async_block_till_done() await hass.async_block_till_done()
assert message in caplog.text assert message in caplog.text
@pytest.mark.parametrize(
("trigger_key"),
["trigger", "platform"],
)
async def test_valid_configuration(
hass: HomeAssistant,
trigger_key: str,
) -> None:
"""Test for valid automation configurations."""
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"triggers": {
trigger_key: "event",
"event_type": "test_event2",
},
"action": [],
}
},
)
await hass.async_block_till_done()

View file

@ -39,7 +39,7 @@ async def test_exclude_attributes(
automation.DOMAIN, automation.DOMAIN,
{ {
automation.DOMAIN: { automation.DOMAIN: {
"trigger": {"platform": "event", "event_type": "test_event"}, "trigger": {"trigger": "event", "event_type": "test_event"},
"actions": {"action": "test.automation", "entity_id": "hello.world"}, "actions": {"action": "test.automation", "entity_id": "hello.world"},
} }
}, },

View file

@ -224,7 +224,7 @@ async def test_save_blueprint(
" service_to_call:\n a_number:\n selector:\n number:\n " " service_to_call:\n a_number:\n selector:\n number:\n "
" mode: box\n step: 1.0\n source_url:" " mode: box\n step: 1.0\n source_url:"
" https://github.com/balloob/home-assistant-config/blob/main/blueprints/automation/motion_light.yaml\ntriggers:\n" " https://github.com/balloob/home-assistant-config/blob/main/blueprints/automation/motion_light.yaml\ntriggers:\n"
" platform: event\n event_type: !input 'trigger_event'\nactions:\n " " trigger: event\n event_type: !input 'trigger_event'\nactions:\n "
" service: !input 'service_to_call'\n entity_id: light.kitchen\n" " service: !input 'service_to_call'\n entity_id: light.kitchen\n"
# c dumper will not quote the value after !input # c dumper will not quote the value after !input
"blueprint:\n name: Call service based on event\n domain: automation\n " "blueprint:\n name: Call service based on event\n domain: automation\n "
@ -232,7 +232,7 @@ async def test_save_blueprint(
" service_to_call:\n a_number:\n selector:\n number:\n " " service_to_call:\n a_number:\n selector:\n number:\n "
" mode: box\n step: 1.0\n source_url:" " mode: box\n step: 1.0\n source_url:"
" https://github.com/balloob/home-assistant-config/blob/main/blueprints/automation/motion_light.yaml\ntriggers:\n" " https://github.com/balloob/home-assistant-config/blob/main/blueprints/automation/motion_light.yaml\ntriggers:\n"
" platform: event\n event_type: !input trigger_event\nactions:\n service:" " trigger: event\n event_type: !input trigger_event\nactions:\n service:"
" !input service_to_call\n entity_id: light.kitchen\n" " !input service_to_call\n entity_id: light.kitchen\n"
) )
# Make sure ita parsable and does not raise # Make sure ita parsable and does not raise
@ -500,7 +500,7 @@ async def test_substituting_blueprint_inputs(
}, },
"triggers": { "triggers": {
"event_type": "test_event", "event_type": "test_event",
"platform": "event", "trigger": "event",
}, },
} }

View file

@ -110,14 +110,14 @@ async def test_update_automation_config(
), ),
( (
{ {
"trigger": {"platform": "automation"}, "trigger": {"trigger": "automation"},
"action": [], "action": [],
}, },
"Integration 'automation' does not provide trigger support", "Integration 'automation' does not provide trigger support",
), ),
( (
{ {
"trigger": {"platform": "event", "event_type": "test_event"}, "trigger": {"trigger": "event", "event_type": "test_event"},
"condition": { "condition": {
"condition": "state", "condition": "state",
# The UUID will fail being resolved to en entity_id # The UUID will fail being resolved to en entity_id
@ -130,7 +130,7 @@ async def test_update_automation_config(
), ),
( (
{ {
"trigger": {"platform": "event", "event_type": "test_event"}, "trigger": {"trigger": "event", "event_type": "test_event"},
"action": { "action": {
"condition": "state", "condition": "state",
# The UUID will fail being resolved to en entity_id # The UUID will fail being resolved to en entity_id
@ -336,12 +336,12 @@ async def test_bad_formatted_automations(
[ [
{ {
"id": "sun", "id": "sun",
"trigger": {"platform": "event", "event_type": "test_event"}, "trigger": {"trigger": "event", "event_type": "test_event"},
"action": {"service": "test.automation"}, "action": {"service": "test.automation"},
}, },
{ {
"id": "moon", "id": "moon",
"trigger": {"platform": "event", "event_type": "test_event"}, "trigger": {"trigger": "event", "event_type": "test_event"},
"action": {"service": "test.automation"}, "action": {"service": "test.automation"},
}, },
], ],

View file

@ -720,12 +720,17 @@ async def test_async_get_device_automations_all_devices_action_exception_throw(
assert "KeyError" in caplog.text assert "KeyError" in caplog.text
@pytest.mark.parametrize(
"trigger_key",
["trigger", "platform"],
)
async def test_websocket_get_trigger_capabilities( async def test_websocket_get_trigger_capabilities(
hass: HomeAssistant, hass: HomeAssistant,
hass_ws_client: WebSocketGenerator, hass_ws_client: WebSocketGenerator,
device_registry: dr.DeviceRegistry, device_registry: dr.DeviceRegistry,
entity_registry: er.EntityRegistry, entity_registry: er.EntityRegistry,
fake_integration, fake_integration,
trigger_key: str,
) -> None: ) -> None:
"""Test we get the expected trigger capabilities through websocket.""" """Test we get the expected trigger capabilities through websocket."""
await async_setup_component(hass, "device_automation", {}) await async_setup_component(hass, "device_automation", {})
@ -767,11 +772,12 @@ async def test_websocket_get_trigger_capabilities(
assert msg["id"] == 1 assert msg["id"] == 1
assert msg["type"] == TYPE_RESULT assert msg["type"] == TYPE_RESULT
assert msg["success"] assert msg["success"]
triggers = msg["result"] triggers: dict = msg["result"]
msg_id = 2 msg_id = 2
assert len(triggers) == 3 # toggled, turned_on, turned_off assert len(triggers) == 3 # toggled, turned_on, turned_off
for trigger in triggers: for trigger in triggers:
trigger[trigger_key] = trigger.pop("platform")
await client.send_json( await client.send_json(
{ {
"id": msg_id, "id": msg_id,

View file

@ -1841,7 +1841,7 @@ async def test_nested_trigger_list() -> None:
"event_type": "trigger_3", "event_type": "trigger_3",
}, },
{ {
"platform": "event", "trigger": "event",
"event_type": "trigger_4", "event_type": "trigger_4",
}, },
], ],
@ -1891,7 +1891,36 @@ async def test_nested_trigger_list_extra() -> None:
validated_triggers = TRIGGER_SCHEMA(trigger_config) validated_triggers = TRIGGER_SCHEMA(trigger_config)
assert validated_triggers == trigger_config assert validated_triggers == [
{
"platform": "other",
"triggers": [
{
"platform": "event",
"event_type": "trigger_1",
},
{
"platform": "event",
"event_type": "trigger_2",
},
],
},
]
async def test_trigger_backwards_compatibility() -> None:
"""Test triggers with backwards compatibility."""
assert cv._backward_compat_trigger_schema("str") == "str"
assert cv._backward_compat_trigger_schema({"platform": "abc"}) == {
"platform": "abc"
}
assert cv._backward_compat_trigger_schema({"trigger": "abc"}) == {"platform": "abc"}
with pytest.raises(
vol.Invalid,
match="Cannot specify both 'platform' and 'trigger'. Please use 'trigger' only.",
):
cv._backward_compat_trigger_schema({"trigger": "abc", "platform": "def"})
async def test_is_entity_service_schema( async def test_is_entity_service_schema(

View file

@ -1,6 +1,7 @@
"""Test selectors.""" """Test selectors."""
from enum import Enum from enum import Enum
from typing import Any
import pytest import pytest
import voluptuous as vol import voluptuous as vol
@ -1107,6 +1108,13 @@ def test_condition_selector_schema(
( (
{}, {},
( (
[
{
"platform": "numeric_state",
"entity_id": ["sensor.temperature"],
"below": 20,
}
],
[ [
{ {
"platform": "numeric_state", "platform": "numeric_state",
@ -1122,7 +1130,24 @@ def test_condition_selector_schema(
) )
def test_trigger_selector_schema(schema, valid_selections, invalid_selections) -> None: def test_trigger_selector_schema(schema, valid_selections, invalid_selections) -> None:
"""Test trigger sequence selector.""" """Test trigger sequence selector."""
_test_selector("trigger", schema, valid_selections, invalid_selections)
def _custom_trigger_serializer(
triggers: list[dict[str, Any]],
) -> list[dict[str, Any]]:
res = []
for trigger in triggers:
if "trigger" in trigger:
trigger["platform"] = trigger.pop("trigger")
res.append(trigger)
return res
_test_selector(
"trigger",
schema,
valid_selections,
invalid_selections,
_custom_trigger_serializer,
)
@pytest.mark.parametrize( @pytest.mark.parametrize(

View file

@ -11,7 +11,7 @@ blueprint:
number: number:
mode: "box" mode: "box"
triggers: triggers:
platform: event trigger: event
event_type: !input trigger_event event_type: !input trigger_event
actions: actions:
service: !input service_to_call service: !input service_to_call