Use entity registry id in toggle_entity device automations (#94995)

* Use entity registry id in toggle_entity device automations

* Update tests

---------

Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
Erik Montnemery 2023-06-26 09:59:01 +02:00 committed by GitHub
parent 408c613731
commit a338e7e242
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 1352 additions and 480 deletions

View file

@ -19,6 +19,7 @@ from homeassistant.const import (
ATTR_ENTITY_ID, ATTR_ENTITY_ID,
CONF_DEVICE_ID, CONF_DEVICE_ID,
CONF_DOMAIN, CONF_DOMAIN,
CONF_ENTITY_ID,
CONF_PLATFORM, CONF_PLATFORM,
) )
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
@ -340,6 +341,21 @@ def async_get_entity_registry_entry_or_raise(
return entry return entry
@callback
def async_validate_entity_schema(
hass: HomeAssistant, config: ConfigType, schema: vol.Schema
) -> ConfigType:
"""Validate schema and resolve entity registry entry id to entity_id."""
config = schema(config)
registry = er.async_get(hass)
config[CONF_ENTITY_ID] = er.async_resolve_entity_id(
registry, config[CONF_ENTITY_ID]
)
return config
def handle_device_errors( def handle_device_errors(
func: Callable[[HomeAssistant, ActiveConnection, dict[str, Any]], Awaitable[None]] func: Callable[[HomeAssistant, ActiveConnection, dict[str, Any]], Awaitable[None]]
) -> Callable[ ) -> Callable[

View file

@ -23,7 +23,7 @@ ENTITY_TRIGGERS = [
TRIGGER_SCHEMA = DEVICE_TRIGGER_BASE_SCHEMA.extend( TRIGGER_SCHEMA = DEVICE_TRIGGER_BASE_SCHEMA.extend(
{ {
vol.Required(CONF_ENTITY_ID): cv.entity_id, vol.Required(CONF_ENTITY_ID): cv.entity_id_or_uuid,
vol.Required(CONF_TYPE): vol.In([CONF_CHANGED_STATES]), vol.Required(CONF_TYPE): vol.In([CONF_CHANGED_STATES]),
vol.Optional(CONF_FOR): cv.positive_time_period_dict, vol.Optional(CONF_FOR): cv.positive_time_period_dict,
} }
@ -73,7 +73,7 @@ async def _async_get_automations(
{ {
**template, **template,
"device_id": device_id, "device_id": device_id,
"entity_id": entry.entity_id, "entity_id": entry.id,
"domain": domain, "domain": domain,
} }
for template in automation_templates for template in automation_templates

View file

@ -25,6 +25,8 @@ STATIC_VALIDATOR = {
DeviceAutomationType.TRIGGER: "TRIGGER_SCHEMA", DeviceAutomationType.TRIGGER: "TRIGGER_SCHEMA",
} }
TOGGLE_ENTITY_DOMAINS = {"fan", "humidifier", "light", "remote", "switch"}
async def async_validate_device_automation_config( async def async_validate_device_automation_config(
hass: HomeAssistant, hass: HomeAssistant,
@ -43,6 +45,16 @@ async def async_validate_device_automation_config(
ConfigType, getattr(platform, STATIC_VALIDATOR[automation_type])(config) ConfigType, getattr(platform, STATIC_VALIDATOR[automation_type])(config)
) )
# Bypass checks for toggle entity domains
if (
automation_type == DeviceAutomationType.ACTION
and validated_config[CONF_DOMAIN] in TOGGLE_ENTITY_DOMAINS
):
return cast(
ConfigType,
await getattr(platform, DYNAMIC_VALIDATOR[automation_type])(hass, config),
)
# Only call the dynamic validator if the referenced device exists and the relevant # Only call the dynamic validator if the referenced device exists and the relevant
# config entry is loaded # config entry is loaded
registry = dr.async_get(hass) registry = dr.async_get(hass)

View file

@ -78,14 +78,14 @@ DEVICE_ACTION_TYPES = [CONF_TOGGLE, CONF_TURN_OFF, CONF_TURN_ON]
ACTION_SCHEMA = cv.DEVICE_ACTION_BASE_SCHEMA.extend( ACTION_SCHEMA = cv.DEVICE_ACTION_BASE_SCHEMA.extend(
{ {
vol.Required(CONF_ENTITY_ID): cv.entity_id, vol.Required(CONF_ENTITY_ID): cv.entity_id_or_uuid,
vol.Required(CONF_TYPE): vol.In(DEVICE_ACTION_TYPES), vol.Required(CONF_TYPE): vol.In(DEVICE_ACTION_TYPES),
} }
) )
CONDITION_SCHEMA = cv.DEVICE_CONDITION_BASE_SCHEMA.extend( CONDITION_SCHEMA = cv.DEVICE_CONDITION_BASE_SCHEMA.extend(
{ {
vol.Required(CONF_ENTITY_ID): cv.entity_id, vol.Required(CONF_ENTITY_ID): cv.entity_id_or_uuid,
vol.Required(CONF_TYPE): vol.In([CONF_IS_OFF, CONF_IS_ON]), vol.Required(CONF_TYPE): vol.In([CONF_IS_OFF, CONF_IS_ON]),
vol.Optional(CONF_FOR): cv.positive_time_period_dict, vol.Optional(CONF_FOR): cv.positive_time_period_dict,
} }
@ -93,7 +93,7 @@ CONDITION_SCHEMA = cv.DEVICE_CONDITION_BASE_SCHEMA.extend(
_TOGGLE_TRIGGER_SCHEMA = DEVICE_TRIGGER_BASE_SCHEMA.extend( _TOGGLE_TRIGGER_SCHEMA = DEVICE_TRIGGER_BASE_SCHEMA.extend(
{ {
vol.Required(CONF_ENTITY_ID): cv.entity_id, vol.Required(CONF_ENTITY_ID): cv.entity_id_or_uuid,
vol.Required(CONF_TYPE): vol.In([CONF_TURNED_OFF, CONF_TURNED_ON]), vol.Required(CONF_TYPE): vol.In([CONF_TURNED_OFF, CONF_TURNED_ON]),
vol.Optional(CONF_FOR): cv.positive_time_period_dict, vol.Optional(CONF_FOR): cv.positive_time_period_dict,
} }
@ -196,7 +196,7 @@ async def _async_get_automations(
{ {
**template, **template,
"device_id": device_id, "device_id": device_id,
"entity_id": entry.entity_id, "entity_id": entry.id,
"domain": domain, "domain": domain,
} }
for template in automation_templates for template in automation_templates

View file

@ -3,7 +3,10 @@ from __future__ import annotations
import voluptuous as vol import voluptuous as vol
from homeassistant.components.device_automation import toggle_entity from homeassistant.components.device_automation import (
async_validate_entity_schema,
toggle_entity,
)
from homeassistant.const import ( from homeassistant.const import (
ATTR_ENTITY_ID, ATTR_ENTITY_ID,
ATTR_MODE, ATTR_MODE,
@ -41,7 +44,14 @@ SET_MODE_SCHEMA = cv.DEVICE_ACTION_BASE_SCHEMA.extend(
ONOFF_SCHEMA = toggle_entity.ACTION_SCHEMA.extend({vol.Required(CONF_DOMAIN): DOMAIN}) ONOFF_SCHEMA = toggle_entity.ACTION_SCHEMA.extend({vol.Required(CONF_DOMAIN): DOMAIN})
ACTION_SCHEMA = vol.Any(SET_HUMIDITY_SCHEMA, SET_MODE_SCHEMA, ONOFF_SCHEMA) _ACTION_SCHEMA = vol.Any(SET_HUMIDITY_SCHEMA, SET_MODE_SCHEMA, ONOFF_SCHEMA)
async def async_validate_action_config(
hass: HomeAssistant, config: ConfigType
) -> ConfigType:
"""Validate config."""
return async_validate_entity_schema(hass, config, _ACTION_SCHEMA)
async def async_get_actions( async def async_get_actions(

View file

@ -3,7 +3,11 @@ from __future__ import annotations
import voluptuous as vol import voluptuous as vol
from homeassistant.components.device_automation import toggle_entity from homeassistant.components.device_automation import (
async_get_entity_registry_entry_or_raise,
async_validate_entity_schema,
toggle_entity,
)
from homeassistant.const import ( from homeassistant.const import (
ATTR_ENTITY_ID, ATTR_ENTITY_ID,
CONF_DEVICE_ID, CONF_DEVICE_ID,
@ -37,9 +41,9 @@ TYPE_BRIGHTNESS_INCREASE = "brightness_increase"
TYPE_BRIGHTNESS_DECREASE = "brightness_decrease" TYPE_BRIGHTNESS_DECREASE = "brightness_decrease"
TYPE_FLASH = "flash" TYPE_FLASH = "flash"
ACTION_SCHEMA = cv.DEVICE_ACTION_BASE_SCHEMA.extend( _ACTION_SCHEMA = cv.DEVICE_ACTION_BASE_SCHEMA.extend(
{ {
vol.Required(ATTR_ENTITY_ID): cv.entity_id, vol.Required(ATTR_ENTITY_ID): cv.entity_id_or_uuid,
vol.Required(CONF_DOMAIN): DOMAIN, vol.Required(CONF_DOMAIN): DOMAIN,
vol.Required(CONF_TYPE): vol.In( vol.Required(CONF_TYPE): vol.In(
toggle_entity.DEVICE_ACTION_TYPES toggle_entity.DEVICE_ACTION_TYPES
@ -51,6 +55,13 @@ ACTION_SCHEMA = cv.DEVICE_ACTION_BASE_SCHEMA.extend(
) )
async def async_validate_action_config(
hass: HomeAssistant, config: ConfigType
) -> ConfigType:
"""Validate config."""
return async_validate_entity_schema(hass, config, _ACTION_SCHEMA)
async def async_call_action_from_config( async def async_call_action_from_config(
hass: HomeAssistant, hass: HomeAssistant,
config: ConfigType, config: ConfigType,
@ -126,13 +137,15 @@ async def async_get_action_capabilities(
if config[CONF_TYPE] != toggle_entity.CONF_TURN_ON: if config[CONF_TYPE] != toggle_entity.CONF_TURN_ON:
return {} return {}
entry = async_get_entity_registry_entry_or_raise(hass, config[CONF_ENTITY_ID])
try: try:
supported_color_modes = get_supported_color_modes(hass, config[ATTR_ENTITY_ID]) supported_color_modes = get_supported_color_modes(hass, entry.entity_id)
except HomeAssistantError: except HomeAssistantError:
supported_color_modes = None supported_color_modes = None
try: try:
supported_features = get_supported_features(hass, config[ATTR_ENTITY_ID]) supported_features = get_supported_features(hass, entry.entity_id)
except HomeAssistantError: except HomeAssistantError:
supported_features = 0 supported_features = 0

View file

@ -3,7 +3,10 @@ from __future__ import annotations
import voluptuous as vol import voluptuous as vol
from homeassistant.components.device_automation import toggle_entity from homeassistant.components.device_automation import (
async_validate_entity_schema,
toggle_entity,
)
from homeassistant.const import CONF_DOMAIN from homeassistant.const import CONF_DOMAIN
from homeassistant.core import Context, HomeAssistant from homeassistant.core import Context, HomeAssistant
from homeassistant.helpers.typing import ConfigType, TemplateVarsType from homeassistant.helpers.typing import ConfigType, TemplateVarsType
@ -12,7 +15,14 @@ from . import DOMAIN
# mypy: disallow-any-generics # mypy: disallow-any-generics
ACTION_SCHEMA = toggle_entity.ACTION_SCHEMA.extend({vol.Required(CONF_DOMAIN): DOMAIN}) _ACTION_SCHEMA = toggle_entity.ACTION_SCHEMA.extend({vol.Required(CONF_DOMAIN): DOMAIN})
async def async_validate_action_config(
hass: HomeAssistant, config: ConfigType
) -> ConfigType:
"""Validate config."""
return async_validate_entity_schema(hass, config, _ACTION_SCHEMA)
async def async_call_action_from_config( async def async_call_action_from_config(

View file

@ -3,7 +3,10 @@ from __future__ import annotations
import voluptuous as vol import voluptuous as vol
from homeassistant.components.device_automation import toggle_entity from homeassistant.components.device_automation import (
async_validate_entity_schema,
toggle_entity,
)
from homeassistant.const import CONF_DOMAIN from homeassistant.const import CONF_DOMAIN
from homeassistant.core import Context, HomeAssistant from homeassistant.core import Context, HomeAssistant
from homeassistant.helpers.typing import ConfigType, TemplateVarsType from homeassistant.helpers.typing import ConfigType, TemplateVarsType
@ -12,7 +15,14 @@ from . import DOMAIN
# mypy: disallow-any-generics # mypy: disallow-any-generics
ACTION_SCHEMA = toggle_entity.ACTION_SCHEMA.extend({vol.Required(CONF_DOMAIN): DOMAIN}) _ACTION_SCHEMA = toggle_entity.ACTION_SCHEMA.extend({vol.Required(CONF_DOMAIN): DOMAIN})
async def async_validate_action_config(
hass: HomeAssistant, config: ConfigType
) -> ConfigType:
"""Validate config."""
return async_validate_entity_schema(hass, config, _ACTION_SCHEMA)
async def async_call_action_from_config( async def async_call_action_from_config(

View file

@ -114,7 +114,7 @@ async def test_websocket_get_actions(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_registry.async_get_or_create( entity_entry = entity_registry.async_get_or_create(
"fake_integration", "test", "5678", device_id=device_entry.id "fake_integration", "test", "5678", device_id=device_entry.id
) )
expected_actions = [ expected_actions = [
@ -122,21 +122,21 @@ async def test_websocket_get_actions(
"domain": "fake_integration", "domain": "fake_integration",
"type": "turn_off", "type": "turn_off",
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": "fake_integration.test_5678", "entity_id": entity_entry.id,
"metadata": {"secondary": False}, "metadata": {"secondary": False},
}, },
{ {
"domain": "fake_integration", "domain": "fake_integration",
"type": "turn_on", "type": "turn_on",
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": "fake_integration.test_5678", "entity_id": entity_entry.id,
"metadata": {"secondary": False}, "metadata": {"secondary": False},
}, },
{ {
"domain": "fake_integration", "domain": "fake_integration",
"type": "toggle", "type": "toggle",
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": "fake_integration.test_5678", "entity_id": entity_entry.id,
"metadata": {"secondary": False}, "metadata": {"secondary": False},
}, },
] ]
@ -169,7 +169,7 @@ async def test_websocket_get_conditions(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_registry.async_get_or_create( entity_entry = entity_registry.async_get_or_create(
"fake_integration", "test", "5678", device_id=device_entry.id "fake_integration", "test", "5678", device_id=device_entry.id
) )
expected_conditions = [ expected_conditions = [
@ -178,7 +178,7 @@ async def test_websocket_get_conditions(
"domain": "fake_integration", "domain": "fake_integration",
"type": "is_off", "type": "is_off",
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": "fake_integration.test_5678", "entity_id": entity_entry.id,
"metadata": {"secondary": False}, "metadata": {"secondary": False},
}, },
{ {
@ -186,7 +186,7 @@ async def test_websocket_get_conditions(
"domain": "fake_integration", "domain": "fake_integration",
"type": "is_on", "type": "is_on",
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": "fake_integration.test_5678", "entity_id": entity_entry.id,
"metadata": {"secondary": False}, "metadata": {"secondary": False},
}, },
] ]
@ -223,7 +223,7 @@ async def test_websocket_get_triggers(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_registry.async_get_or_create( entity_entry = entity_registry.async_get_or_create(
"fake_integration", "test", "5678", device_id=device_entry.id "fake_integration", "test", "5678", device_id=device_entry.id
) )
expected_triggers = [ expected_triggers = [
@ -232,7 +232,7 @@ async def test_websocket_get_triggers(
"domain": "fake_integration", "domain": "fake_integration",
"type": "changed_states", "type": "changed_states",
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": "fake_integration.test_5678", "entity_id": entity_entry.id,
"metadata": {"secondary": False}, "metadata": {"secondary": False},
}, },
{ {
@ -240,7 +240,7 @@ async def test_websocket_get_triggers(
"domain": "fake_integration", "domain": "fake_integration",
"type": "turned_off", "type": "turned_off",
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": "fake_integration.test_5678", "entity_id": entity_entry.id,
"metadata": {"secondary": False}, "metadata": {"secondary": False},
}, },
{ {
@ -248,7 +248,7 @@ async def test_websocket_get_triggers(
"domain": "fake_integration", "domain": "fake_integration",
"type": "turned_on", "type": "turned_on",
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": "fake_integration.test_5678", "entity_id": entity_entry.id,
"metadata": {"secondary": False}, "metadata": {"secondary": False},
}, },
] ]

View file

@ -35,7 +35,7 @@ async def test_get_actions(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_registry.async_get_or_create( entity_entry = entity_registry.async_get_or_create(
DOMAIN, "test", "5678", device_id=device_entry.id DOMAIN, "test", "5678", device_id=device_entry.id
) )
expected_actions = [] expected_actions = []
@ -44,7 +44,7 @@ async def test_get_actions(
"domain": DOMAIN, "domain": DOMAIN,
"type": action, "type": action,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": entity_entry.id,
"metadata": {"secondary": False}, "metadata": {"secondary": False},
} }
for action in ["turn_on", "turn_off", "toggle"] for action in ["turn_on", "turn_off", "toggle"]
@ -78,7 +78,7 @@ async def test_get_actions_hidden_auxiliary(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_registry.async_get_or_create( entity_entry = entity_registry.async_get_or_create(
DOMAIN, DOMAIN,
"test", "test",
"5678", "5678",
@ -92,7 +92,7 @@ async def test_get_actions_hidden_auxiliary(
"domain": DOMAIN, "domain": DOMAIN,
"type": action, "type": action,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": entity_entry.id,
"metadata": {"secondary": True}, "metadata": {"secondary": True},
} }
for action in ["turn_on", "turn_off", "toggle"] for action in ["turn_on", "turn_off", "toggle"]
@ -103,8 +103,10 @@ async def test_get_actions_hidden_auxiliary(
assert actions == unordered(expected_actions) assert actions == unordered(expected_actions)
async def test_action(hass: HomeAssistant) -> None: async def test_action(hass: HomeAssistant, entity_registry: er.EntityRegistry) -> None:
"""Test for turn_on and turn_off actions.""" """Test for turn_on and turn_off actions."""
entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
assert await async_setup_component( assert await async_setup_component(
hass, hass,
automation.DOMAIN, automation.DOMAIN,
@ -118,7 +120,7 @@ async def test_action(hass: HomeAssistant) -> None:
"action": { "action": {
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "abcdefgh", "device_id": "abcdefgh",
"entity_id": "fan.entity", "entity_id": entry.id,
"type": "turn_off", "type": "turn_off",
}, },
}, },
@ -130,7 +132,7 @@ async def test_action(hass: HomeAssistant) -> None:
"action": { "action": {
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "abcdefgh", "device_id": "abcdefgh",
"entity_id": "fan.entity", "entity_id": entry.id,
"type": "turn_on", "type": "turn_on",
}, },
}, },
@ -142,7 +144,7 @@ async def test_action(hass: HomeAssistant) -> None:
"action": { "action": {
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "abcdefgh", "device_id": "abcdefgh",
"entity_id": "fan.entity", "entity_id": entry.id,
"type": "toggle", "type": "toggle",
}, },
}, },
@ -171,3 +173,37 @@ async def test_action(hass: HomeAssistant) -> None:
assert len(turn_off_calls) == 1 assert len(turn_off_calls) == 1
assert len(turn_on_calls) == 1 assert len(turn_on_calls) == 1
assert len(toggle_calls) == 1 assert len(toggle_calls) == 1
async def test_action_legacy(
hass: HomeAssistant, entity_registry: er.EntityRegistry
) -> None:
"""Test for turn_on and turn_off actions."""
entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: [
{
"trigger": {
"platform": "event",
"event_type": "test_event_turn_off",
},
"action": {
"domain": DOMAIN,
"device_id": "abcdefgh",
"entity_id": entry.entity_id,
"type": "turn_off",
},
},
]
},
)
turn_off_calls = async_mock_service(hass, "fan", "turn_off")
hass.bus.async_fire("test_event_turn_off")
await hass.async_block_till_done()
assert len(turn_off_calls) == 1

View file

@ -46,7 +46,7 @@ async def test_get_triggers(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_registry.async_get_or_create( entity_entry = entity_registry.async_get_or_create(
DOMAIN, "test", "5678", device_id=device_entry.id DOMAIN, "test", "5678", device_id=device_entry.id
) )
expected_triggers = [ expected_triggers = [
@ -55,7 +55,7 @@ async def test_get_triggers(
"domain": DOMAIN, "domain": DOMAIN,
"type": trigger, "type": trigger,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": entity_entry.id,
"metadata": {"secondary": False}, "metadata": {"secondary": False},
} }
for trigger in ["turned_off", "turned_on", "changed_states"] for trigger in ["turned_off", "turned_on", "changed_states"]
@ -89,7 +89,7 @@ async def test_get_triggers_hidden_auxiliary(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_registry.async_get_or_create( entity_entry = entity_registry.async_get_or_create(
DOMAIN, DOMAIN,
"test", "test",
"5678", "5678",
@ -103,7 +103,7 @@ async def test_get_triggers_hidden_auxiliary(
"domain": DOMAIN, "domain": DOMAIN,
"type": trigger, "type": trigger,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": entity_entry.id,
"metadata": {"secondary": True}, "metadata": {"secondary": True},
} }
for trigger in ["turned_off", "turned_on", "changed_states"] for trigger in ["turned_off", "turned_on", "changed_states"]
@ -144,9 +144,44 @@ async def test_get_trigger_capabilities(
assert capabilities == expected_capabilities assert capabilities == expected_capabilities
async def test_if_fires_on_state_change(hass: HomeAssistant, calls) -> None: async def test_get_trigger_capabilities_legacy(
hass: HomeAssistant,
device_registry: dr.DeviceRegistry,
entity_registry: er.EntityRegistry,
) -> None:
"""Test we get the expected capabilities from a switch trigger."""
config_entry = MockConfigEntry(domain="test", data={})
config_entry.add_to_hass(hass)
device_entry = device_registry.async_get_or_create(
config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
)
entity_registry.async_get_or_create(
DOMAIN, "test", "5678", device_id=device_entry.id
)
expected_capabilities = {
"extra_fields": [
{"name": "for", "optional": True, "type": "positive_time_period_dict"}
]
}
triggers = await async_get_device_automations(
hass, DeviceAutomationType.TRIGGER, device_entry.id
)
for trigger in triggers:
trigger["entity_id"] = entity_registry.async_get(trigger["entity_id"]).entity_id
capabilities = await async_get_device_automation_capabilities(
hass, DeviceAutomationType.TRIGGER, trigger
)
assert capabilities == expected_capabilities
async def test_if_fires_on_state_change(
hass: HomeAssistant, entity_registry: er.EntityRegistry, calls
) -> None:
"""Test for turn_on and turn_off triggers firing.""" """Test for turn_on and turn_off triggers firing."""
hass.states.async_set("fan.entity", STATE_OFF) entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
hass.states.async_set(entry.entity_id, STATE_OFF)
assert await async_setup_component( assert await async_setup_component(
hass, hass,
@ -158,7 +193,7 @@ async def test_if_fires_on_state_change(hass: HomeAssistant, calls) -> None:
"platform": "device", "platform": "device",
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": "fan.entity", "entity_id": entry.id,
"type": "turned_on", "type": "turned_on",
}, },
"action": { "action": {
@ -180,7 +215,7 @@ async def test_if_fires_on_state_change(hass: HomeAssistant, calls) -> None:
"platform": "device", "platform": "device",
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": "fan.entity", "entity_id": entry.id,
"type": "turned_off", "type": "turned_off",
}, },
"action": { "action": {
@ -202,7 +237,7 @@ async def test_if_fires_on_state_change(hass: HomeAssistant, calls) -> None:
"platform": "device", "platform": "device",
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": "fan.entity", "entity_id": entry.id,
"type": "changed_states", "type": "changed_states",
}, },
"action": { "action": {
@ -224,28 +259,31 @@ async def test_if_fires_on_state_change(hass: HomeAssistant, calls) -> None:
) )
# Fake that the entity is turning on. # Fake that the entity is turning on.
hass.states.async_set("fan.entity", STATE_ON) hass.states.async_set(entry.entity_id, STATE_ON)
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(calls) == 2 assert len(calls) == 2
assert {calls[0].data["some"], calls[1].data["some"]} == { assert {calls[0].data["some"], calls[1].data["some"]} == {
"turn_on - device - fan.entity - off - on - None", f"turn_on - device - {entry.entity_id} - off - on - None",
"turn_on_or_off - device - fan.entity - off - on - None", f"turn_on_or_off - device - {entry.entity_id} - off - on - None",
} }
# Fake that the entity is turning off. # Fake that the entity is turning off.
hass.states.async_set("fan.entity", STATE_OFF) hass.states.async_set(entry.entity_id, STATE_OFF)
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(calls) == 4 assert len(calls) == 4
assert {calls[2].data["some"], calls[3].data["some"]} == { assert {calls[2].data["some"], calls[3].data["some"]} == {
"turn_off - device - fan.entity - on - off - None", f"turn_off - device - {entry.entity_id} - on - off - None",
"turn_on_or_off - device - fan.entity - on - off - None", f"turn_on_or_off - device - {entry.entity_id} - on - off - None",
} }
async def test_if_fires_on_state_change_with_for(hass: HomeAssistant, calls) -> None: async def test_if_fires_on_state_change_legacy(
"""Test for triggers firing with delay.""" hass: HomeAssistant, entity_registry: er.EntityRegistry, calls
entity_id = "fan.entity" ) -> None:
hass.states.async_set(entity_id, STATE_ON) """Test for turn_on and turn_off triggers firing."""
entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
hass.states.async_set(entry.entity_id, STATE_OFF)
assert await async_setup_component( assert await async_setup_component(
hass, hass,
@ -257,7 +295,56 @@ async def test_if_fires_on_state_change_with_for(hass: HomeAssistant, calls) ->
"platform": "device", "platform": "device",
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": entity_id, "entity_id": entry.id,
"type": "turned_on",
},
"action": {
"service": "test.automation",
"data_template": {
"some": (
"turn_on "
"- {{ trigger.platform }} "
"- {{ trigger.entity_id }} "
"- {{ trigger.from_state.state }} "
"- {{ trigger.to_state.state }} "
"- {{ trigger.for }}"
)
},
},
},
]
},
)
# Fake that the entity is turning on.
hass.states.async_set(entry.entity_id, STATE_ON)
await hass.async_block_till_done()
assert len(calls) == 1
assert (
calls[0].data["some"]
== f"turn_on - device - {entry.entity_id} - off - on - None"
)
async def test_if_fires_on_state_change_with_for(
hass: HomeAssistant, entity_registry: er.EntityRegistry, calls
) -> None:
"""Test for triggers firing with delay."""
entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
hass.states.async_set(entry.entity_id, STATE_ON)
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: [
{
"trigger": {
"platform": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": entry.id,
"type": "turned_off", "type": "turned_off",
"for": {"seconds": 5}, "for": {"seconds": 5},
}, },
@ -281,10 +368,9 @@ async def test_if_fires_on_state_change_with_for(hass: HomeAssistant, calls) ->
}, },
) )
await hass.async_block_till_done() await hass.async_block_till_done()
assert hass.states.get(entity_id).state == STATE_ON
assert len(calls) == 0 assert len(calls) == 0
hass.states.async_set(entity_id, STATE_OFF) hass.states.async_set(entry.entity_id, STATE_OFF)
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(calls) == 0 assert len(calls) == 0
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=10)) async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=10))
@ -292,5 +378,6 @@ async def test_if_fires_on_state_change_with_for(hass: HomeAssistant, calls) ->
assert len(calls) == 1 assert len(calls) == 1
await hass.async_block_till_done() await hass.async_block_till_done()
assert ( assert (
calls[0].data["some"] == f"turn_off device - {entity_id} - on - off - 0:00:05" calls[0].data["some"]
== f"turn_off device - {entry.entity_id} - on - off - 0:00:05"
) )

View file

@ -53,7 +53,7 @@ async def test_get_actions(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_registry.async_get_or_create( entity_entry = entity_registry.async_get_or_create(
DOMAIN, DOMAIN,
"test", "test",
"5678", "5678",
@ -65,7 +65,8 @@ async def test_get_actions(
f"{DOMAIN}.test_5678", "attributes", {"supported_features": features_state} f"{DOMAIN}.test_5678", "attributes", {"supported_features": features_state}
) )
expected_actions = [] expected_actions = []
basic_action_types = ["turn_on", "turn_off", "toggle", "set_humidity"] basic_action_types = ["set_humidity"]
toggle_action_types = ["turn_on", "turn_off", "toggle"]
expected_actions += [ expected_actions += [
{ {
"domain": DOMAIN, "domain": DOMAIN,
@ -76,6 +77,16 @@ async def test_get_actions(
} }
for action in basic_action_types for action in basic_action_types
] ]
expected_actions += [
{
"domain": DOMAIN,
"type": action,
"device_id": device_entry.id,
"entity_id": entity_entry.id,
"metadata": {"secondary": False},
}
for action in toggle_action_types
]
expected_actions += [ expected_actions += [
{ {
"domain": DOMAIN, "domain": DOMAIN,
@ -115,7 +126,7 @@ async def test_get_actions_hidden_auxiliary(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_registry.async_get_or_create( entity_entry = entity_registry.async_get_or_create(
DOMAIN, DOMAIN,
"test", "test",
"5678", "5678",
@ -124,6 +135,8 @@ async def test_get_actions_hidden_auxiliary(
hidden_by=hidden_by, hidden_by=hidden_by,
supported_features=0, supported_features=0,
) )
basic_action_types = ["set_humidity"]
toggle_action_types = ["turn_on", "turn_off", "toggle"]
expected_actions = [] expected_actions = []
expected_actions += [ expected_actions += [
{ {
@ -133,7 +146,17 @@ async def test_get_actions_hidden_auxiliary(
"entity_id": f"{DOMAIN}.test_5678", "entity_id": f"{DOMAIN}.test_5678",
"metadata": {"secondary": True}, "metadata": {"secondary": True},
} }
for action in ["turn_on", "turn_off", "toggle", "set_humidity"] for action in basic_action_types
]
expected_actions += [
{
"domain": DOMAIN,
"type": action,
"device_id": device_entry.id,
"entity_id": entity_entry.id,
"metadata": {"secondary": True},
}
for action in toggle_action_types
] ]
actions = await async_get_device_automations( actions = await async_get_device_automations(
hass, DeviceAutomationType.ACTION, device_entry.id hass, DeviceAutomationType.ACTION, device_entry.id
@ -141,10 +164,12 @@ async def test_get_actions_hidden_auxiliary(
assert actions == unordered(expected_actions) assert actions == unordered(expected_actions)
async def test_action(hass: HomeAssistant) -> None: async def test_action(hass: HomeAssistant, entity_registry: er.EntityRegistry) -> None:
"""Test for actions.""" """Test for actions."""
entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
hass.states.async_set( hass.states.async_set(
"humidifier.entity", entry.entity_id,
STATE_ON, STATE_ON,
{const.ATTR_AVAILABLE_MODES: [const.MODE_HOME, const.MODE_AWAY]}, {const.ATTR_AVAILABLE_MODES: [const.MODE_HOME, const.MODE_AWAY]},
) )
@ -162,7 +187,7 @@ async def test_action(hass: HomeAssistant) -> None:
"action": { "action": {
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "abcdefgh", "device_id": "abcdefgh",
"entity_id": "humidifier.entity", "entity_id": entry.id,
"type": "turn_off", "type": "turn_off",
}, },
}, },
@ -174,7 +199,7 @@ async def test_action(hass: HomeAssistant) -> None:
"action": { "action": {
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "abcdefgh", "device_id": "abcdefgh",
"entity_id": "humidifier.entity", "entity_id": entry.id,
"type": "turn_on", "type": "turn_on",
}, },
}, },
@ -183,7 +208,7 @@ async def test_action(hass: HomeAssistant) -> None:
"action": { "action": {
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "abcdefgh", "device_id": "abcdefgh",
"entity_id": "humidifier.entity", "entity_id": entry.id,
"type": "toggle", "type": "toggle",
}, },
}, },
@ -195,7 +220,7 @@ async def test_action(hass: HomeAssistant) -> None:
"action": { "action": {
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "abcdefgh", "device_id": "abcdefgh",
"entity_id": "humidifier.entity", "entity_id": entry.entity_id,
"type": "set_humidity", "type": "set_humidity",
"humidity": 35, "humidity": 35,
}, },
@ -208,7 +233,7 @@ async def test_action(hass: HomeAssistant) -> None:
"action": { "action": {
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "abcdefgh", "device_id": "abcdefgh",
"entity_id": "humidifier.entity", "entity_id": entry.entity_id,
"type": "set_mode", "type": "set_mode",
"mode": const.MODE_AWAY, "mode": const.MODE_AWAY,
}, },
@ -269,6 +294,67 @@ async def test_action(hass: HomeAssistant) -> None:
assert len(turn_off_calls) == 1 assert len(turn_off_calls) == 1
assert len(toggle_calls) == 1 assert len(toggle_calls) == 1
assert set_humidity_calls[0].domain == DOMAIN
assert set_humidity_calls[0].service == "set_humidity"
assert set_humidity_calls[0].data == {"entity_id": entry.entity_id, "humidity": 35}
assert set_mode_calls[0].domain == DOMAIN
assert set_mode_calls[0].service == "set_mode"
assert set_mode_calls[0].data == {"entity_id": entry.entity_id, "mode": "away"}
assert turn_on_calls[0].domain == DOMAIN
assert turn_on_calls[0].service == "turn_on"
assert turn_on_calls[0].data == {"entity_id": entry.entity_id}
assert turn_off_calls[0].domain == DOMAIN
assert turn_off_calls[0].service == "turn_off"
assert turn_off_calls[0].data == {"entity_id": entry.entity_id}
assert toggle_calls[0].domain == DOMAIN
assert toggle_calls[0].service == "toggle"
assert toggle_calls[0].data == {"entity_id": entry.entity_id}
async def test_action_legacy(
hass: HomeAssistant, entity_registry: er.EntityRegistry
) -> None:
"""Test for actions."""
entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
hass.states.async_set(
entry.entity_id,
STATE_ON,
{const.ATTR_AVAILABLE_MODES: [const.MODE_HOME, const.MODE_AWAY]},
)
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: [
{
"trigger": {
"platform": "event",
"event_type": "test_event_set_mode",
},
"action": {
"domain": DOMAIN,
"device_id": "abcdefgh",
"entity_id": entry.entity_id,
"type": "set_mode",
"mode": const.MODE_AWAY,
},
},
]
},
)
set_mode_calls = async_mock_service(hass, "humidifier", "set_mode")
hass.bus.async_fire("test_event_set_mode")
await hass.async_block_till_done()
assert len(set_mode_calls) == 1
assert set_mode_calls[0].domain == DOMAIN
assert set_mode_calls[0].service == "set_mode"
assert set_mode_calls[0].data == {"entity_id": entry.entity_id, "mode": "away"}
@pytest.mark.parametrize( @pytest.mark.parametrize(
( (
@ -380,7 +466,7 @@ async def test_capabilities(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_registry.async_get_or_create( entity_entry = entity_registry.async_get_or_create(
DOMAIN, DOMAIN,
"test", "test",
"5678", "5678",
@ -399,7 +485,7 @@ async def test_capabilities(
{ {
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "abcdefgh", "device_id": "abcdefgh",
"entity_id": f"{DOMAIN}.test_5678", "entity_id": entity_entry.entity_id,
"type": action, "type": action,
}, },
) )
@ -418,7 +504,6 @@ async def test_capabilities(
("action", "capability_name", "extra"), ("action", "capability_name", "extra"),
[ [
("set_humidity", "humidity", {"type": "integer"}), ("set_humidity", "humidity", {"type": "integer"}),
("set_mode", "mode", {"type": "select", "options": []}),
], ],
) )
async def test_capabilities_missing_entity( async def test_capabilities_missing_entity(

View file

@ -59,7 +59,7 @@ async def test_get_conditions(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_registry.async_get_or_create( entity_entry = entity_registry.async_get_or_create(
DOMAIN, DOMAIN,
"test", "test",
"5678", "5678",
@ -78,7 +78,7 @@ async def test_get_conditions(
"domain": DOMAIN, "domain": DOMAIN,
"type": condition, "type": condition,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": entity_entry.id,
"metadata": {"secondary": False}, "metadata": {"secondary": False},
} }
for condition in basic_condition_types for condition in basic_condition_types
@ -89,7 +89,7 @@ async def test_get_conditions(
"domain": DOMAIN, "domain": DOMAIN,
"type": condition, "type": condition,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": entity_entry.entity_id,
"metadata": {"secondary": False}, "metadata": {"secondary": False},
} }
for condition in expected_condition_types for condition in expected_condition_types
@ -123,7 +123,7 @@ async def test_get_conditions_hidden_auxiliary(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_registry.async_get_or_create( entity_entry = entity_registry.async_get_or_create(
DOMAIN, DOMAIN,
"test", "test",
"5678", "5678",
@ -137,7 +137,7 @@ async def test_get_conditions_hidden_auxiliary(
"domain": DOMAIN, "domain": DOMAIN,
"type": condition, "type": condition,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": entity_entry.id,
"metadata": {"secondary": True}, "metadata": {"secondary": True},
} }
for condition in ["is_off", "is_on"] for condition in ["is_off", "is_on"]
@ -148,9 +148,13 @@ async def test_get_conditions_hidden_auxiliary(
assert conditions == unordered(expected_conditions) assert conditions == unordered(expected_conditions)
async def test_if_state(hass: HomeAssistant, calls) -> None: async def test_if_state(
hass: HomeAssistant, entity_registry: er.EntityRegistry, calls
) -> None:
"""Test for turn_on and turn_off conditions.""" """Test for turn_on and turn_off conditions."""
hass.states.async_set("humidifier.entity", STATE_ON, {ATTR_MODE: const.MODE_AWAY}) entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
hass.states.async_set(entry.entity_id, STATE_ON, {ATTR_MODE: const.MODE_AWAY})
assert await async_setup_component( assert await async_setup_component(
hass, hass,
@ -164,7 +168,7 @@ async def test_if_state(hass: HomeAssistant, calls) -> None:
"condition": "device", "condition": "device",
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": "humidifier.entity", "entity_id": entry.id,
"type": "is_on", "type": "is_on",
} }
], ],
@ -183,7 +187,7 @@ async def test_if_state(hass: HomeAssistant, calls) -> None:
"condition": "device", "condition": "device",
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": "humidifier.entity", "entity_id": entry.id,
"type": "is_off", "type": "is_off",
} }
], ],
@ -202,7 +206,7 @@ async def test_if_state(hass: HomeAssistant, calls) -> None:
"condition": "device", "condition": "device",
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": "humidifier.entity", "entity_id": entry.entity_id,
"type": "is_mode", "type": "is_mode",
"mode": "away", "mode": "away",
} }
@ -218,7 +222,6 @@ async def test_if_state(hass: HomeAssistant, calls) -> None:
}, },
) )
await hass.async_block_till_done() await hass.async_block_till_done()
assert hass.states.get("humidifier.entity").state == STATE_ON
assert len(calls) == 0 assert len(calls) == 0
hass.bus.async_fire("test_event1") hass.bus.async_fire("test_event1")
@ -227,14 +230,14 @@ async def test_if_state(hass: HomeAssistant, calls) -> None:
assert len(calls) == 1 assert len(calls) == 1
assert calls[0].data["some"] == "is_on event - test_event1" assert calls[0].data["some"] == "is_on event - test_event1"
hass.states.async_set("humidifier.entity", STATE_OFF) hass.states.async_set(entry.entity_id, STATE_OFF)
hass.bus.async_fire("test_event1") hass.bus.async_fire("test_event1")
hass.bus.async_fire("test_event2") hass.bus.async_fire("test_event2")
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(calls) == 2 assert len(calls) == 2
assert calls[1].data["some"] == "is_off event - test_event2" assert calls[1].data["some"] == "is_off event - test_event2"
hass.states.async_set("humidifier.entity", STATE_ON, {ATTR_MODE: const.MODE_AWAY}) hass.states.async_set(entry.entity_id, STATE_ON, {ATTR_MODE: const.MODE_AWAY})
hass.bus.async_fire("test_event3") hass.bus.async_fire("test_event3")
await hass.async_block_till_done() await hass.async_block_till_done()
@ -242,7 +245,7 @@ async def test_if_state(hass: HomeAssistant, calls) -> None:
assert len(calls) == 3 assert len(calls) == 3
assert calls[2].data["some"] == "is_mode - event - test_event3" assert calls[2].data["some"] == "is_mode - event - test_event3"
hass.states.async_set("humidifier.entity", STATE_ON, {ATTR_MODE: const.MODE_HOME}) hass.states.async_set(entry.entity_id, STATE_ON, {ATTR_MODE: const.MODE_HOME})
# Should not fire # Should not fire
hass.bus.async_fire("test_event3") hass.bus.async_fire("test_event3")
@ -386,7 +389,7 @@ async def test_capabilities(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_registry.async_get_or_create( entity_entry = entity_registry.async_get_or_create(
DOMAIN, DOMAIN,
"test", "test",
"5678", "5678",
@ -395,7 +398,7 @@ async def test_capabilities(
) )
if set_state: if set_state:
hass.states.async_set( hass.states.async_set(
f"{DOMAIN}.test_5678", entity_entry.entity_id,
STATE_ON, STATE_ON,
capabilities_state, capabilities_state,
) )
@ -405,7 +408,7 @@ async def test_capabilities(
{ {
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "abcdefgh", "device_id": "abcdefgh",
"entity_id": f"{DOMAIN}.test_5678", "entity_id": entity_entry.entity_id,
"type": condition, "type": condition,
}, },
) )

View file

@ -89,7 +89,7 @@ async def test_get_triggers(
"domain": DOMAIN, "domain": DOMAIN,
"type": trigger, "type": trigger,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": entity_entry.entity_id, "entity_id": entity_entry.id,
"metadata": {"secondary": False}, "metadata": {"secondary": False},
} }
for trigger in toggle_trigger_types for trigger in toggle_trigger_types
@ -150,7 +150,7 @@ async def test_get_triggers_hidden_auxiliary(
"domain": DOMAIN, "domain": DOMAIN,
"type": trigger, "type": trigger,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": entity_entry.entity_id, "entity_id": entity_entry.id,
"metadata": {"secondary": True}, "metadata": {"secondary": True},
} }
for trigger in toggle_trigger_types for trigger in toggle_trigger_types
@ -231,7 +231,7 @@ async def test_if_fires_on_state_change(
"platform": "device", "platform": "device",
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": entry.entity_id, "entity_id": entry.id,
"type": "turned_on", "type": "turned_on",
}, },
"action": { "action": {
@ -255,7 +255,7 @@ async def test_if_fires_on_state_change(
"platform": "device", "platform": "device",
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": entry.entity_id, "entity_id": entry.id,
"type": "turned_off", "type": "turned_off",
}, },
"action": { "action": {
@ -279,7 +279,7 @@ async def test_if_fires_on_state_change(
"platform": "device", "platform": "device",
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": entry.entity_id, "entity_id": entry.id,
"type": "changed_states", "type": "changed_states",
}, },
"action": { "action": {

View file

@ -12,9 +12,12 @@ from homeassistant.components.light import (
ColorMode, ColorMode,
LightEntityFeature, LightEntityFeature,
) )
from homeassistant.const import CONF_PLATFORM, STATE_OFF, STATE_ON, EntityCategory from homeassistant.const import EntityCategory
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
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.helpers.entity_registry import RegistryEntryHider from homeassistant.helpers.entity_registry import RegistryEntryHider
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
@ -49,7 +52,7 @@ async def test_get_actions(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_registry.async_get_or_create( entity_entry = entity_registry.async_get_or_create(
DOMAIN, DOMAIN,
"test", "test",
"5678", "5678",
@ -63,13 +66,24 @@ async def test_get_actions(
"domain": DOMAIN, "domain": DOMAIN,
"type": action, "type": action,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": entity_entry.id,
"metadata": {"secondary": False}, "metadata": {"secondary": False},
} }
for action in [ for action in [
"turn_off", "turn_off",
"turn_on", "turn_on",
"toggle", "toggle",
]
]
expected_actions += [
{
"domain": DOMAIN,
"type": action,
"device_id": device_entry.id,
"entity_id": entity_entry.entity_id,
"metadata": {"secondary": False},
}
for action in [
"brightness_decrease", "brightness_decrease",
"brightness_increase", "brightness_increase",
"flash", "flash",
@ -104,7 +118,7 @@ async def test_get_actions_hidden_auxiliary(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_registry.async_get_or_create( entity_entry = entity_registry.async_get_or_create(
DOMAIN, DOMAIN,
"test", "test",
"5678", "5678",
@ -120,7 +134,7 @@ async def test_get_actions_hidden_auxiliary(
"domain": DOMAIN, "domain": DOMAIN,
"type": action, "type": action,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": entity_entry.id,
"metadata": {"secondary": True}, "metadata": {"secondary": True},
} }
for action in ["turn_on", "turn_off", "toggle"] for action in ["turn_on", "turn_off", "toggle"]
@ -168,7 +182,7 @@ async def test_get_action_capabilities(
capabilities = await async_get_device_automation_capabilities( capabilities = await async_get_device_automation_capabilities(
hass, DeviceAutomationType.ACTION, action hass, DeviceAutomationType.ACTION, action
) )
assert capabilities == {"extra_fields": []} assert capabilities == {"extra_fields": []} or capabilities == {}
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -319,16 +333,13 @@ async def test_get_action_capabilities_features(
async def test_action( async def test_action(
hass: HomeAssistant, calls, enable_custom_integrations: None hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None: ) -> None:
"""Test for turn_on and turn_off actions.""" """Test for turn_on and turn_off actions."""
platform = getattr(hass.components, f"test.{DOMAIN}") entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
platform.init()
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
await hass.async_block_till_done()
ent1 = platform.ENTITIES[0]
assert await async_setup_component( assert await async_setup_component(
hass, hass,
@ -340,7 +351,7 @@ async def test_action(
"action": { "action": {
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.id,
"type": "turn_off", "type": "turn_off",
}, },
}, },
@ -349,7 +360,7 @@ async def test_action(
"action": { "action": {
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.id,
"type": "turn_on", "type": "turn_on",
}, },
}, },
@ -358,7 +369,7 @@ async def test_action(
"action": { "action": {
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.id,
"type": "toggle", "type": "toggle",
}, },
}, },
@ -367,7 +378,7 @@ async def test_action(
"action": { "action": {
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.entity_id,
"type": "flash", "type": "flash",
}, },
}, },
@ -376,7 +387,7 @@ async def test_action(
"action": { "action": {
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.entity_id,
"type": "flash", "type": "flash",
"flash": "long", "flash": "long",
}, },
@ -389,7 +400,7 @@ async def test_action(
"action": { "action": {
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.entity_id,
"type": "brightness_increase", "type": "brightness_increase",
}, },
}, },
@ -401,7 +412,7 @@ async def test_action(
"action": { "action": {
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.entity_id,
"type": "brightness_decrease", "type": "brightness_decrease",
}, },
}, },
@ -410,7 +421,7 @@ async def test_action(
"action": { "action": {
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.entity_id,
"type": "turn_on", "type": "turn_on",
"brightness_pct": 75, "brightness_pct": 75,
}, },
@ -419,89 +430,59 @@ async def test_action(
}, },
) )
await hass.async_block_till_done() await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_ON
assert len(calls) == 0
hass.bus.async_fire("test_off")
await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_OFF
hass.bus.async_fire("test_off")
await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_OFF
hass.bus.async_fire("test_on")
await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_ON
hass.bus.async_fire("test_on")
await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_ON
hass.bus.async_fire("test_toggle")
await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_OFF
hass.bus.async_fire("test_toggle")
await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_ON
hass.bus.async_fire("test_toggle")
await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_OFF
hass.bus.async_fire("test_flash_short")
await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_ON
hass.bus.async_fire("test_toggle")
await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_OFF
hass.bus.async_fire("test_flash_long")
await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_ON
turn_on_calls = async_mock_service(hass, DOMAIN, "turn_on") turn_on_calls = async_mock_service(hass, DOMAIN, "turn_on")
turn_off_calls = async_mock_service(hass, DOMAIN, "turn_off")
toggle_calls = async_mock_service(hass, DOMAIN, "toggle")
hass.bus.async_fire("test_toggle")
await hass.async_block_till_done()
assert len(toggle_calls) == 1
assert toggle_calls[-1].data == {"entity_id": entry.entity_id}
hass.bus.async_fire("test_off")
await hass.async_block_till_done()
assert len(turn_off_calls) == 1
assert turn_off_calls[-1].data == {"entity_id": entry.entity_id}
hass.bus.async_fire("test_brightness_increase") hass.bus.async_fire("test_brightness_increase")
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(turn_on_calls) == 1 assert len(turn_on_calls) == 1
assert turn_on_calls[0].data["entity_id"] == ent1.entity_id assert turn_on_calls[-1].data == {
assert turn_on_calls[0].data["brightness_step_pct"] == 10 "entity_id": entry.entity_id,
"brightness_step_pct": 10,
}
hass.bus.async_fire("test_brightness_decrease") hass.bus.async_fire("test_brightness_decrease")
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(turn_on_calls) == 2 assert len(turn_on_calls) == 2
assert turn_on_calls[1].data["entity_id"] == ent1.entity_id assert turn_on_calls[-1].data == {
assert turn_on_calls[1].data["brightness_step_pct"] == -10 "entity_id": entry.entity_id,
"brightness_step_pct": -10,
}
hass.bus.async_fire("test_brightness") hass.bus.async_fire("test_brightness")
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(turn_on_calls) == 3 assert len(turn_on_calls) == 3
assert turn_on_calls[2].data["entity_id"] == ent1.entity_id assert turn_on_calls[-1].data == {
assert turn_on_calls[2].data["brightness_pct"] == 75 "entity_id": entry.entity_id,
"brightness_pct": 75,
}
hass.bus.async_fire("test_on") hass.bus.async_fire("test_on")
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(turn_on_calls) == 4 assert len(turn_on_calls) == 4
assert turn_on_calls[3].data["entity_id"] == ent1.entity_id assert turn_on_calls[-1].data == {"entity_id": entry.entity_id}
assert "brightness_pct" not in turn_on_calls[3].data
hass.bus.async_fire("test_flash_short") hass.bus.async_fire("test_flash_short")
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(turn_on_calls) == 5 assert len(turn_on_calls) == 5
assert turn_on_calls[4].data["entity_id"] == ent1.entity_id assert turn_on_calls[-1].data == {
assert turn_on_calls[4].data["flash"] == FLASH_SHORT "entity_id": entry.entity_id,
"flash": FLASH_SHORT,
}
hass.bus.async_fire("test_flash_long") hass.bus.async_fire("test_flash_long")
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(turn_on_calls) == 6 assert len(turn_on_calls) == 6
assert turn_on_calls[5].data["entity_id"] == ent1.entity_id assert turn_on_calls[-1].data == {"entity_id": entry.entity_id, "flash": FLASH_LONG}
assert turn_on_calls[5].data["flash"] == FLASH_LONG

View file

@ -46,7 +46,7 @@ async def test_get_conditions(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_registry.async_get_or_create( entity_entry = entity_registry.async_get_or_create(
DOMAIN, "test", "5678", device_id=device_entry.id DOMAIN, "test", "5678", device_id=device_entry.id
) )
expected_conditions = [ expected_conditions = [
@ -55,7 +55,7 @@ async def test_get_conditions(
"domain": DOMAIN, "domain": DOMAIN,
"type": condition, "type": condition,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": entity_entry.id,
"metadata": {"secondary": False}, "metadata": {"secondary": False},
} }
for condition in ["is_off", "is_on"] for condition in ["is_off", "is_on"]
@ -89,7 +89,7 @@ async def test_get_conditions_hidden_auxiliary(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_registry.async_get_or_create( entity_entry = entity_registry.async_get_or_create(
DOMAIN, DOMAIN,
"test", "test",
"5678", "5678",
@ -103,7 +103,7 @@ async def test_get_conditions_hidden_auxiliary(
"domain": DOMAIN, "domain": DOMAIN,
"type": condition, "type": condition,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": entity_entry.id,
"metadata": {"secondary": True}, "metadata": {"secondary": True},
} }
for condition in ["is_off", "is_on"] for condition in ["is_off", "is_on"]
@ -144,17 +144,49 @@ async def test_get_condition_capabilities(
assert capabilities == expected_capabilities assert capabilities == expected_capabilities
async def test_get_condition_capabilities_legacy(
hass: HomeAssistant,
device_registry: dr.DeviceRegistry,
entity_registry: er.EntityRegistry,
) -> None:
"""Test we get the expected capabilities from a light condition."""
config_entry = MockConfigEntry(domain="test", data={})
config_entry.add_to_hass(hass)
device_entry = device_registry.async_get_or_create(
config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
)
entity_registry.async_get_or_create(
DOMAIN, "test", "5678", device_id=device_entry.id
)
expected_capabilities = {
"extra_fields": [
{"name": "for", "optional": True, "type": "positive_time_period_dict"}
]
}
conditions = await async_get_device_automations(
hass, DeviceAutomationType.CONDITION, device_entry.id
)
for condition in conditions:
condition["entity_id"] = entity_registry.async_get(
condition["entity_id"]
).entity_id
capabilities = await async_get_device_automation_capabilities(
hass, DeviceAutomationType.CONDITION, condition
)
assert capabilities == expected_capabilities
async def test_if_state( async def test_if_state(
hass: HomeAssistant, calls, enable_custom_integrations: None hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None: ) -> None:
"""Test for turn_on and turn_off conditions.""" """Test for turn_on and turn_off conditions."""
platform = getattr(hass.components, f"test.{DOMAIN}") entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
platform.init() hass.states.async_set(entry.entity_id, STATE_ON)
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
await hass.async_block_till_done()
ent1, ent2, ent3 = platform.ENTITIES
assert await async_setup_component( assert await async_setup_component(
hass, hass,
@ -168,7 +200,7 @@ async def test_if_state(
"condition": "device", "condition": "device",
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.id,
"type": "is_on", "type": "is_on",
} }
], ],
@ -187,7 +219,7 @@ async def test_if_state(
"condition": "device", "condition": "device",
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.id,
"type": "is_off", "type": "is_off",
} }
], ],
@ -203,7 +235,6 @@ async def test_if_state(
}, },
) )
await hass.async_block_till_done() await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_ON
assert len(calls) == 0 assert len(calls) == 0
hass.bus.async_fire("test_event1") hass.bus.async_fire("test_event1")
@ -212,7 +243,7 @@ async def test_if_state(
assert len(calls) == 1 assert len(calls) == 1
assert calls[0].data["some"] == "is_on event - test_event1" assert calls[0].data["some"] == "is_on event - test_event1"
hass.states.async_set(ent1.entity_id, STATE_OFF) hass.states.async_set(entry.entity_id, STATE_OFF)
hass.bus.async_fire("test_event1") hass.bus.async_fire("test_event1")
hass.bus.async_fire("test_event2") hass.bus.async_fire("test_event2")
await hass.async_block_till_done() await hass.async_block_till_done()
@ -220,10 +251,65 @@ async def test_if_state(
assert calls[1].data["some"] == "is_off event - test_event2" assert calls[1].data["some"] == "is_off event - test_event2"
async def test_if_state_legacy(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None:
"""Test for turn_on and turn_off conditions."""
entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
hass.states.async_set(entry.entity_id, STATE_ON)
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: [
{
"trigger": {"platform": "event", "event_type": "test_event1"},
"condition": [
{
"condition": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": entry.entity_id,
"type": "is_on",
}
],
"action": {
"service": "test.automation",
"data_template": {
"some": "is_on {{ trigger.%s }}"
% "}} - {{ trigger.".join(("platform", "event.event_type"))
},
},
},
]
},
)
await hass.async_block_till_done()
assert len(calls) == 0
hass.bus.async_fire("test_event1")
hass.bus.async_fire("test_event2")
await hass.async_block_till_done()
assert len(calls) == 1
assert calls[0].data["some"] == "is_on event - test_event1"
async def test_if_fires_on_for_condition( async def test_if_fires_on_for_condition(
hass: HomeAssistant, calls, enable_custom_integrations: None hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None: ) -> None:
"""Test for firing if condition is on with delay.""" """Test for firing if condition is on with delay."""
entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
hass.states.async_set(entry.entity_id, STATE_ON)
point1 = dt_util.utcnow() point1 = dt_util.utcnow()
point2 = point1 + timedelta(seconds=10) point2 = point1 + timedelta(seconds=10)
point3 = point2 + timedelta(seconds=10) point3 = point2 + timedelta(seconds=10)
@ -248,7 +334,7 @@ async def test_if_fires_on_for_condition(
"condition": "device", "condition": "device",
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.id,
"type": "is_off", "type": "is_off",
"for": {"seconds": 5}, "for": {"seconds": 5},
}, },
@ -266,7 +352,6 @@ async def test_if_fires_on_for_condition(
}, },
) )
await hass.async_block_till_done() await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_ON
assert len(calls) == 0 assert len(calls) == 0
hass.bus.async_fire("test_event1") hass.bus.async_fire("test_event1")
@ -279,7 +364,7 @@ async def test_if_fires_on_for_condition(
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(calls) == 0 assert len(calls) == 0
hass.states.async_set(ent1.entity_id, STATE_OFF) hass.states.async_set(entry.entity_id, STATE_OFF)
hass.bus.async_fire("test_event1") hass.bus.async_fire("test_event1")
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(calls) == 0 assert len(calls) == 0

View file

@ -7,7 +7,7 @@ from pytest_unordered import unordered
import homeassistant.components.automation as automation import homeassistant.components.automation as automation
from homeassistant.components.device_automation import DeviceAutomationType from homeassistant.components.device_automation import DeviceAutomationType
from homeassistant.components.light import DOMAIN from homeassistant.components.light import DOMAIN
from homeassistant.const import CONF_PLATFORM, STATE_OFF, STATE_ON, EntityCategory from homeassistant.const import STATE_OFF, STATE_ON, EntityCategory
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
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.helpers.entity_registry import RegistryEntryHider from homeassistant.helpers.entity_registry import RegistryEntryHider
@ -46,7 +46,7 @@ async def test_get_triggers(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_registry.async_get_or_create( entity_entry = entity_registry.async_get_or_create(
DOMAIN, "test", "5678", device_id=device_entry.id DOMAIN, "test", "5678", device_id=device_entry.id
) )
expected_triggers = [ expected_triggers = [
@ -55,7 +55,7 @@ async def test_get_triggers(
"domain": DOMAIN, "domain": DOMAIN,
"type": trigger, "type": trigger,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": entity_entry.id,
"metadata": {"secondary": False}, "metadata": {"secondary": False},
} }
for trigger in ["changed_states", "turned_off", "turned_on"] for trigger in ["changed_states", "turned_off", "turned_on"]
@ -89,7 +89,7 @@ async def test_get_triggers_hidden_auxiliary(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_registry.async_get_or_create( entity_entry = entity_registry.async_get_or_create(
DOMAIN, DOMAIN,
"test", "test",
"5678", "5678",
@ -103,7 +103,7 @@ async def test_get_triggers_hidden_auxiliary(
"domain": DOMAIN, "domain": DOMAIN,
"type": trigger, "type": trigger,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": entity_entry.id,
"metadata": {"secondary": True}, "metadata": {"secondary": True},
} }
for trigger in ["changed_states", "turned_off", "turned_on"] for trigger in ["changed_states", "turned_off", "turned_on"]
@ -144,19 +144,47 @@ async def test_get_trigger_capabilities(
assert capabilities == expected_capabilities assert capabilities == expected_capabilities
async def test_get_trigger_capabilities_legacy(
hass: HomeAssistant,
device_registry: dr.DeviceRegistry,
entity_registry: er.EntityRegistry,
) -> None:
"""Test we get the expected capabilities from a light trigger."""
config_entry = MockConfigEntry(domain="test", data={})
config_entry.add_to_hass(hass)
device_entry = device_registry.async_get_or_create(
config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
)
entity_registry.async_get_or_create(
DOMAIN, "test", "5678", device_id=device_entry.id
)
expected_capabilities = {
"extra_fields": [
{"name": "for", "optional": True, "type": "positive_time_period_dict"}
]
}
triggers = await async_get_device_automations(
hass, DeviceAutomationType.TRIGGER, device_entry.id
)
for trigger in triggers:
trigger["entity_id"] = entity_registry.async_get(trigger["entity_id"]).entity_id
capabilities = await async_get_device_automation_capabilities(
hass, DeviceAutomationType.TRIGGER, trigger
)
assert capabilities == expected_capabilities
async def test_if_fires_on_state_change( async def test_if_fires_on_state_change(
hass: HomeAssistant, calls, enable_custom_integrations: None hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None: ) -> None:
"""Test for turn_on and turn_off triggers firing.""" """Test for turn_on and turn_off triggers firing."""
platform = getattr(hass.components, f"test.{DOMAIN}") entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
platform.init() hass.states.async_set(entry.entity_id, STATE_ON)
await hass.async_block_till_done()
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
await hass.async_block_till_done()
ent1, ent2, ent3 = platform.ENTITIES
assert await async_setup_component( assert await async_setup_component(
hass, hass,
@ -168,7 +196,7 @@ async def test_if_fires_on_state_change(
"platform": "device", "platform": "device",
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.id,
"type": "turned_on", "type": "turned_on",
}, },
"action": { "action": {
@ -192,7 +220,7 @@ async def test_if_fires_on_state_change(
"platform": "device", "platform": "device",
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.id,
"type": "turned_off", "type": "turned_off",
}, },
"action": { "action": {
@ -216,7 +244,7 @@ async def test_if_fires_on_state_change(
"platform": "device", "platform": "device",
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.id,
"type": "changed_states", "type": "changed_states",
}, },
"action": { "action": {
@ -239,39 +267,35 @@ async def test_if_fires_on_state_change(
}, },
) )
await hass.async_block_till_done() await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_ON
assert len(calls) == 0 assert len(calls) == 0
hass.states.async_set(ent1.entity_id, STATE_OFF) hass.states.async_set(entry.entity_id, STATE_OFF)
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(calls) == 2 assert len(calls) == 2
assert {calls[0].data["some"], calls[1].data["some"]} == { assert {calls[0].data["some"], calls[1].data["some"]} == {
f"turn_off device - {ent1.entity_id} - on - off - None", f"turn_off device - {entry.entity_id} - on - off - None",
f"turn_on_or_off device - {ent1.entity_id} - on - off - None", f"turn_on_or_off device - {entry.entity_id} - on - off - None",
} }
hass.states.async_set(ent1.entity_id, STATE_ON) hass.states.async_set(entry.entity_id, STATE_ON)
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(calls) == 4 assert len(calls) == 4
assert {calls[2].data["some"], calls[3].data["some"]} == { assert {calls[2].data["some"], calls[3].data["some"]} == {
f"turn_on device - {ent1.entity_id} - off - on - None", f"turn_on device - {entry.entity_id} - off - on - None",
f"turn_on_or_off device - {ent1.entity_id} - off - on - None", f"turn_on_or_off device - {entry.entity_id} - off - on - None",
} }
async def test_if_fires_on_state_change_with_for( async def test_if_fires_on_state_change_legacy(
hass: HomeAssistant, calls, enable_custom_integrations: None hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None: ) -> None:
"""Test for triggers firing with delay.""" """Test for turn_on and turn_off triggers firing."""
platform = getattr(hass.components, f"test.{DOMAIN}") entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
platform.init() hass.states.async_set(entry.entity_id, STATE_ON)
await hass.async_block_till_done()
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
await hass.async_block_till_done()
ent1, ent2, ent3 = platform.ENTITIES
assert await async_setup_component( assert await async_setup_component(
hass, hass,
@ -283,7 +307,61 @@ async def test_if_fires_on_state_change_with_for(
"platform": "device", "platform": "device",
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.entity_id,
"type": "turned_off",
},
"action": {
"service": "test.automation",
"data_template": {
"some": "turn_on {{ trigger.%s }}"
% "}} - {{ trigger.".join(
(
"platform",
"entity_id",
"from_state.state",
"to_state.state",
"for",
)
)
},
},
},
]
},
)
await hass.async_block_till_done()
assert len(calls) == 0
hass.states.async_set(entry.entity_id, STATE_OFF)
await hass.async_block_till_done()
assert len(calls) == 1
assert (
calls[0].data["some"] == f"turn_on device - {entry.entity_id} - on - off - None"
)
async def test_if_fires_on_state_change_with_for(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None:
"""Test for triggers firing with delay."""
entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
hass.states.async_set(entry.entity_id, STATE_ON)
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: [
{
"trigger": {
"platform": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": entry.id,
"type": "turned_off", "type": "turned_off",
"for": {"seconds": 5}, "for": {"seconds": 5},
}, },
@ -307,16 +385,16 @@ async def test_if_fires_on_state_change_with_for(
}, },
) )
await hass.async_block_till_done() await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_ON
assert len(calls) == 0 assert len(calls) == 0
hass.states.async_set(ent1.entity_id, STATE_OFF) hass.states.async_set(entry.entity_id, STATE_OFF)
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(calls) == 0 assert len(calls) == 0
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=10)) async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=10))
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(calls) == 1 assert len(calls) == 1
await hass.async_block_till_done() await hass.async_block_till_done()
assert calls[0].data["some"] == "turn_off device - {} - on - off - 0:00:05".format( assert (
ent1.entity_id calls[0].data["some"]
== f"turn_off device - {entry.entity_id} - on - off - 0:00:05"
) )

View file

@ -58,11 +58,9 @@ async def test_get_triggers(
DOMAIN, "test", "5678", device_id=device_entry.id DOMAIN, "test", "5678", device_id=device_entry.id
) )
entity_trigger_types = {
"changed_states",
}
trigger_types = { trigger_types = {
"buffering", "buffering",
"changed_states",
"idle", "idle",
"paused", "paused",
"playing", "playing",
@ -80,17 +78,6 @@ async def test_get_triggers(
} }
for trigger in trigger_types for trigger in trigger_types
] ]
expected_triggers += [
{
"platform": "device",
"domain": DOMAIN,
"type": trigger,
"device_id": device_entry.id,
"entity_id": entity_entry.entity_id,
"metadata": {"secondary": False},
}
for trigger in entity_trigger_types
]
triggers = await async_get_device_automations( triggers = await async_get_device_automations(
hass, DeviceAutomationType.TRIGGER, device_entry.id hass, DeviceAutomationType.TRIGGER, device_entry.id
) )
@ -128,11 +115,9 @@ async def test_get_triggers_hidden_auxiliary(
entity_category=entity_category, entity_category=entity_category,
hidden_by=hidden_by, hidden_by=hidden_by,
) )
entity_trigger_types = {
"changed_states",
}
trigger_types = { trigger_types = {
"buffering", "buffering",
"changed_states",
"idle", "idle",
"paused", "paused",
"playing", "playing",
@ -150,17 +135,6 @@ async def test_get_triggers_hidden_auxiliary(
} }
for trigger in trigger_types for trigger in trigger_types
] ]
expected_triggers += [
{
"platform": "device",
"domain": DOMAIN,
"type": trigger,
"device_id": device_entry.id,
"entity_id": entity_entry.entity_id,
"metadata": {"secondary": True},
}
for trigger in entity_trigger_types
]
triggers = await async_get_device_automations( triggers = await async_get_device_automations(
hass, DeviceAutomationType.TRIGGER, device_entry.id hass, DeviceAutomationType.TRIGGER, device_entry.id
) )
@ -263,9 +237,7 @@ async def test_if_fires_on_state_change(
"platform": "device", "platform": "device",
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": entry.entity_id "entity_id": entry.id,
if trigger == "changed_states"
else entry.id,
"type": trigger, "type": trigger,
}, },
"action": { "action": {

View file

@ -5,7 +5,7 @@ from pytest_unordered import unordered
import homeassistant.components.automation as automation import homeassistant.components.automation as automation
from homeassistant.components.device_automation import DeviceAutomationType from homeassistant.components.device_automation import DeviceAutomationType
from homeassistant.components.remote import DOMAIN from homeassistant.components.remote import DOMAIN
from homeassistant.const import CONF_PLATFORM, STATE_OFF, STATE_ON, EntityCategory from homeassistant.const import EntityCategory
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
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.helpers.entity_registry import RegistryEntryHider from homeassistant.helpers.entity_registry import RegistryEntryHider
@ -41,7 +41,7 @@ async def test_get_actions(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_registry.async_get_or_create( entity_entry = entity_registry.async_get_or_create(
DOMAIN, "test", "5678", device_id=device_entry.id DOMAIN, "test", "5678", device_id=device_entry.id
) )
expected_actions = [ expected_actions = [
@ -49,7 +49,7 @@ async def test_get_actions(
"domain": DOMAIN, "domain": DOMAIN,
"type": action, "type": action,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": entity_entry.id,
"metadata": {"secondary": False}, "metadata": {"secondary": False},
} }
for action in ["turn_off", "turn_on", "toggle"] for action in ["turn_off", "turn_on", "toggle"]
@ -83,7 +83,7 @@ async def test_get_actions_hidden_auxiliary(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_registry.async_get_or_create( entity_entry = entity_registry.async_get_or_create(
DOMAIN, DOMAIN,
"test", "test",
"5678", "5678",
@ -97,7 +97,7 @@ async def test_get_actions_hidden_auxiliary(
"domain": DOMAIN, "domain": DOMAIN,
"type": action, "type": action,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": entity_entry.id,
"metadata": {"secondary": True}, "metadata": {"secondary": True},
} }
for action in ["turn_off", "turn_on", "toggle"] for action in ["turn_off", "turn_on", "toggle"]
@ -109,16 +109,13 @@ async def test_get_actions_hidden_auxiliary(
async def test_action( async def test_action(
hass: HomeAssistant, calls, enable_custom_integrations: None hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None: ) -> None:
"""Test for turn_on and turn_off actions.""" """Test for turn_on and turn_off actions."""
platform = getattr(hass.components, f"test.{DOMAIN}") entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
platform.init()
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
await hass.async_block_till_done()
ent1, ent2, ent3 = platform.ENTITIES
assert await async_setup_component( assert await async_setup_component(
hass, hass,
@ -126,29 +123,29 @@ async def test_action(
{ {
automation.DOMAIN: [ automation.DOMAIN: [
{ {
"trigger": {"platform": "event", "event_type": "test_event1"}, "trigger": {"platform": "event", "event_type": "test_off"},
"action": { "action": {
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.id,
"type": "turn_off", "type": "turn_off",
}, },
}, },
{ {
"trigger": {"platform": "event", "event_type": "test_event2"}, "trigger": {"platform": "event", "event_type": "test_on"},
"action": { "action": {
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.id,
"type": "turn_on", "type": "turn_on",
}, },
}, },
{ {
"trigger": {"platform": "event", "event_type": "test_event3"}, "trigger": {"platform": "event", "event_type": "test_toggle"},
"action": { "action": {
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.id,
"type": "toggle", "type": "toggle",
}, },
}, },
@ -156,29 +153,58 @@ async def test_action(
}, },
) )
await hass.async_block_till_done() await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_ON
assert len(calls) == 0
hass.bus.async_fire("test_event1") turn_on_calls = async_mock_service(hass, DOMAIN, "turn_on")
await hass.async_block_till_done() turn_off_calls = async_mock_service(hass, DOMAIN, "turn_off")
assert hass.states.get(ent1.entity_id).state == STATE_OFF toggle_calls = async_mock_service(hass, DOMAIN, "toggle")
hass.bus.async_fire("test_event1") hass.bus.async_fire("test_toggle")
await hass.async_block_till_done() await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_OFF assert len(toggle_calls) == 1
assert toggle_calls[-1].data == {"entity_id": entry.entity_id}
hass.bus.async_fire("test_event2") hass.bus.async_fire("test_off")
await hass.async_block_till_done() await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_ON assert len(turn_off_calls) == 1
assert turn_off_calls[-1].data == {"entity_id": entry.entity_id}
hass.bus.async_fire("test_event2") hass.bus.async_fire("test_on")
await hass.async_block_till_done() await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_ON assert len(turn_on_calls) == 1
assert turn_on_calls[-1].data == {"entity_id": entry.entity_id}
hass.bus.async_fire("test_event3")
await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_OFF
hass.bus.async_fire("test_event3") async def test_action_legacy(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None:
"""Test for turn_on and turn_off actions."""
entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: [
{
"trigger": {"platform": "event", "event_type": "test_off"},
"action": {
"domain": DOMAIN,
"device_id": "",
"entity_id": entry.entity_id,
"type": "turn_off",
},
},
]
},
)
await hass.async_block_till_done() await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_ON
turn_off_calls = async_mock_service(hass, DOMAIN, "turn_off")
hass.bus.async_fire("test_off")
await hass.async_block_till_done()
assert len(turn_off_calls) == 1
assert turn_off_calls[-1].data == {"entity_id": entry.entity_id}

View file

@ -8,7 +8,7 @@ from pytest_unordered import unordered
import homeassistant.components.automation as automation import homeassistant.components.automation as automation
from homeassistant.components.device_automation import DeviceAutomationType from homeassistant.components.device_automation import DeviceAutomationType
from homeassistant.components.remote import DOMAIN from homeassistant.components.remote import DOMAIN
from homeassistant.const import CONF_PLATFORM, STATE_OFF, STATE_ON, EntityCategory from homeassistant.const import STATE_OFF, STATE_ON, EntityCategory
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
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.helpers.entity_registry import RegistryEntryHider from homeassistant.helpers.entity_registry import RegistryEntryHider
@ -46,7 +46,7 @@ async def test_get_conditions(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_registry.async_get_or_create( entity_entry = entity_registry.async_get_or_create(
DOMAIN, "test", "5678", device_id=device_entry.id DOMAIN, "test", "5678", device_id=device_entry.id
) )
expected_conditions = [ expected_conditions = [
@ -55,7 +55,7 @@ async def test_get_conditions(
"domain": DOMAIN, "domain": DOMAIN,
"type": condition, "type": condition,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": entity_entry.id,
"metadata": {"secondary": False}, "metadata": {"secondary": False},
} }
for condition in ["is_off", "is_on"] for condition in ["is_off", "is_on"]
@ -89,7 +89,7 @@ async def test_get_conditions_hidden_auxiliary(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_registry.async_get_or_create( entity_entry = entity_registry.async_get_or_create(
DOMAIN, DOMAIN,
"test", "test",
"5678", "5678",
@ -103,7 +103,7 @@ async def test_get_conditions_hidden_auxiliary(
"domain": DOMAIN, "domain": DOMAIN,
"type": condition, "type": condition,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": entity_entry.id,
"metadata": {"secondary": True}, "metadata": {"secondary": True},
} }
for condition in ["is_off", "is_on"] for condition in ["is_off", "is_on"]
@ -144,17 +144,49 @@ async def test_get_condition_capabilities(
assert capabilities == expected_capabilities assert capabilities == expected_capabilities
async def test_get_condition_capabilities_legacy(
hass: HomeAssistant,
device_registry: dr.DeviceRegistry,
entity_registry: er.EntityRegistry,
) -> None:
"""Test we get the expected capabilities from a remote condition."""
config_entry = MockConfigEntry(domain="test", data={})
config_entry.add_to_hass(hass)
device_entry = device_registry.async_get_or_create(
config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
)
entity_registry.async_get_or_create(
DOMAIN, "test", "5678", device_id=device_entry.id
)
expected_capabilities = {
"extra_fields": [
{"name": "for", "optional": True, "type": "positive_time_period_dict"}
]
}
conditions = await async_get_device_automations(
hass, DeviceAutomationType.CONDITION, device_entry.id
)
for condition in conditions:
condition["entity_id"] = entity_registry.async_get(
condition["entity_id"]
).entity_id
capabilities = await async_get_device_automation_capabilities(
hass, DeviceAutomationType.CONDITION, condition
)
assert capabilities == expected_capabilities
async def test_if_state( async def test_if_state(
hass: HomeAssistant, calls, enable_custom_integrations: None hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None: ) -> None:
"""Test for turn_on and turn_off conditions.""" """Test for turn_on and turn_off conditions."""
platform = getattr(hass.components, f"test.{DOMAIN}") entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
platform.init() hass.states.async_set(entry.entity_id, STATE_ON)
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
await hass.async_block_till_done()
ent1, ent2, ent3 = platform.ENTITIES
assert await async_setup_component( assert await async_setup_component(
hass, hass,
@ -168,7 +200,7 @@ async def test_if_state(
"condition": "device", "condition": "device",
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.id,
"type": "is_on", "type": "is_on",
} }
], ],
@ -187,7 +219,7 @@ async def test_if_state(
"condition": "device", "condition": "device",
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.id,
"type": "is_off", "type": "is_off",
} }
], ],
@ -203,7 +235,6 @@ async def test_if_state(
}, },
) )
await hass.async_block_till_done() await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_ON
assert len(calls) == 0 assert len(calls) == 0
hass.bus.async_fire("test_event1") hass.bus.async_fire("test_event1")
@ -212,7 +243,7 @@ async def test_if_state(
assert len(calls) == 1 assert len(calls) == 1
assert calls[0].data["some"] == "is_on event - test_event1" assert calls[0].data["some"] == "is_on event - test_event1"
hass.states.async_set(ent1.entity_id, STATE_OFF) hass.states.async_set(entry.entity_id, STATE_OFF)
hass.bus.async_fire("test_event1") hass.bus.async_fire("test_event1")
hass.bus.async_fire("test_event2") hass.bus.async_fire("test_event2")
await hass.async_block_till_done() await hass.async_block_till_done()
@ -220,21 +251,68 @@ async def test_if_state(
assert calls[1].data["some"] == "is_off event - test_event2" assert calls[1].data["some"] == "is_off event - test_event2"
async def test_if_state_legacy(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None:
"""Test for turn_on and turn_off conditions."""
entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
hass.states.async_set(entry.entity_id, STATE_ON)
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: [
{
"trigger": {"platform": "event", "event_type": "test_event1"},
"condition": [
{
"condition": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": entry.entity_id,
"type": "is_on",
}
],
"action": {
"service": "test.automation",
"data_template": {
"some": "is_on {{ trigger.%s }}"
% "}} - {{ trigger.".join(("platform", "event.event_type"))
},
},
},
]
},
)
await hass.async_block_till_done()
assert len(calls) == 0
hass.bus.async_fire("test_event1")
hass.bus.async_fire("test_event2")
await hass.async_block_till_done()
assert len(calls) == 1
assert calls[0].data["some"] == "is_on event - test_event1"
async def test_if_fires_on_for_condition( async def test_if_fires_on_for_condition(
hass: HomeAssistant, calls, enable_custom_integrations: None hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None: ) -> None:
"""Test for firing if condition is on with delay.""" """Test for firing if condition is on with delay."""
point1 = dt_util.utcnow() point1 = dt_util.utcnow()
point2 = point1 + timedelta(seconds=10) point2 = point1 + timedelta(seconds=10)
point3 = point2 + timedelta(seconds=10) point3 = point2 + timedelta(seconds=10)
platform = getattr(hass.components, f"test.{DOMAIN}") entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
platform.init() hass.states.async_set(entry.entity_id, STATE_ON)
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
await hass.async_block_till_done()
ent1, ent2, ent3 = platform.ENTITIES
with freeze_time(point1) as freezer: with freeze_time(point1) as freezer:
assert await async_setup_component( assert await async_setup_component(
@ -248,7 +326,7 @@ async def test_if_fires_on_for_condition(
"condition": "device", "condition": "device",
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.id,
"type": "is_off", "type": "is_off",
"for": {"seconds": 5}, "for": {"seconds": 5},
}, },
@ -266,7 +344,6 @@ async def test_if_fires_on_for_condition(
}, },
) )
await hass.async_block_till_done() await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_ON
assert len(calls) == 0 assert len(calls) == 0
hass.bus.async_fire("test_event1") hass.bus.async_fire("test_event1")
@ -279,7 +356,7 @@ async def test_if_fires_on_for_condition(
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(calls) == 0 assert len(calls) == 0
hass.states.async_set(ent1.entity_id, STATE_OFF) hass.states.async_set(entry.entity_id, STATE_OFF)
hass.bus.async_fire("test_event1") hass.bus.async_fire("test_event1")
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(calls) == 0 assert len(calls) == 0

View file

@ -7,7 +7,7 @@ from pytest_unordered import unordered
import homeassistant.components.automation as automation import homeassistant.components.automation as automation
from homeassistant.components.device_automation import DeviceAutomationType from homeassistant.components.device_automation import DeviceAutomationType
from homeassistant.components.remote import DOMAIN from homeassistant.components.remote import DOMAIN
from homeassistant.const import CONF_PLATFORM, STATE_OFF, STATE_ON, EntityCategory from homeassistant.const import STATE_OFF, STATE_ON, EntityCategory
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
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.helpers.entity_registry import RegistryEntryHider from homeassistant.helpers.entity_registry import RegistryEntryHider
@ -46,7 +46,7 @@ async def test_get_triggers(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_registry.async_get_or_create( entity_entry = entity_registry.async_get_or_create(
DOMAIN, "test", "5678", device_id=device_entry.id DOMAIN, "test", "5678", device_id=device_entry.id
) )
expected_triggers = [ expected_triggers = [
@ -55,7 +55,7 @@ async def test_get_triggers(
"domain": DOMAIN, "domain": DOMAIN,
"type": trigger, "type": trigger,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": entity_entry.id,
"metadata": {"secondary": False}, "metadata": {"secondary": False},
} }
for trigger in ["changed_states", "turned_off", "turned_on"] for trigger in ["changed_states", "turned_off", "turned_on"]
@ -89,7 +89,7 @@ async def test_get_triggers_hidden_auxiliary(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_registry.async_get_or_create( entity_entry = entity_registry.async_get_or_create(
DOMAIN, DOMAIN,
"test", "test",
"5678", "5678",
@ -103,7 +103,7 @@ async def test_get_triggers_hidden_auxiliary(
"domain": DOMAIN, "domain": DOMAIN,
"type": trigger, "type": trigger,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": entity_entry.id,
"metadata": {"secondary": True}, "metadata": {"secondary": True},
} }
for trigger in ["changed_states", "turned_off", "turned_on"] for trigger in ["changed_states", "turned_off", "turned_on"]
@ -144,17 +144,47 @@ async def test_get_trigger_capabilities(
assert capabilities == expected_capabilities assert capabilities == expected_capabilities
async def test_get_trigger_capabilities_legacy(
hass: HomeAssistant,
device_registry: dr.DeviceRegistry,
entity_registry: er.EntityRegistry,
) -> None:
"""Test we get the expected capabilities from a remote trigger."""
config_entry = MockConfigEntry(domain="test", data={})
config_entry.add_to_hass(hass)
device_entry = device_registry.async_get_or_create(
config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
)
entity_registry.async_get_or_create(
DOMAIN, "test", "5678", device_id=device_entry.id
)
expected_capabilities = {
"extra_fields": [
{"name": "for", "optional": True, "type": "positive_time_period_dict"}
]
}
triggers = await async_get_device_automations(
hass, DeviceAutomationType.TRIGGER, device_entry.id
)
for trigger in triggers:
trigger["entity_id"] = entity_registry.async_get(trigger["entity_id"]).entity_id
capabilities = await async_get_device_automation_capabilities(
hass, DeviceAutomationType.TRIGGER, trigger
)
assert capabilities == expected_capabilities
async def test_if_fires_on_state_change( async def test_if_fires_on_state_change(
hass: HomeAssistant, calls, enable_custom_integrations: None hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None: ) -> None:
"""Test for turn_on and turn_off triggers firing.""" """Test for turn_on and turn_off triggers firing."""
platform = getattr(hass.components, f"test.{DOMAIN}") entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
platform.init() hass.states.async_set(entry.entity_id, STATE_ON)
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
await hass.async_block_till_done()
ent1, ent2, ent3 = platform.ENTITIES
assert await async_setup_component( assert await async_setup_component(
hass, hass,
@ -166,7 +196,7 @@ async def test_if_fires_on_state_change(
"platform": "device", "platform": "device",
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.id,
"type": "turned_on", "type": "turned_on",
}, },
"action": { "action": {
@ -190,7 +220,7 @@ async def test_if_fires_on_state_change(
"platform": "device", "platform": "device",
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.id,
"type": "turned_off", "type": "turned_off",
}, },
"action": { "action": {
@ -214,7 +244,7 @@ async def test_if_fires_on_state_change(
"platform": "device", "platform": "device",
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.id,
"type": "changed_states", "type": "changed_states",
}, },
"action": { "action": {
@ -236,38 +266,35 @@ async def test_if_fires_on_state_change(
] ]
}, },
) )
await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_ON
assert len(calls) == 0 assert len(calls) == 0
hass.states.async_set(ent1.entity_id, STATE_OFF) hass.states.async_set(entry.entity_id, STATE_OFF)
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(calls) == 2 assert len(calls) == 2
assert {calls[0].data["some"], calls[1].data["some"]} == { assert {calls[0].data["some"], calls[1].data["some"]} == {
f"turn_off device - {ent1.entity_id} - on - off - None", f"turn_off device - {entry.entity_id} - on - off - None",
f"turn_on_or_off device - {ent1.entity_id} - on - off - None", f"turn_on_or_off device - {entry.entity_id} - on - off - None",
} }
hass.states.async_set(ent1.entity_id, STATE_ON) hass.states.async_set(entry.entity_id, STATE_ON)
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(calls) == 4 assert len(calls) == 4
assert {calls[2].data["some"], calls[3].data["some"]} == { assert {calls[2].data["some"], calls[3].data["some"]} == {
f"turn_on device - {ent1.entity_id} - off - on - None", f"turn_on device - {entry.entity_id} - off - on - None",
f"turn_on_or_off device - {ent1.entity_id} - off - on - None", f"turn_on_or_off device - {entry.entity_id} - off - on - None",
} }
async def test_if_fires_on_state_change_with_for( async def test_if_fires_on_state_change_legacy(
hass: HomeAssistant, calls, enable_custom_integrations: None hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None: ) -> None:
"""Test for triggers firing with delay.""" """Test for turn_on and turn_off triggers firing."""
platform = getattr(hass.components, f"test.{DOMAIN}") entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
platform.init() hass.states.async_set(entry.entity_id, STATE_ON)
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
await hass.async_block_till_done()
ent1, ent2, ent3 = platform.ENTITIES
assert await async_setup_component( assert await async_setup_component(
hass, hass,
@ -279,7 +306,61 @@ async def test_if_fires_on_state_change_with_for(
"platform": "device", "platform": "device",
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.entity_id,
"type": "turned_off",
},
"action": {
"service": "test.automation",
"data_template": {
"some": "turn_off {{ trigger.%s }}"
% "}} - {{ trigger.".join(
(
"platform",
"entity_id",
"from_state.state",
"to_state.state",
"for",
)
)
},
},
},
]
},
)
assert len(calls) == 0
hass.states.async_set(entry.entity_id, STATE_OFF)
await hass.async_block_till_done()
assert len(calls) == 1
assert (
calls[0].data["some"]
== f"turn_off device - {entry.entity_id} - on - off - None"
)
async def test_if_fires_on_state_change_with_for(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None:
"""Test for triggers firing with delay."""
entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
hass.states.async_set(entry.entity_id, STATE_ON)
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: [
{
"trigger": {
"platform": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": entry.id,
"type": "turned_off", "type": "turned_off",
"for": {"seconds": 5}, "for": {"seconds": 5},
}, },
@ -303,16 +384,16 @@ async def test_if_fires_on_state_change_with_for(
}, },
) )
await hass.async_block_till_done() await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_ON
assert len(calls) == 0 assert len(calls) == 0
hass.states.async_set(ent1.entity_id, STATE_OFF) hass.states.async_set(entry.entity_id, STATE_OFF)
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(calls) == 0 assert len(calls) == 0
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=10)) async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=10))
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(calls) == 1 assert len(calls) == 1
await hass.async_block_till_done() await hass.async_block_till_done()
assert calls[0].data["some"] == "turn_off device - {} - on - off - 0:00:05".format( assert (
ent1.entity_id calls[0].data["some"]
== f"turn_off device - {entry.entity_id} - on - off - 0:00:05"
) )

View file

@ -5,7 +5,7 @@ from pytest_unordered import unordered
import homeassistant.components.automation as automation import homeassistant.components.automation as automation
from homeassistant.components.device_automation import DeviceAutomationType from homeassistant.components.device_automation import DeviceAutomationType
from homeassistant.components.switch import DOMAIN from homeassistant.components.switch import DOMAIN
from homeassistant.const import CONF_PLATFORM, STATE_OFF, STATE_ON, EntityCategory from homeassistant.const import EntityCategory
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
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.helpers.entity_registry import RegistryEntryHider from homeassistant.helpers.entity_registry import RegistryEntryHider
@ -41,7 +41,7 @@ async def test_get_actions(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_registry.async_get_or_create( entity_entry = entity_registry.async_get_or_create(
DOMAIN, "test", "5678", device_id=device_entry.id DOMAIN, "test", "5678", device_id=device_entry.id
) )
expected_actions = [] expected_actions = []
@ -50,7 +50,7 @@ async def test_get_actions(
"domain": DOMAIN, "domain": DOMAIN,
"type": action, "type": action,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": entity_entry.id,
"metadata": {"secondary": False}, "metadata": {"secondary": False},
} }
for action in ["turn_off", "turn_on", "toggle"] for action in ["turn_off", "turn_on", "toggle"]
@ -84,7 +84,7 @@ async def test_get_actions_hidden_auxiliary(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_registry.async_get_or_create( entity_entry = entity_registry.async_get_or_create(
DOMAIN, DOMAIN,
"test", "test",
"5678", "5678",
@ -98,7 +98,7 @@ async def test_get_actions_hidden_auxiliary(
"domain": DOMAIN, "domain": DOMAIN,
"type": action, "type": action,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": entity_entry.id,
"metadata": {"secondary": True}, "metadata": {"secondary": True},
} }
for action in ["turn_off", "turn_on", "toggle"] for action in ["turn_off", "turn_on", "toggle"]
@ -110,16 +110,13 @@ async def test_get_actions_hidden_auxiliary(
async def test_action( async def test_action(
hass: HomeAssistant, calls, enable_custom_integrations: None hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None: ) -> None:
"""Test for turn_on and turn_off actions.""" """Test for turn_on and turn_off actions."""
platform = getattr(hass.components, f"test.{DOMAIN}") entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
platform.init()
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
await hass.async_block_till_done()
ent1, ent2, ent3 = platform.ENTITIES
assert await async_setup_component( assert await async_setup_component(
hass, hass,
@ -127,29 +124,29 @@ async def test_action(
{ {
automation.DOMAIN: [ automation.DOMAIN: [
{ {
"trigger": {"platform": "event", "event_type": "test_event1"}, "trigger": {"platform": "event", "event_type": "test_off"},
"action": { "action": {
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.id,
"type": "turn_off", "type": "turn_off",
}, },
}, },
{ {
"trigger": {"platform": "event", "event_type": "test_event2"}, "trigger": {"platform": "event", "event_type": "test_on"},
"action": { "action": {
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.id,
"type": "turn_on", "type": "turn_on",
}, },
}, },
{ {
"trigger": {"platform": "event", "event_type": "test_event3"}, "trigger": {"platform": "event", "event_type": "test_toggle"},
"action": { "action": {
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.id,
"type": "toggle", "type": "toggle",
}, },
}, },
@ -157,29 +154,58 @@ async def test_action(
}, },
) )
await hass.async_block_till_done() await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_ON
assert len(calls) == 0
hass.bus.async_fire("test_event1") turn_on_calls = async_mock_service(hass, DOMAIN, "turn_on")
await hass.async_block_till_done() turn_off_calls = async_mock_service(hass, DOMAIN, "turn_off")
assert hass.states.get(ent1.entity_id).state == STATE_OFF toggle_calls = async_mock_service(hass, DOMAIN, "toggle")
hass.bus.async_fire("test_event1") hass.bus.async_fire("test_toggle")
await hass.async_block_till_done() await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_OFF assert len(toggle_calls) == 1
assert toggle_calls[-1].data == {"entity_id": entry.entity_id}
hass.bus.async_fire("test_event2") hass.bus.async_fire("test_off")
await hass.async_block_till_done() await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_ON assert len(turn_off_calls) == 1
assert turn_off_calls[-1].data == {"entity_id": entry.entity_id}
hass.bus.async_fire("test_event2") hass.bus.async_fire("test_on")
await hass.async_block_till_done() await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_ON assert len(turn_on_calls) == 1
assert turn_on_calls[-1].data == {"entity_id": entry.entity_id}
hass.bus.async_fire("test_event3")
await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_OFF
hass.bus.async_fire("test_event3") async def test_action_legacy(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None:
"""Test for turn_on and turn_off actions."""
entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: [
{
"trigger": {"platform": "event", "event_type": "test_off"},
"action": {
"domain": DOMAIN,
"device_id": "",
"entity_id": entry.id,
"type": "turn_off",
},
},
]
},
)
await hass.async_block_till_done() await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_ON
turn_off_calls = async_mock_service(hass, DOMAIN, "turn_off")
hass.bus.async_fire("test_off")
await hass.async_block_till_done()
assert len(turn_off_calls) == 1
assert turn_off_calls[-1].data == {"entity_id": entry.entity_id}

View file

@ -8,7 +8,7 @@ from pytest_unordered import unordered
import homeassistant.components.automation as automation import homeassistant.components.automation as automation
from homeassistant.components.device_automation import DeviceAutomationType from homeassistant.components.device_automation import DeviceAutomationType
from homeassistant.components.switch import DOMAIN from homeassistant.components.switch import DOMAIN
from homeassistant.const import CONF_PLATFORM, STATE_OFF, STATE_ON, EntityCategory from homeassistant.const import STATE_OFF, STATE_ON, EntityCategory
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
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.helpers.entity_registry import RegistryEntryHider from homeassistant.helpers.entity_registry import RegistryEntryHider
@ -46,7 +46,7 @@ async def test_get_conditions(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_registry.async_get_or_create( entity_entry = entity_registry.async_get_or_create(
DOMAIN, "test", "5678", device_id=device_entry.id DOMAIN, "test", "5678", device_id=device_entry.id
) )
expected_conditions = [ expected_conditions = [
@ -55,7 +55,7 @@ async def test_get_conditions(
"domain": DOMAIN, "domain": DOMAIN,
"type": condition, "type": condition,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": entity_entry.id,
"metadata": {"secondary": False}, "metadata": {"secondary": False},
} }
for condition in ["is_off", "is_on"] for condition in ["is_off", "is_on"]
@ -89,7 +89,7 @@ async def test_get_conditions_hidden_auxiliary(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_registry.async_get_or_create( entity_entry = entity_registry.async_get_or_create(
DOMAIN, DOMAIN,
"test", "test",
"5678", "5678",
@ -103,7 +103,7 @@ async def test_get_conditions_hidden_auxiliary(
"domain": DOMAIN, "domain": DOMAIN,
"type": condition, "type": condition,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": entity_entry.id,
"metadata": {"secondary": True}, "metadata": {"secondary": True},
} }
for condition in ["is_off", "is_on"] for condition in ["is_off", "is_on"]
@ -144,17 +144,49 @@ async def test_get_condition_capabilities(
assert capabilities == expected_capabilities assert capabilities == expected_capabilities
async def test_get_condition_capabilities_legacy(
hass: HomeAssistant,
device_registry: dr.DeviceRegistry,
entity_registry: er.EntityRegistry,
) -> None:
"""Test we get the expected capabilities from a switch condition."""
config_entry = MockConfigEntry(domain="test", data={})
config_entry.add_to_hass(hass)
device_entry = device_registry.async_get_or_create(
config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
)
entity_registry.async_get_or_create(
DOMAIN, "test", "5678", device_id=device_entry.id
)
expected_capabilities = {
"extra_fields": [
{"name": "for", "optional": True, "type": "positive_time_period_dict"}
]
}
conditions = await async_get_device_automations(
hass, DeviceAutomationType.CONDITION, device_entry.id
)
for condition in conditions:
condition["entity_id"] = entity_registry.async_get(
condition["entity_id"]
).entity_id
capabilities = await async_get_device_automation_capabilities(
hass, DeviceAutomationType.CONDITION, condition
)
assert capabilities == expected_capabilities
async def test_if_state( async def test_if_state(
hass: HomeAssistant, calls, enable_custom_integrations: None hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None: ) -> None:
"""Test for turn_on and turn_off conditions.""" """Test for turn_on and turn_off conditions."""
platform = getattr(hass.components, f"test.{DOMAIN}") entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
platform.init() hass.states.async_set(entry.entity_id, STATE_ON)
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
await hass.async_block_till_done()
ent1, ent2, ent3 = platform.ENTITIES
assert await async_setup_component( assert await async_setup_component(
hass, hass,
@ -168,7 +200,7 @@ async def test_if_state(
"condition": "device", "condition": "device",
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.id,
"type": "is_on", "type": "is_on",
} }
], ],
@ -187,7 +219,7 @@ async def test_if_state(
"condition": "device", "condition": "device",
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.id,
"type": "is_off", "type": "is_off",
} }
], ],
@ -203,7 +235,6 @@ async def test_if_state(
}, },
) )
await hass.async_block_till_done() await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_ON
assert len(calls) == 0 assert len(calls) == 0
hass.bus.async_fire("test_event1") hass.bus.async_fire("test_event1")
@ -212,7 +243,7 @@ async def test_if_state(
assert len(calls) == 1 assert len(calls) == 1
assert calls[0].data["some"] == "is_on event - test_event1" assert calls[0].data["some"] == "is_on event - test_event1"
hass.states.async_set(ent1.entity_id, STATE_OFF) hass.states.async_set(entry.entity_id, STATE_OFF)
hass.bus.async_fire("test_event1") hass.bus.async_fire("test_event1")
hass.bus.async_fire("test_event2") hass.bus.async_fire("test_event2")
await hass.async_block_till_done() await hass.async_block_till_done()
@ -220,21 +251,67 @@ async def test_if_state(
assert calls[1].data["some"] == "is_off event - test_event2" assert calls[1].data["some"] == "is_off event - test_event2"
async def test_if_state_legacy(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None:
"""Test for turn_on and turn_off conditions."""
entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
hass.states.async_set(entry.entity_id, STATE_ON)
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: [
{
"trigger": {"platform": "event", "event_type": "test_event1"},
"condition": [
{
"condition": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": entry.entity_id,
"type": "is_on",
}
],
"action": {
"service": "test.automation",
"data_template": {
"some": "is_on {{ trigger.%s }}"
% "}} - {{ trigger.".join(("platform", "event.event_type"))
},
},
},
]
},
)
await hass.async_block_till_done()
assert len(calls) == 0
hass.bus.async_fire("test_event1")
await hass.async_block_till_done()
assert len(calls) == 1
assert calls[0].data["some"] == "is_on event - test_event1"
async def test_if_fires_on_for_condition( async def test_if_fires_on_for_condition(
hass: HomeAssistant, calls, enable_custom_integrations: None hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None: ) -> None:
"""Test for firing if condition is on with delay.""" """Test for firing if condition is on with delay."""
point1 = dt_util.utcnow() point1 = dt_util.utcnow()
point2 = point1 + timedelta(seconds=10) point2 = point1 + timedelta(seconds=10)
point3 = point2 + timedelta(seconds=10) point3 = point2 + timedelta(seconds=10)
platform = getattr(hass.components, f"test.{DOMAIN}") entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
platform.init() hass.states.async_set(entry.entity_id, STATE_ON)
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
await hass.async_block_till_done()
ent1, ent2, ent3 = platform.ENTITIES
with freeze_time(point1) as freezer: with freeze_time(point1) as freezer:
assert await async_setup_component( assert await async_setup_component(
@ -248,7 +325,7 @@ async def test_if_fires_on_for_condition(
"condition": "device", "condition": "device",
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.id,
"type": "is_off", "type": "is_off",
"for": {"seconds": 5}, "for": {"seconds": 5},
}, },
@ -266,7 +343,6 @@ async def test_if_fires_on_for_condition(
}, },
) )
await hass.async_block_till_done() await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_ON
assert len(calls) == 0 assert len(calls) == 0
hass.bus.async_fire("test_event1") hass.bus.async_fire("test_event1")
@ -279,7 +355,7 @@ async def test_if_fires_on_for_condition(
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(calls) == 0 assert len(calls) == 0
hass.states.async_set(ent1.entity_id, STATE_OFF) hass.states.async_set(entry.entity_id, STATE_OFF)
hass.bus.async_fire("test_event1") hass.bus.async_fire("test_event1")
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(calls) == 0 assert len(calls) == 0

View file

@ -7,7 +7,7 @@ from pytest_unordered import unordered
import homeassistant.components.automation as automation import homeassistant.components.automation as automation
from homeassistant.components.device_automation import DeviceAutomationType from homeassistant.components.device_automation import DeviceAutomationType
from homeassistant.components.switch import DOMAIN from homeassistant.components.switch import DOMAIN
from homeassistant.const import CONF_PLATFORM, STATE_OFF, STATE_ON, EntityCategory from homeassistant.const import STATE_OFF, STATE_ON, EntityCategory
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
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.helpers.entity_registry import RegistryEntryHider from homeassistant.helpers.entity_registry import RegistryEntryHider
@ -46,7 +46,7 @@ async def test_get_triggers(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_registry.async_get_or_create( entity_entry = entity_registry.async_get_or_create(
DOMAIN, "test", "5678", device_id=device_entry.id DOMAIN, "test", "5678", device_id=device_entry.id
) )
expected_triggers = [ expected_triggers = [
@ -55,7 +55,7 @@ async def test_get_triggers(
"domain": DOMAIN, "domain": DOMAIN,
"type": trigger, "type": trigger,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": entity_entry.id,
"metadata": {"secondary": False}, "metadata": {"secondary": False},
} }
for trigger in ["changed_states", "turned_off", "turned_on"] for trigger in ["changed_states", "turned_off", "turned_on"]
@ -89,7 +89,7 @@ async def test_get_triggers_hidden_auxiliary(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_registry.async_get_or_create( entity_entry = entity_registry.async_get_or_create(
DOMAIN, DOMAIN,
"test", "test",
"5678", "5678",
@ -103,7 +103,7 @@ async def test_get_triggers_hidden_auxiliary(
"domain": DOMAIN, "domain": DOMAIN,
"type": trigger, "type": trigger,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": entity_entry.id,
"metadata": {"secondary": True}, "metadata": {"secondary": True},
} }
for trigger in ["changed_states", "turned_off", "turned_on"] for trigger in ["changed_states", "turned_off", "turned_on"]
@ -144,17 +144,47 @@ async def test_get_trigger_capabilities(
assert capabilities == expected_capabilities assert capabilities == expected_capabilities
async def test_get_trigger_capabilities_legacy(
hass: HomeAssistant,
device_registry: dr.DeviceRegistry,
entity_registry: er.EntityRegistry,
) -> None:
"""Test we get the expected capabilities from a switch trigger."""
config_entry = MockConfigEntry(domain="test", data={})
config_entry.add_to_hass(hass)
device_entry = device_registry.async_get_or_create(
config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
)
entity_registry.async_get_or_create(
DOMAIN, "test", "5678", device_id=device_entry.id
)
expected_capabilities = {
"extra_fields": [
{"name": "for", "optional": True, "type": "positive_time_period_dict"}
]
}
triggers = await async_get_device_automations(
hass, DeviceAutomationType.TRIGGER, device_entry.id
)
for trigger in triggers:
trigger["entity_id"] = entity_registry.async_get(trigger["entity_id"]).entity_id
capabilities = await async_get_device_automation_capabilities(
hass, DeviceAutomationType.TRIGGER, trigger
)
assert capabilities == expected_capabilities
async def test_if_fires_on_state_change( async def test_if_fires_on_state_change(
hass: HomeAssistant, calls, enable_custom_integrations: None hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None: ) -> None:
"""Test for turn_on and turn_off triggers firing.""" """Test for turn_on and turn_off triggers firing."""
platform = getattr(hass.components, f"test.{DOMAIN}") entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
platform.init() hass.states.async_set(entry.entity_id, STATE_ON)
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
await hass.async_block_till_done()
ent1, ent2, ent3 = platform.ENTITIES
assert await async_setup_component( assert await async_setup_component(
hass, hass,
@ -166,7 +196,7 @@ async def test_if_fires_on_state_change(
"platform": "device", "platform": "device",
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.id,
"type": "turned_on", "type": "turned_on",
}, },
"action": { "action": {
@ -190,7 +220,7 @@ async def test_if_fires_on_state_change(
"platform": "device", "platform": "device",
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.id,
"type": "turned_off", "type": "turned_off",
}, },
"action": { "action": {
@ -214,7 +244,7 @@ async def test_if_fires_on_state_change(
"platform": "device", "platform": "device",
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.id,
"type": "changed_states", "type": "changed_states",
}, },
"action": { "action": {
@ -237,37 +267,35 @@ async def test_if_fires_on_state_change(
}, },
) )
await hass.async_block_till_done() await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_ON
assert len(calls) == 0 assert len(calls) == 0
hass.states.async_set(ent1.entity_id, STATE_OFF) hass.states.async_set(entry.entity_id, STATE_OFF)
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(calls) == 2 assert len(calls) == 2
assert {calls[0].data["some"], calls[1].data["some"]} == { assert {calls[0].data["some"], calls[1].data["some"]} == {
f"turn_off device - {ent1.entity_id} - on - off - None", f"turn_off device - {entry.entity_id} - on - off - None",
f"turn_on_or_off device - {ent1.entity_id} - on - off - None", f"turn_on_or_off device - {entry.entity_id} - on - off - None",
} }
hass.states.async_set(ent1.entity_id, STATE_ON) hass.states.async_set(entry.entity_id, STATE_ON)
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(calls) == 4 assert len(calls) == 4
assert {calls[2].data["some"], calls[3].data["some"]} == { assert {calls[2].data["some"], calls[3].data["some"]} == {
f"turn_on device - {ent1.entity_id} - off - on - None", f"turn_on device - {entry.entity_id} - off - on - None",
f"turn_on_or_off device - {ent1.entity_id} - off - on - None", f"turn_on_or_off device - {entry.entity_id} - off - on - None",
} }
async def test_if_fires_on_state_change_with_for( async def test_if_fires_on_state_change_legacy(
hass: HomeAssistant, calls, enable_custom_integrations: None hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None: ) -> None:
"""Test for triggers firing with delay.""" """Test for turn_on and turn_off triggers firing."""
platform = getattr(hass.components, f"test.{DOMAIN}") entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
platform.init() hass.states.async_set(entry.entity_id, STATE_ON)
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
await hass.async_block_till_done()
ent1, ent2, ent3 = platform.ENTITIES
assert await async_setup_component( assert await async_setup_component(
hass, hass,
@ -279,7 +307,62 @@ async def test_if_fires_on_state_change_with_for(
"platform": "device", "platform": "device",
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": ent1.entity_id, "entity_id": entry.entity_id,
"type": "turned_off",
},
"action": {
"service": "test.automation",
"data_template": {
"some": "turn_off {{ trigger.%s }}"
% "}} - {{ trigger.".join(
(
"platform",
"entity_id",
"from_state.state",
"to_state.state",
"for",
)
)
},
},
},
]
},
)
await hass.async_block_till_done()
assert len(calls) == 0
hass.states.async_set(entry.entity_id, STATE_OFF)
await hass.async_block_till_done()
assert len(calls) == 1
assert (
calls[0].data["some"]
== f"turn_off device - {entry.entity_id} - on - off - None"
)
async def test_if_fires_on_state_change_with_for(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None:
"""Test for triggers firing with delay."""
entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
hass.states.async_set(entry.entity_id, STATE_ON)
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: [
{
"trigger": {
"platform": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": entry.id,
"type": "turned_off", "type": "turned_off",
"for": {"seconds": 5}, "for": {"seconds": 5},
}, },
@ -303,16 +386,16 @@ async def test_if_fires_on_state_change_with_for(
}, },
) )
await hass.async_block_till_done() await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_ON
assert len(calls) == 0 assert len(calls) == 0
hass.states.async_set(ent1.entity_id, STATE_OFF) hass.states.async_set(entry.entity_id, STATE_OFF)
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(calls) == 0 assert len(calls) == 0
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=10)) async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=10))
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(calls) == 1 assert len(calls) == 1
await hass.async_block_till_done() await hass.async_block_till_done()
assert calls[0].data["some"] == "turn_off device - {} - on - off - 0:00:05".format( assert (
ent1.entity_id calls[0].data["some"]
== f"turn_off device - {entry.entity_id} - on - off - 0:00:05"
) )

View file

@ -45,7 +45,7 @@ async def test_get_triggers(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_registry.async_get_or_create( entity_entry = entity_registry.async_get_or_create(
DOMAIN, "test", "5678", device_id=device_entry.id DOMAIN, "test", "5678", device_id=device_entry.id
) )
expected_triggers = [ expected_triggers = [
@ -54,7 +54,7 @@ async def test_get_triggers(
"domain": DOMAIN, "domain": DOMAIN,
"type": trigger, "type": trigger,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": entity_entry.id,
"metadata": {"secondary": False}, "metadata": {"secondary": False},
} }
for trigger in ["changed_states", "turned_off", "turned_on"] for trigger in ["changed_states", "turned_off", "turned_on"]
@ -88,7 +88,7 @@ async def test_get_triggers_hidden_auxiliary(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_registry.async_get_or_create( entity_entry = entity_registry.async_get_or_create(
DOMAIN, DOMAIN,
"test", "test",
"5678", "5678",
@ -102,7 +102,7 @@ async def test_get_triggers_hidden_auxiliary(
"domain": DOMAIN, "domain": DOMAIN,
"type": trigger, "type": trigger,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": entity_entry.id,
"metadata": {"secondary": True}, "metadata": {"secondary": True},
} }
for trigger in ["changed_states", "turned_off", "turned_on"] for trigger in ["changed_states", "turned_off", "turned_on"]
@ -143,8 +143,42 @@ async def test_get_trigger_capabilities(
assert capabilities == expected_capabilities assert capabilities == expected_capabilities
async def test_get_trigger_capabilities_legacy(
hass: HomeAssistant,
device_registry: dr.DeviceRegistry,
entity_registry: er.EntityRegistry,
) -> None:
"""Test we get the expected capabilities from a update trigger."""
config_entry = MockConfigEntry(domain="test", data={})
config_entry.add_to_hass(hass)
device_entry = device_registry.async_get_or_create(
config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
)
entity_registry.async_get_or_create(
DOMAIN, "test", "5678", device_id=device_entry.id
)
expected_capabilities = {
"extra_fields": [
{"name": "for", "optional": True, "type": "positive_time_period_dict"}
]
}
triggers = await async_get_device_automations(
hass, DeviceAutomationType.TRIGGER, device_entry.id
)
for trigger in triggers:
trigger["entity_id"] = entity_registry.async_get(trigger["entity_id"]).entity_id
capabilities = await async_get_device_automation_capabilities(
hass, DeviceAutomationType.TRIGGER, trigger
)
assert capabilities == expected_capabilities
async def test_if_fires_on_state_change( async def test_if_fires_on_state_change(
hass: HomeAssistant, calls: list[ServiceCall], enable_custom_integrations: None hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls: list[ServiceCall],
enable_custom_integrations: None,
) -> None: ) -> None:
"""Test for turn_on and turn_off triggers firing.""" """Test for turn_on and turn_off triggers firing."""
platform = getattr(hass.components, f"test.{DOMAIN}") platform = getattr(hass.components, f"test.{DOMAIN}")
@ -153,6 +187,8 @@ async def test_if_fires_on_state_change(
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}}) assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
await hass.async_block_till_done() await hass.async_block_till_done()
entry = entity_registry.async_get("update.update_available")
assert await async_setup_component( assert await async_setup_component(
hass, hass,
automation.DOMAIN, automation.DOMAIN,
@ -163,7 +199,7 @@ async def test_if_fires_on_state_change(
"platform": "device", "platform": "device",
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": "update.update_available", "entity_id": entry.id,
"type": "turned_on", "type": "turned_on",
}, },
"action": { "action": {
@ -232,16 +268,21 @@ async def test_if_fires_on_state_change(
) )
async def test_if_fires_on_state_change_with_for( async def test_if_fires_on_state_change_legacy(
hass: HomeAssistant, calls: list[ServiceCall], enable_custom_integrations: None hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls: list[ServiceCall],
enable_custom_integrations: None,
) -> None: ) -> None:
"""Test for triggers firing with delay.""" """Test for turn_on and turn_off triggers firing."""
platform = getattr(hass.components, f"test.{DOMAIN}") platform = getattr(hass.components, f"test.{DOMAIN}")
platform.init() platform.init()
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}}) assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
await hass.async_block_till_done() await hass.async_block_till_done()
entry = entity_registry.async_get("update.update_available")
assert await async_setup_component( assert await async_setup_component(
hass, hass,
automation.DOMAIN, automation.DOMAIN,
@ -252,7 +293,69 @@ async def test_if_fires_on_state_change_with_for(
"platform": "device", "platform": "device",
"domain": DOMAIN, "domain": DOMAIN,
"device_id": "", "device_id": "",
"entity_id": "update.update_available", "entity_id": entry.entity_id,
"type": "turned_off",
},
"action": {
"service": "test.automation",
"data_template": {
"some": "no_update {{ trigger.%s }}"
% "}} - {{ trigger.".join(
(
"platform",
"entity_id",
"from_state.state",
"to_state.state",
"for",
)
)
},
},
},
]
},
)
await hass.async_block_till_done()
state = hass.states.get("update.update_available")
assert state
assert state.state == STATE_ON
assert not calls
hass.states.async_set("update.update_available", STATE_OFF)
await hass.async_block_till_done()
assert len(calls) == 1
assert (
calls[0].data["some"]
== "no_update device - update.update_available - on - off - None"
)
async def test_if_fires_on_state_change_with_for(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls: list[ServiceCall],
enable_custom_integrations: None,
) -> None:
"""Test for triggers firing with delay."""
platform = getattr(hass.components, f"test.{DOMAIN}")
platform.init()
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
await hass.async_block_till_done()
entry = entity_registry.async_get("update.update_available")
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: [
{
"trigger": {
"platform": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": entry.id,
"type": "turned_off", "type": "turned_off",
"for": {"seconds": 5}, "for": {"seconds": 5},
}, },

View file

@ -71,7 +71,7 @@ async def test_get_triggers(hass: HomeAssistant, wemo_entity) -> None:
{ {
CONF_DEVICE_ID: wemo_entity.device_id, CONF_DEVICE_ID: wemo_entity.device_id,
CONF_DOMAIN: Platform.SWITCH, CONF_DOMAIN: Platform.SWITCH,
CONF_ENTITY_ID: wemo_entity.entity_id, CONF_ENTITY_ID: wemo_entity.id,
CONF_PLATFORM: "device", CONF_PLATFORM: "device",
CONF_TYPE: "changed_states", CONF_TYPE: "changed_states",
"metadata": {"secondary": False}, "metadata": {"secondary": False},
@ -79,7 +79,7 @@ async def test_get_triggers(hass: HomeAssistant, wemo_entity) -> None:
{ {
CONF_DEVICE_ID: wemo_entity.device_id, CONF_DEVICE_ID: wemo_entity.device_id,
CONF_DOMAIN: Platform.SWITCH, CONF_DOMAIN: Platform.SWITCH,
CONF_ENTITY_ID: wemo_entity.entity_id, CONF_ENTITY_ID: wemo_entity.id,
CONF_PLATFORM: "device", CONF_PLATFORM: "device",
CONF_TYPE: "turned_off", CONF_TYPE: "turned_off",
"metadata": {"secondary": False}, "metadata": {"secondary": False},
@ -87,7 +87,7 @@ async def test_get_triggers(hass: HomeAssistant, wemo_entity) -> None:
{ {
CONF_DEVICE_ID: wemo_entity.device_id, CONF_DEVICE_ID: wemo_entity.device_id,
CONF_DOMAIN: Platform.SWITCH, CONF_DOMAIN: Platform.SWITCH,
CONF_ENTITY_ID: wemo_entity.entity_id, CONF_ENTITY_ID: wemo_entity.id,
CONF_PLATFORM: "device", CONF_PLATFORM: "device",
CONF_TYPE: "turned_on", CONF_TYPE: "turned_on",
"metadata": {"secondary": False}, "metadata": {"secondary": False},

View file

@ -14,7 +14,7 @@ from homeassistant.components.device_automation import DeviceAutomationType
from homeassistant.components.zha import DOMAIN from homeassistant.components.zha import DOMAIN
from homeassistant.const import Platform from homeassistant.const import Platform
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr 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 SIG_EP_INPUT, SIG_EP_OUTPUT, SIG_EP_TYPE from .conftest import SIG_EP_INPUT, SIG_EP_OUTPUT, SIG_EP_TYPE
@ -164,6 +164,8 @@ async def test_get_inovelli_actions(hass: HomeAssistant, device_inovelli) -> Non
inovelli_reg_device = ha_device_registry.async_get_device( inovelli_reg_device = ha_device_registry.async_get_device(
{(DOMAIN, inovelli_ieee_address)} {(DOMAIN, inovelli_ieee_address)}
) )
ha_entity_registry = er.async_get(hass)
inovelli_light = ha_entity_registry.async_get("light.inovelli_vzm31_sn_light")
actions = await async_get_device_automations( actions = await async_get_device_automations(
hass, DeviceAutomationType.ACTION, inovelli_reg_device.id hass, DeviceAutomationType.ACTION, inovelli_reg_device.id
@ -192,21 +194,21 @@ async def test_get_inovelli_actions(hass: HomeAssistant, device_inovelli) -> Non
{ {
"device_id": inovelli_reg_device.id, "device_id": inovelli_reg_device.id,
"domain": Platform.LIGHT, "domain": Platform.LIGHT,
"entity_id": "light.inovelli_vzm31_sn_light", "entity_id": inovelli_light.id,
"metadata": {"secondary": False}, "metadata": {"secondary": False},
"type": "turn_off", "type": "turn_off",
}, },
{ {
"device_id": inovelli_reg_device.id, "device_id": inovelli_reg_device.id,
"domain": Platform.LIGHT, "domain": Platform.LIGHT,
"entity_id": "light.inovelli_vzm31_sn_light", "entity_id": inovelli_light.id,
"metadata": {"secondary": False}, "metadata": {"secondary": False},
"type": "turn_on", "type": "turn_on",
}, },
{ {
"device_id": inovelli_reg_device.id, "device_id": inovelli_reg_device.id,
"domain": Platform.LIGHT, "domain": Platform.LIGHT,
"entity_id": "light.inovelli_vzm31_sn_light", "entity_id": inovelli_light.id,
"metadata": {"secondary": False}, "metadata": {"secondary": False},
"type": "toggle", "type": "toggle",
}, },