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,
CONF_DEVICE_ID,
CONF_DOMAIN,
CONF_ENTITY_ID,
CONF_PLATFORM,
)
from homeassistant.core import HomeAssistant, callback
@ -340,6 +341,21 @@ def async_get_entity_registry_entry_or_raise(
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(
func: Callable[[HomeAssistant, ActiveConnection, dict[str, Any]], Awaitable[None]]
) -> Callable[

View file

@ -23,7 +23,7 @@ ENTITY_TRIGGERS = [
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.Optional(CONF_FOR): cv.positive_time_period_dict,
}
@ -73,7 +73,7 @@ async def _async_get_automations(
{
**template,
"device_id": device_id,
"entity_id": entry.entity_id,
"entity_id": entry.id,
"domain": domain,
}
for template in automation_templates

View file

@ -25,6 +25,8 @@ STATIC_VALIDATOR = {
DeviceAutomationType.TRIGGER: "TRIGGER_SCHEMA",
}
TOGGLE_ENTITY_DOMAINS = {"fan", "humidifier", "light", "remote", "switch"}
async def async_validate_device_automation_config(
hass: HomeAssistant,
@ -43,6 +45,16 @@ async def async_validate_device_automation_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
# config entry is loaded
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(
{
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),
}
)
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.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(
{
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.Optional(CONF_FOR): cv.positive_time_period_dict,
}
@ -196,7 +196,7 @@ async def _async_get_automations(
{
**template,
"device_id": device_id,
"entity_id": entry.entity_id,
"entity_id": entry.id,
"domain": domain,
}
for template in automation_templates

View file

@ -3,7 +3,10 @@ from __future__ import annotations
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 (
ATTR_ENTITY_ID,
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})
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(

View file

@ -3,7 +3,11 @@ from __future__ import annotations
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 (
ATTR_ENTITY_ID,
CONF_DEVICE_ID,
@ -37,9 +41,9 @@ TYPE_BRIGHTNESS_INCREASE = "brightness_increase"
TYPE_BRIGHTNESS_DECREASE = "brightness_decrease"
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_TYPE): vol.In(
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(
hass: HomeAssistant,
config: ConfigType,
@ -126,13 +137,15 @@ async def async_get_action_capabilities(
if config[CONF_TYPE] != toggle_entity.CONF_TURN_ON:
return {}
entry = async_get_entity_registry_entry_or_raise(hass, config[CONF_ENTITY_ID])
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:
supported_color_modes = None
try:
supported_features = get_supported_features(hass, config[ATTR_ENTITY_ID])
supported_features = get_supported_features(hass, entry.entity_id)
except HomeAssistantError:
supported_features = 0

View file

@ -3,7 +3,10 @@ from __future__ import annotations
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.core import Context, HomeAssistant
from homeassistant.helpers.typing import ConfigType, TemplateVarsType
@ -12,7 +15,14 @@ from . import DOMAIN
# 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(

View file

@ -3,7 +3,10 @@ from __future__ import annotations
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.core import Context, HomeAssistant
from homeassistant.helpers.typing import ConfigType, TemplateVarsType
@ -12,7 +15,14 @@ from . import DOMAIN
# 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(

View file

@ -114,7 +114,7 @@ async def test_websocket_get_actions(
config_entry_id=config_entry.entry_id,
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
)
expected_actions = [
@ -122,21 +122,21 @@ async def test_websocket_get_actions(
"domain": "fake_integration",
"type": "turn_off",
"device_id": device_entry.id,
"entity_id": "fake_integration.test_5678",
"entity_id": entity_entry.id,
"metadata": {"secondary": False},
},
{
"domain": "fake_integration",
"type": "turn_on",
"device_id": device_entry.id,
"entity_id": "fake_integration.test_5678",
"entity_id": entity_entry.id,
"metadata": {"secondary": False},
},
{
"domain": "fake_integration",
"type": "toggle",
"device_id": device_entry.id,
"entity_id": "fake_integration.test_5678",
"entity_id": entity_entry.id,
"metadata": {"secondary": False},
},
]
@ -169,7 +169,7 @@ async def test_websocket_get_conditions(
config_entry_id=config_entry.entry_id,
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
)
expected_conditions = [
@ -178,7 +178,7 @@ async def test_websocket_get_conditions(
"domain": "fake_integration",
"type": "is_off",
"device_id": device_entry.id,
"entity_id": "fake_integration.test_5678",
"entity_id": entity_entry.id,
"metadata": {"secondary": False},
},
{
@ -186,7 +186,7 @@ async def test_websocket_get_conditions(
"domain": "fake_integration",
"type": "is_on",
"device_id": device_entry.id,
"entity_id": "fake_integration.test_5678",
"entity_id": entity_entry.id,
"metadata": {"secondary": False},
},
]
@ -223,7 +223,7 @@ async def test_websocket_get_triggers(
config_entry_id=config_entry.entry_id,
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
)
expected_triggers = [
@ -232,7 +232,7 @@ async def test_websocket_get_triggers(
"domain": "fake_integration",
"type": "changed_states",
"device_id": device_entry.id,
"entity_id": "fake_integration.test_5678",
"entity_id": entity_entry.id,
"metadata": {"secondary": False},
},
{
@ -240,7 +240,7 @@ async def test_websocket_get_triggers(
"domain": "fake_integration",
"type": "turned_off",
"device_id": device_entry.id,
"entity_id": "fake_integration.test_5678",
"entity_id": entity_entry.id,
"metadata": {"secondary": False},
},
{
@ -248,7 +248,7 @@ async def test_websocket_get_triggers(
"domain": "fake_integration",
"type": "turned_on",
"device_id": device_entry.id,
"entity_id": "fake_integration.test_5678",
"entity_id": entity_entry.id,
"metadata": {"secondary": False},
},
]

View file

@ -35,7 +35,7 @@ async def test_get_actions(
config_entry_id=config_entry.entry_id,
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
)
expected_actions = []
@ -44,7 +44,7 @@ async def test_get_actions(
"domain": DOMAIN,
"type": action,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"entity_id": entity_entry.id,
"metadata": {"secondary": False},
}
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,
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",
@ -92,7 +92,7 @@ async def test_get_actions_hidden_auxiliary(
"domain": DOMAIN,
"type": action,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"entity_id": entity_entry.id,
"metadata": {"secondary": True},
}
for action in ["turn_on", "turn_off", "toggle"]
@ -103,8 +103,10 @@ async def test_get_actions_hidden_auxiliary(
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."""
entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
assert await async_setup_component(
hass,
automation.DOMAIN,
@ -118,7 +120,7 @@ async def test_action(hass: HomeAssistant) -> None:
"action": {
"domain": DOMAIN,
"device_id": "abcdefgh",
"entity_id": "fan.entity",
"entity_id": entry.id,
"type": "turn_off",
},
},
@ -130,7 +132,7 @@ async def test_action(hass: HomeAssistant) -> None:
"action": {
"domain": DOMAIN,
"device_id": "abcdefgh",
"entity_id": "fan.entity",
"entity_id": entry.id,
"type": "turn_on",
},
},
@ -142,7 +144,7 @@ async def test_action(hass: HomeAssistant) -> None:
"action": {
"domain": DOMAIN,
"device_id": "abcdefgh",
"entity_id": "fan.entity",
"entity_id": entry.id,
"type": "toggle",
},
},
@ -171,3 +173,37 @@ async def test_action(hass: HomeAssistant) -> None:
assert len(turn_off_calls) == 1
assert len(turn_on_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,
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
)
expected_triggers = [
@ -55,7 +55,7 @@ async def test_get_triggers(
"domain": DOMAIN,
"type": trigger,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"entity_id": entity_entry.id,
"metadata": {"secondary": False},
}
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,
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",
@ -103,7 +103,7 @@ async def test_get_triggers_hidden_auxiliary(
"domain": DOMAIN,
"type": trigger,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"entity_id": entity_entry.id,
"metadata": {"secondary": True},
}
for trigger in ["turned_off", "turned_on", "changed_states"]
@ -144,9 +144,44 @@ async def test_get_trigger_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."""
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(
hass,
@ -158,7 +193,7 @@ async def test_if_fires_on_state_change(hass: HomeAssistant, calls) -> None:
"platform": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": "fan.entity",
"entity_id": entry.id,
"type": "turned_on",
},
"action": {
@ -180,7 +215,7 @@ async def test_if_fires_on_state_change(hass: HomeAssistant, calls) -> None:
"platform": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": "fan.entity",
"entity_id": entry.id,
"type": "turned_off",
},
"action": {
@ -202,7 +237,7 @@ async def test_if_fires_on_state_change(hass: HomeAssistant, calls) -> None:
"platform": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": "fan.entity",
"entity_id": entry.id,
"type": "changed_states",
},
"action": {
@ -224,28 +259,31 @@ async def test_if_fires_on_state_change(hass: HomeAssistant, calls) -> None:
)
# 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()
assert len(calls) == 2
assert {calls[0].data["some"], calls[1].data["some"]} == {
"turn_on - device - fan.entity - off - on - None",
"turn_on_or_off - device - fan.entity - off - on - None",
f"turn_on - device - {entry.entity_id} - off - on - None",
f"turn_on_or_off - device - {entry.entity_id} - off - on - None",
}
# 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()
assert len(calls) == 4
assert {calls[2].data["some"], calls[3].data["some"]} == {
"turn_off - device - fan.entity - on - off - None",
"turn_on_or_off - device - fan.entity - on - off - None",
f"turn_off - device - {entry.entity_id} - 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:
"""Test for triggers firing with delay."""
entity_id = "fan.entity"
hass.states.async_set(entity_id, STATE_ON)
async def test_if_fires_on_state_change_legacy(
hass: HomeAssistant, entity_registry: er.EntityRegistry, calls
) -> None:
"""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(
hass,
@ -257,7 +295,56 @@ async def test_if_fires_on_state_change_with_for(hass: HomeAssistant, calls) ->
"platform": "device",
"domain": DOMAIN,
"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",
"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()
assert hass.states.get(entity_id).state == STATE_ON
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()
assert len(calls) == 0
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
await hass.async_block_till_done()
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,
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",
@ -65,7 +65,8 @@ async def test_get_actions(
f"{DOMAIN}.test_5678", "attributes", {"supported_features": features_state}
)
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 += [
{
"domain": DOMAIN,
@ -76,6 +77,16 @@ async def test_get_actions(
}
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 += [
{
"domain": DOMAIN,
@ -115,7 +126,7 @@ async def test_get_actions_hidden_auxiliary(
config_entry_id=config_entry.entry_id,
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",
@ -124,6 +135,8 @@ async def test_get_actions_hidden_auxiliary(
hidden_by=hidden_by,
supported_features=0,
)
basic_action_types = ["set_humidity"]
toggle_action_types = ["turn_on", "turn_off", "toggle"]
expected_actions = []
expected_actions += [
{
@ -133,7 +146,17 @@ async def test_get_actions_hidden_auxiliary(
"entity_id": f"{DOMAIN}.test_5678",
"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(
hass, DeviceAutomationType.ACTION, device_entry.id
@ -141,10 +164,12 @@ async def test_get_actions_hidden_auxiliary(
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."""
entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
hass.states.async_set(
"humidifier.entity",
entry.entity_id,
STATE_ON,
{const.ATTR_AVAILABLE_MODES: [const.MODE_HOME, const.MODE_AWAY]},
)
@ -162,7 +187,7 @@ async def test_action(hass: HomeAssistant) -> None:
"action": {
"domain": DOMAIN,
"device_id": "abcdefgh",
"entity_id": "humidifier.entity",
"entity_id": entry.id,
"type": "turn_off",
},
},
@ -174,7 +199,7 @@ async def test_action(hass: HomeAssistant) -> None:
"action": {
"domain": DOMAIN,
"device_id": "abcdefgh",
"entity_id": "humidifier.entity",
"entity_id": entry.id,
"type": "turn_on",
},
},
@ -183,7 +208,7 @@ async def test_action(hass: HomeAssistant) -> None:
"action": {
"domain": DOMAIN,
"device_id": "abcdefgh",
"entity_id": "humidifier.entity",
"entity_id": entry.id,
"type": "toggle",
},
},
@ -195,7 +220,7 @@ async def test_action(hass: HomeAssistant) -> None:
"action": {
"domain": DOMAIN,
"device_id": "abcdefgh",
"entity_id": "humidifier.entity",
"entity_id": entry.entity_id,
"type": "set_humidity",
"humidity": 35,
},
@ -208,7 +233,7 @@ async def test_action(hass: HomeAssistant) -> None:
"action": {
"domain": DOMAIN,
"device_id": "abcdefgh",
"entity_id": "humidifier.entity",
"entity_id": entry.entity_id,
"type": "set_mode",
"mode": const.MODE_AWAY,
},
@ -269,6 +294,67 @@ async def test_action(hass: HomeAssistant) -> None:
assert len(turn_off_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(
(
@ -380,7 +466,7 @@ async def test_capabilities(
config_entry_id=config_entry.entry_id,
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",
@ -399,7 +485,7 @@ async def test_capabilities(
{
"domain": DOMAIN,
"device_id": "abcdefgh",
"entity_id": f"{DOMAIN}.test_5678",
"entity_id": entity_entry.entity_id,
"type": action,
},
)
@ -418,7 +504,6 @@ async def test_capabilities(
("action", "capability_name", "extra"),
[
("set_humidity", "humidity", {"type": "integer"}),
("set_mode", "mode", {"type": "select", "options": []}),
],
)
async def test_capabilities_missing_entity(

View file

@ -59,7 +59,7 @@ async def test_get_conditions(
config_entry_id=config_entry.entry_id,
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",
@ -78,7 +78,7 @@ async def test_get_conditions(
"domain": DOMAIN,
"type": condition,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"entity_id": entity_entry.id,
"metadata": {"secondary": False},
}
for condition in basic_condition_types
@ -89,7 +89,7 @@ async def test_get_conditions(
"domain": DOMAIN,
"type": condition,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"entity_id": entity_entry.entity_id,
"metadata": {"secondary": False},
}
for condition in expected_condition_types
@ -123,7 +123,7 @@ async def test_get_conditions_hidden_auxiliary(
config_entry_id=config_entry.entry_id,
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",
@ -137,7 +137,7 @@ async def test_get_conditions_hidden_auxiliary(
"domain": DOMAIN,
"type": condition,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"entity_id": entity_entry.id,
"metadata": {"secondary": True},
}
for condition in ["is_off", "is_on"]
@ -148,9 +148,13 @@ async def test_get_conditions_hidden_auxiliary(
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."""
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(
hass,
@ -164,7 +168,7 @@ async def test_if_state(hass: HomeAssistant, calls) -> None:
"condition": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": "humidifier.entity",
"entity_id": entry.id,
"type": "is_on",
}
],
@ -183,7 +187,7 @@ async def test_if_state(hass: HomeAssistant, calls) -> None:
"condition": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": "humidifier.entity",
"entity_id": entry.id,
"type": "is_off",
}
],
@ -202,7 +206,7 @@ async def test_if_state(hass: HomeAssistant, calls) -> None:
"condition": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": "humidifier.entity",
"entity_id": entry.entity_id,
"type": "is_mode",
"mode": "away",
}
@ -218,7 +222,6 @@ async def test_if_state(hass: HomeAssistant, calls) -> None:
},
)
await hass.async_block_till_done()
assert hass.states.get("humidifier.entity").state == STATE_ON
assert len(calls) == 0
hass.bus.async_fire("test_event1")
@ -227,14 +230,14 @@ async def test_if_state(hass: HomeAssistant, calls) -> None:
assert len(calls) == 1
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_event2")
await hass.async_block_till_done()
assert len(calls) == 2
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")
await hass.async_block_till_done()
@ -242,7 +245,7 @@ async def test_if_state(hass: HomeAssistant, calls) -> None:
assert len(calls) == 3
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
hass.bus.async_fire("test_event3")
@ -386,7 +389,7 @@ async def test_capabilities(
config_entry_id=config_entry.entry_id,
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",
@ -395,7 +398,7 @@ async def test_capabilities(
)
if set_state:
hass.states.async_set(
f"{DOMAIN}.test_5678",
entity_entry.entity_id,
STATE_ON,
capabilities_state,
)
@ -405,7 +408,7 @@ async def test_capabilities(
{
"domain": DOMAIN,
"device_id": "abcdefgh",
"entity_id": f"{DOMAIN}.test_5678",
"entity_id": entity_entry.entity_id,
"type": condition,
},
)

View file

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

View file

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

View file

@ -46,7 +46,7 @@ async def test_get_conditions(
config_entry_id=config_entry.entry_id,
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
)
expected_conditions = [
@ -55,7 +55,7 @@ async def test_get_conditions(
"domain": DOMAIN,
"type": condition,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"entity_id": entity_entry.id,
"metadata": {"secondary": False},
}
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,
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",
@ -103,7 +103,7 @@ async def test_get_conditions_hidden_auxiliary(
"domain": DOMAIN,
"type": condition,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"entity_id": entity_entry.id,
"metadata": {"secondary": True},
}
for condition in ["is_off", "is_on"]
@ -144,17 +144,49 @@ async def test_get_condition_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(
hass: HomeAssistant, calls, enable_custom_integrations: None
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None:
"""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()
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
await hass.async_block_till_done()
ent1, ent2, ent3 = platform.ENTITIES
hass.states.async_set(entry.entity_id, STATE_ON)
assert await async_setup_component(
hass,
@ -168,7 +200,7 @@ async def test_if_state(
"condition": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": ent1.entity_id,
"entity_id": entry.id,
"type": "is_on",
}
],
@ -187,7 +219,7 @@ async def test_if_state(
"condition": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": ent1.entity_id,
"entity_id": entry.id,
"type": "is_off",
}
],
@ -203,7 +235,6 @@ async def test_if_state(
},
)
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")
@ -212,7 +243,7 @@ async def test_if_state(
assert len(calls) == 1
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_event2")
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"
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(
hass: HomeAssistant, calls, enable_custom_integrations: None
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None:
"""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()
point2 = point1 + timedelta(seconds=10)
point3 = point2 + timedelta(seconds=10)
@ -248,7 +334,7 @@ async def test_if_fires_on_for_condition(
"condition": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": ent1.entity_id,
"entity_id": entry.id,
"type": "is_off",
"for": {"seconds": 5},
},
@ -266,7 +352,6 @@ async def test_if_fires_on_for_condition(
},
)
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")
@ -279,7 +364,7 @@ async def test_if_fires_on_for_condition(
await hass.async_block_till_done()
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")
await hass.async_block_till_done()
assert len(calls) == 0

View file

@ -7,7 +7,7 @@ from pytest_unordered import unordered
import homeassistant.components.automation as automation
from homeassistant.components.device_automation import DeviceAutomationType
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.helpers import device_registry as dr, entity_registry as er
from homeassistant.helpers.entity_registry import RegistryEntryHider
@ -46,7 +46,7 @@ async def test_get_triggers(
config_entry_id=config_entry.entry_id,
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
)
expected_triggers = [
@ -55,7 +55,7 @@ async def test_get_triggers(
"domain": DOMAIN,
"type": trigger,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"entity_id": entity_entry.id,
"metadata": {"secondary": False},
}
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,
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",
@ -103,7 +103,7 @@ async def test_get_triggers_hidden_auxiliary(
"domain": DOMAIN,
"type": trigger,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"entity_id": entity_entry.id,
"metadata": {"secondary": True},
}
for trigger in ["changed_states", "turned_off", "turned_on"]
@ -144,19 +144,47 @@ async def test_get_trigger_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(
hass: HomeAssistant, calls, enable_custom_integrations: None
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None:
"""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()
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
hass.states.async_set(entry.entity_id, STATE_ON)
assert await async_setup_component(
hass,
@ -168,7 +196,7 @@ async def test_if_fires_on_state_change(
"platform": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": ent1.entity_id,
"entity_id": entry.id,
"type": "turned_on",
},
"action": {
@ -192,7 +220,7 @@ async def test_if_fires_on_state_change(
"platform": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": ent1.entity_id,
"entity_id": entry.id,
"type": "turned_off",
},
"action": {
@ -216,7 +244,7 @@ async def test_if_fires_on_state_change(
"platform": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": ent1.entity_id,
"entity_id": entry.id,
"type": "changed_states",
},
"action": {
@ -239,39 +267,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
hass.states.async_set(ent1.entity_id, STATE_OFF)
hass.states.async_set(entry.entity_id, STATE_OFF)
await hass.async_block_till_done()
assert len(calls) == 2
assert {calls[0].data["some"], calls[1].data["some"]} == {
f"turn_off device - {ent1.entity_id} - on - off - None",
f"turn_on_or_off device - {ent1.entity_id} - on - off - None",
f"turn_off device - {entry.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()
assert len(calls) == 4
assert {calls[2].data["some"], calls[3].data["some"]} == {
f"turn_on device - {ent1.entity_id} - off - on - None",
f"turn_on_or_off device - {ent1.entity_id} - off - on - None",
f"turn_on device - {entry.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(
hass: HomeAssistant, calls, enable_custom_integrations: None
async def test_if_fires_on_state_change_legacy(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None:
"""Test for triggers firing with delay."""
platform = getattr(hass.components, f"test.{DOMAIN}")
"""Test for turn_on and turn_off triggers firing."""
entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
platform.init()
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
hass.states.async_set(entry.entity_id, STATE_ON)
assert await async_setup_component(
hass,
@ -283,7 +307,61 @@ async def test_if_fires_on_state_change_with_for(
"platform": "device",
"domain": DOMAIN,
"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",
"for": {"seconds": 5},
},
@ -307,16 +385,16 @@ async def test_if_fires_on_state_change_with_for(
},
)
await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_ON
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()
assert len(calls) == 0
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=10))
await hass.async_block_till_done()
assert len(calls) == 1
await hass.async_block_till_done()
assert calls[0].data["some"] == "turn_off device - {} - on - off - 0:00:05".format(
ent1.entity_id
assert (
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
)
entity_trigger_types = {
"changed_states",
}
trigger_types = {
"buffering",
"changed_states",
"idle",
"paused",
"playing",
@ -80,17 +78,6 @@ async def test_get_triggers(
}
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(
hass, DeviceAutomationType.TRIGGER, device_entry.id
)
@ -128,11 +115,9 @@ async def test_get_triggers_hidden_auxiliary(
entity_category=entity_category,
hidden_by=hidden_by,
)
entity_trigger_types = {
"changed_states",
}
trigger_types = {
"buffering",
"changed_states",
"idle",
"paused",
"playing",
@ -150,17 +135,6 @@ async def test_get_triggers_hidden_auxiliary(
}
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(
hass, DeviceAutomationType.TRIGGER, device_entry.id
)
@ -263,9 +237,7 @@ async def test_if_fires_on_state_change(
"platform": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": entry.entity_id
if trigger == "changed_states"
else entry.id,
"entity_id": entry.id,
"type": trigger,
},
"action": {

View file

@ -5,7 +5,7 @@ from pytest_unordered import unordered
import homeassistant.components.automation as automation
from homeassistant.components.device_automation import DeviceAutomationType
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.helpers import device_registry as dr, entity_registry as er
from homeassistant.helpers.entity_registry import RegistryEntryHider
@ -41,7 +41,7 @@ async def test_get_actions(
config_entry_id=config_entry.entry_id,
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
)
expected_actions = [
@ -49,7 +49,7 @@ async def test_get_actions(
"domain": DOMAIN,
"type": action,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"entity_id": entity_entry.id,
"metadata": {"secondary": False},
}
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,
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",
@ -97,7 +97,7 @@ async def test_get_actions_hidden_auxiliary(
"domain": DOMAIN,
"type": action,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"entity_id": entity_entry.id,
"metadata": {"secondary": True},
}
for action in ["turn_off", "turn_on", "toggle"]
@ -109,16 +109,13 @@ async def test_get_actions_hidden_auxiliary(
async def test_action(
hass: HomeAssistant, calls, enable_custom_integrations: None
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None:
"""Test for turn_on and turn_off actions."""
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()
ent1, ent2, ent3 = platform.ENTITIES
entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
assert await async_setup_component(
hass,
@ -126,29 +123,29 @@ async def test_action(
{
automation.DOMAIN: [
{
"trigger": {"platform": "event", "event_type": "test_event1"},
"trigger": {"platform": "event", "event_type": "test_off"},
"action": {
"domain": DOMAIN,
"device_id": "",
"entity_id": ent1.entity_id,
"entity_id": entry.id,
"type": "turn_off",
},
},
{
"trigger": {"platform": "event", "event_type": "test_event2"},
"trigger": {"platform": "event", "event_type": "test_on"},
"action": {
"domain": DOMAIN,
"device_id": "",
"entity_id": ent1.entity_id,
"entity_id": entry.id,
"type": "turn_on",
},
},
{
"trigger": {"platform": "event", "event_type": "test_event3"},
"trigger": {"platform": "event", "event_type": "test_toggle"},
"action": {
"domain": DOMAIN,
"device_id": "",
"entity_id": ent1.entity_id,
"entity_id": entry.id,
"type": "toggle",
},
},
@ -156,29 +153,58 @@ async def test_action(
},
)
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")
await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_OFF
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_event1")
hass.bus.async_fire("test_toggle")
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()
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()
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()
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
from homeassistant.components.device_automation import DeviceAutomationType
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.helpers import device_registry as dr, entity_registry as er
from homeassistant.helpers.entity_registry import RegistryEntryHider
@ -46,7 +46,7 @@ async def test_get_conditions(
config_entry_id=config_entry.entry_id,
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
)
expected_conditions = [
@ -55,7 +55,7 @@ async def test_get_conditions(
"domain": DOMAIN,
"type": condition,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"entity_id": entity_entry.id,
"metadata": {"secondary": False},
}
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,
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",
@ -103,7 +103,7 @@ async def test_get_conditions_hidden_auxiliary(
"domain": DOMAIN,
"type": condition,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"entity_id": entity_entry.id,
"metadata": {"secondary": True},
}
for condition in ["is_off", "is_on"]
@ -144,17 +144,49 @@ async def test_get_condition_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(
hass: HomeAssistant, calls, enable_custom_integrations: None
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None:
"""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()
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
await hass.async_block_till_done()
ent1, ent2, ent3 = platform.ENTITIES
hass.states.async_set(entry.entity_id, STATE_ON)
assert await async_setup_component(
hass,
@ -168,7 +200,7 @@ async def test_if_state(
"condition": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": ent1.entity_id,
"entity_id": entry.id,
"type": "is_on",
}
],
@ -187,7 +219,7 @@ async def test_if_state(
"condition": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": ent1.entity_id,
"entity_id": entry.id,
"type": "is_off",
}
],
@ -203,7 +235,6 @@ async def test_if_state(
},
)
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")
@ -212,7 +243,7 @@ async def test_if_state(
assert len(calls) == 1
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_event2")
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"
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(
hass: HomeAssistant, calls, enable_custom_integrations: None
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None:
"""Test for firing if condition is on with delay."""
point1 = dt_util.utcnow()
point2 = point1 + 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()
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
await hass.async_block_till_done()
ent1, ent2, ent3 = platform.ENTITIES
hass.states.async_set(entry.entity_id, STATE_ON)
with freeze_time(point1) as freezer:
assert await async_setup_component(
@ -248,7 +326,7 @@ async def test_if_fires_on_for_condition(
"condition": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": ent1.entity_id,
"entity_id": entry.id,
"type": "is_off",
"for": {"seconds": 5},
},
@ -266,7 +344,6 @@ async def test_if_fires_on_for_condition(
},
)
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")
@ -279,7 +356,7 @@ async def test_if_fires_on_for_condition(
await hass.async_block_till_done()
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")
await hass.async_block_till_done()
assert len(calls) == 0

View file

@ -7,7 +7,7 @@ from pytest_unordered import unordered
import homeassistant.components.automation as automation
from homeassistant.components.device_automation import DeviceAutomationType
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.helpers import device_registry as dr, entity_registry as er
from homeassistant.helpers.entity_registry import RegistryEntryHider
@ -46,7 +46,7 @@ async def test_get_triggers(
config_entry_id=config_entry.entry_id,
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
)
expected_triggers = [
@ -55,7 +55,7 @@ async def test_get_triggers(
"domain": DOMAIN,
"type": trigger,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"entity_id": entity_entry.id,
"metadata": {"secondary": False},
}
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,
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",
@ -103,7 +103,7 @@ async def test_get_triggers_hidden_auxiliary(
"domain": DOMAIN,
"type": trigger,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"entity_id": entity_entry.id,
"metadata": {"secondary": True},
}
for trigger in ["changed_states", "turned_off", "turned_on"]
@ -144,17 +144,47 @@ async def test_get_trigger_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(
hass: HomeAssistant, calls, enable_custom_integrations: None
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None:
"""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()
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
await hass.async_block_till_done()
ent1, ent2, ent3 = platform.ENTITIES
hass.states.async_set(entry.entity_id, STATE_ON)
assert await async_setup_component(
hass,
@ -166,7 +196,7 @@ async def test_if_fires_on_state_change(
"platform": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": ent1.entity_id,
"entity_id": entry.id,
"type": "turned_on",
},
"action": {
@ -190,7 +220,7 @@ async def test_if_fires_on_state_change(
"platform": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": ent1.entity_id,
"entity_id": entry.id,
"type": "turned_off",
},
"action": {
@ -214,7 +244,7 @@ async def test_if_fires_on_state_change(
"platform": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": ent1.entity_id,
"entity_id": entry.id,
"type": "changed_states",
},
"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
hass.states.async_set(ent1.entity_id, STATE_OFF)
hass.states.async_set(entry.entity_id, STATE_OFF)
await hass.async_block_till_done()
assert len(calls) == 2
assert {calls[0].data["some"], calls[1].data["some"]} == {
f"turn_off device - {ent1.entity_id} - on - off - None",
f"turn_on_or_off device - {ent1.entity_id} - on - off - None",
f"turn_off device - {entry.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()
assert len(calls) == 4
assert {calls[2].data["some"], calls[3].data["some"]} == {
f"turn_on device - {ent1.entity_id} - off - on - None",
f"turn_on_or_off device - {ent1.entity_id} - off - on - None",
f"turn_on device - {entry.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(
hass: HomeAssistant, calls, enable_custom_integrations: None
async def test_if_fires_on_state_change_legacy(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None:
"""Test for triggers firing with delay."""
platform = getattr(hass.components, f"test.{DOMAIN}")
"""Test for turn_on and turn_off triggers firing."""
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
hass.states.async_set(entry.entity_id, STATE_ON)
assert await async_setup_component(
hass,
@ -279,7 +306,61 @@ async def test_if_fires_on_state_change_with_for(
"platform": "device",
"domain": DOMAIN,
"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",
"for": {"seconds": 5},
},
@ -303,16 +384,16 @@ async def test_if_fires_on_state_change_with_for(
},
)
await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_ON
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()
assert len(calls) == 0
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=10))
await hass.async_block_till_done()
assert len(calls) == 1
await hass.async_block_till_done()
assert calls[0].data["some"] == "turn_off device - {} - on - off - 0:00:05".format(
ent1.entity_id
assert (
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
from homeassistant.components.device_automation import DeviceAutomationType
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.helpers import device_registry as dr, entity_registry as er
from homeassistant.helpers.entity_registry import RegistryEntryHider
@ -41,7 +41,7 @@ async def test_get_actions(
config_entry_id=config_entry.entry_id,
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
)
expected_actions = []
@ -50,7 +50,7 @@ async def test_get_actions(
"domain": DOMAIN,
"type": action,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"entity_id": entity_entry.id,
"metadata": {"secondary": False},
}
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,
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",
@ -98,7 +98,7 @@ async def test_get_actions_hidden_auxiliary(
"domain": DOMAIN,
"type": action,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"entity_id": entity_entry.id,
"metadata": {"secondary": True},
}
for action in ["turn_off", "turn_on", "toggle"]
@ -110,16 +110,13 @@ async def test_get_actions_hidden_auxiliary(
async def test_action(
hass: HomeAssistant, calls, enable_custom_integrations: None
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None:
"""Test for turn_on and turn_off actions."""
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()
ent1, ent2, ent3 = platform.ENTITIES
entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678")
assert await async_setup_component(
hass,
@ -127,29 +124,29 @@ async def test_action(
{
automation.DOMAIN: [
{
"trigger": {"platform": "event", "event_type": "test_event1"},
"trigger": {"platform": "event", "event_type": "test_off"},
"action": {
"domain": DOMAIN,
"device_id": "",
"entity_id": ent1.entity_id,
"entity_id": entry.id,
"type": "turn_off",
},
},
{
"trigger": {"platform": "event", "event_type": "test_event2"},
"trigger": {"platform": "event", "event_type": "test_on"},
"action": {
"domain": DOMAIN,
"device_id": "",
"entity_id": ent1.entity_id,
"entity_id": entry.id,
"type": "turn_on",
},
},
{
"trigger": {"platform": "event", "event_type": "test_event3"},
"trigger": {"platform": "event", "event_type": "test_toggle"},
"action": {
"domain": DOMAIN,
"device_id": "",
"entity_id": ent1.entity_id,
"entity_id": entry.id,
"type": "toggle",
},
},
@ -157,29 +154,58 @@ async def test_action(
},
)
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")
await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_OFF
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_event1")
hass.bus.async_fire("test_toggle")
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()
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()
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()
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
from homeassistant.components.device_automation import DeviceAutomationType
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.helpers import device_registry as dr, entity_registry as er
from homeassistant.helpers.entity_registry import RegistryEntryHider
@ -46,7 +46,7 @@ async def test_get_conditions(
config_entry_id=config_entry.entry_id,
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
)
expected_conditions = [
@ -55,7 +55,7 @@ async def test_get_conditions(
"domain": DOMAIN,
"type": condition,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"entity_id": entity_entry.id,
"metadata": {"secondary": False},
}
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,
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",
@ -103,7 +103,7 @@ async def test_get_conditions_hidden_auxiliary(
"domain": DOMAIN,
"type": condition,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"entity_id": entity_entry.id,
"metadata": {"secondary": True},
}
for condition in ["is_off", "is_on"]
@ -144,17 +144,49 @@ async def test_get_condition_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(
hass: HomeAssistant, calls, enable_custom_integrations: None
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None:
"""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()
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
await hass.async_block_till_done()
ent1, ent2, ent3 = platform.ENTITIES
hass.states.async_set(entry.entity_id, STATE_ON)
assert await async_setup_component(
hass,
@ -168,7 +200,7 @@ async def test_if_state(
"condition": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": ent1.entity_id,
"entity_id": entry.id,
"type": "is_on",
}
],
@ -187,7 +219,7 @@ async def test_if_state(
"condition": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": ent1.entity_id,
"entity_id": entry.id,
"type": "is_off",
}
],
@ -203,7 +235,6 @@ async def test_if_state(
},
)
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")
@ -212,7 +243,7 @@ async def test_if_state(
assert len(calls) == 1
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_event2")
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"
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(
hass: HomeAssistant, calls, enable_custom_integrations: None
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None:
"""Test for firing if condition is on with delay."""
point1 = dt_util.utcnow()
point2 = point1 + 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()
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
await hass.async_block_till_done()
ent1, ent2, ent3 = platform.ENTITIES
hass.states.async_set(entry.entity_id, STATE_ON)
with freeze_time(point1) as freezer:
assert await async_setup_component(
@ -248,7 +325,7 @@ async def test_if_fires_on_for_condition(
"condition": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": ent1.entity_id,
"entity_id": entry.id,
"type": "is_off",
"for": {"seconds": 5},
},
@ -266,7 +343,6 @@ async def test_if_fires_on_for_condition(
},
)
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")
@ -279,7 +355,7 @@ async def test_if_fires_on_for_condition(
await hass.async_block_till_done()
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")
await hass.async_block_till_done()
assert len(calls) == 0

View file

@ -7,7 +7,7 @@ from pytest_unordered import unordered
import homeassistant.components.automation as automation
from homeassistant.components.device_automation import DeviceAutomationType
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.helpers import device_registry as dr, entity_registry as er
from homeassistant.helpers.entity_registry import RegistryEntryHider
@ -46,7 +46,7 @@ async def test_get_triggers(
config_entry_id=config_entry.entry_id,
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
)
expected_triggers = [
@ -55,7 +55,7 @@ async def test_get_triggers(
"domain": DOMAIN,
"type": trigger,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"entity_id": entity_entry.id,
"metadata": {"secondary": False},
}
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,
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",
@ -103,7 +103,7 @@ async def test_get_triggers_hidden_auxiliary(
"domain": DOMAIN,
"type": trigger,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"entity_id": entity_entry.id,
"metadata": {"secondary": True},
}
for trigger in ["changed_states", "turned_off", "turned_on"]
@ -144,17 +144,47 @@ async def test_get_trigger_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(
hass: HomeAssistant, calls, enable_custom_integrations: None
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None:
"""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()
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
await hass.async_block_till_done()
ent1, ent2, ent3 = platform.ENTITIES
hass.states.async_set(entry.entity_id, STATE_ON)
assert await async_setup_component(
hass,
@ -166,7 +196,7 @@ async def test_if_fires_on_state_change(
"platform": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": ent1.entity_id,
"entity_id": entry.id,
"type": "turned_on",
},
"action": {
@ -190,7 +220,7 @@ async def test_if_fires_on_state_change(
"platform": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": ent1.entity_id,
"entity_id": entry.id,
"type": "turned_off",
},
"action": {
@ -214,7 +244,7 @@ async def test_if_fires_on_state_change(
"platform": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": ent1.entity_id,
"entity_id": entry.id,
"type": "changed_states",
},
"action": {
@ -237,37 +267,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
hass.states.async_set(ent1.entity_id, STATE_OFF)
hass.states.async_set(entry.entity_id, STATE_OFF)
await hass.async_block_till_done()
assert len(calls) == 2
assert {calls[0].data["some"], calls[1].data["some"]} == {
f"turn_off device - {ent1.entity_id} - on - off - None",
f"turn_on_or_off device - {ent1.entity_id} - on - off - None",
f"turn_off device - {entry.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()
assert len(calls) == 4
assert {calls[2].data["some"], calls[3].data["some"]} == {
f"turn_on device - {ent1.entity_id} - off - on - None",
f"turn_on_or_off device - {ent1.entity_id} - off - on - None",
f"turn_on device - {entry.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(
hass: HomeAssistant, calls, enable_custom_integrations: None
async def test_if_fires_on_state_change_legacy(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls,
enable_custom_integrations: None,
) -> None:
"""Test for triggers firing with delay."""
platform = getattr(hass.components, f"test.{DOMAIN}")
"""Test for turn_on and turn_off triggers firing."""
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
hass.states.async_set(entry.entity_id, STATE_ON)
assert await async_setup_component(
hass,
@ -279,7 +307,62 @@ async def test_if_fires_on_state_change_with_for(
"platform": "device",
"domain": DOMAIN,
"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",
"for": {"seconds": 5},
},
@ -303,16 +386,16 @@ async def test_if_fires_on_state_change_with_for(
},
)
await hass.async_block_till_done()
assert hass.states.get(ent1.entity_id).state == STATE_ON
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()
assert len(calls) == 0
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=10))
await hass.async_block_till_done()
assert len(calls) == 1
await hass.async_block_till_done()
assert calls[0].data["some"] == "turn_off device - {} - on - off - 0:00:05".format(
ent1.entity_id
assert (
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,
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
)
expected_triggers = [
@ -54,7 +54,7 @@ async def test_get_triggers(
"domain": DOMAIN,
"type": trigger,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"entity_id": entity_entry.id,
"metadata": {"secondary": False},
}
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,
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",
@ -102,7 +102,7 @@ async def test_get_triggers_hidden_auxiliary(
"domain": DOMAIN,
"type": trigger,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"entity_id": entity_entry.id,
"metadata": {"secondary": True},
}
for trigger in ["changed_states", "turned_off", "turned_on"]
@ -143,8 +143,42 @@ async def test_get_trigger_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(
hass: HomeAssistant, calls: list[ServiceCall], enable_custom_integrations: None
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls: list[ServiceCall],
enable_custom_integrations: None,
) -> None:
"""Test for turn_on and turn_off triggers firing."""
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"}})
await hass.async_block_till_done()
entry = entity_registry.async_get("update.update_available")
assert await async_setup_component(
hass,
automation.DOMAIN,
@ -163,7 +199,7 @@ async def test_if_fires_on_state_change(
"platform": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": "update.update_available",
"entity_id": entry.id,
"type": "turned_on",
},
"action": {
@ -232,16 +268,21 @@ async def test_if_fires_on_state_change(
)
async def test_if_fires_on_state_change_with_for(
hass: HomeAssistant, calls: list[ServiceCall], enable_custom_integrations: None
async def test_if_fires_on_state_change_legacy(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
calls: list[ServiceCall],
enable_custom_integrations: 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.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,
@ -252,7 +293,69 @@ async def test_if_fires_on_state_change_with_for(
"platform": "device",
"domain": DOMAIN,
"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",
"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_DOMAIN: Platform.SWITCH,
CONF_ENTITY_ID: wemo_entity.entity_id,
CONF_ENTITY_ID: wemo_entity.id,
CONF_PLATFORM: "device",
CONF_TYPE: "changed_states",
"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_DOMAIN: Platform.SWITCH,
CONF_ENTITY_ID: wemo_entity.entity_id,
CONF_ENTITY_ID: wemo_entity.id,
CONF_PLATFORM: "device",
CONF_TYPE: "turned_off",
"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_DOMAIN: Platform.SWITCH,
CONF_ENTITY_ID: wemo_entity.entity_id,
CONF_ENTITY_ID: wemo_entity.id,
CONF_PLATFORM: "device",
CONF_TYPE: "turned_on",
"metadata": {"secondary": False},

View file

@ -14,7 +14,7 @@ from homeassistant.components.device_automation import DeviceAutomationType
from homeassistant.components.zha import DOMAIN
from homeassistant.const import Platform
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 .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(
{(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(
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,
"domain": Platform.LIGHT,
"entity_id": "light.inovelli_vzm31_sn_light",
"entity_id": inovelli_light.id,
"metadata": {"secondary": False},
"type": "turn_off",
},
{
"device_id": inovelli_reg_device.id,
"domain": Platform.LIGHT,
"entity_id": "light.inovelli_vzm31_sn_light",
"entity_id": inovelli_light.id,
"metadata": {"secondary": False},
"type": "turn_on",
},
{
"device_id": inovelli_reg_device.id,
"domain": Platform.LIGHT,
"entity_id": "light.inovelli_vzm31_sn_light",
"entity_id": inovelli_light.id,
"metadata": {"secondary": False},
"type": "toggle",
},