mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 20:57:21 +00:00
Add support for for
to binary_sensor, light and switch device conditions (#27153)
* Add support for `for` to binary_sensor, light and switch device conditions * Fix typing * Fixup * Fixup
This commit is contained in:
parent
4733fea416
commit
cda7692f24
@ -4,7 +4,7 @@ import voluptuous as vol
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.components.device_automation.const import CONF_IS_OFF, CONF_IS_ON
|
||||
from homeassistant.const import ATTR_DEVICE_CLASS, CONF_ENTITY_ID, CONF_TYPE
|
||||
from homeassistant.const import ATTR_DEVICE_CLASS, CONF_ENTITY_ID, CONF_FOR, CONF_TYPE
|
||||
from homeassistant.helpers import condition, config_validation as cv
|
||||
from homeassistant.helpers.entity_registry import (
|
||||
async_entries_for_device,
|
||||
@ -188,6 +188,7 @@ CONDITION_SCHEMA = cv.DEVICE_CONDITION_BASE_SCHEMA.extend(
|
||||
{
|
||||
vol.Required(CONF_ENTITY_ID): cv.entity_id,
|
||||
vol.Required(CONF_TYPE): vol.In(IS_OFF + IS_ON),
|
||||
vol.Optional(CONF_FOR): cv.positive_time_period_dict,
|
||||
}
|
||||
)
|
||||
|
||||
@ -244,5 +245,16 @@ def async_condition_from_config(
|
||||
condition.CONF_ENTITY_ID: config[CONF_ENTITY_ID],
|
||||
condition.CONF_STATE: stat,
|
||||
}
|
||||
if CONF_FOR in config:
|
||||
state_config[CONF_FOR] = config[CONF_FOR]
|
||||
|
||||
return condition.state_from_config(state_config, config_validation)
|
||||
|
||||
|
||||
async def async_get_condition_capabilities(hass: HomeAssistant, config: dict) -> dict:
|
||||
"""List condition capabilities."""
|
||||
return {
|
||||
"extra_fields": vol.Schema(
|
||||
{vol.Optional(CONF_FOR): cv.positive_time_period_dict}
|
||||
)
|
||||
}
|
||||
|
@ -240,7 +240,7 @@ async def async_get_triggers(hass, device_id):
|
||||
return triggers
|
||||
|
||||
|
||||
async def async_get_trigger_capabilities(hass, trigger):
|
||||
async def async_get_trigger_capabilities(hass, config):
|
||||
"""List trigger capabilities."""
|
||||
return {
|
||||
"extra_fields": vol.Schema(
|
||||
|
@ -59,6 +59,9 @@ async def async_setup(hass, config):
|
||||
hass.components.websocket_api.async_register_command(
|
||||
websocket_device_automation_list_triggers
|
||||
)
|
||||
hass.components.websocket_api.async_register_command(
|
||||
websocket_device_automation_get_condition_capabilities
|
||||
)
|
||||
hass.components.websocket_api.async_register_command(
|
||||
websocket_device_automation_get_trigger_capabilities
|
||||
)
|
||||
@ -206,6 +209,22 @@ async def websocket_device_automation_list_triggers(hass, connection, msg):
|
||||
connection.send_result(msg["id"], triggers)
|
||||
|
||||
|
||||
@websocket_api.async_response
|
||||
@websocket_api.websocket_command(
|
||||
{
|
||||
vol.Required("type"): "device_automation/condition/capabilities",
|
||||
vol.Required("condition"): dict,
|
||||
}
|
||||
)
|
||||
async def websocket_device_automation_get_condition_capabilities(hass, connection, msg):
|
||||
"""Handle request for device condition capabilities."""
|
||||
condition = msg["condition"]
|
||||
capabilities = await _async_get_device_automation_capabilities(
|
||||
hass, "condition", condition
|
||||
)
|
||||
connection.send_result(msg["id"], capabilities)
|
||||
|
||||
|
||||
@websocket_api.async_response
|
||||
@websocket_api.websocket_command(
|
||||
{
|
||||
|
@ -80,6 +80,7 @@ CONDITION_SCHEMA = cv.DEVICE_CONDITION_BASE_SCHEMA.extend(
|
||||
{
|
||||
vol.Required(CONF_ENTITY_ID): cv.entity_id,
|
||||
vol.Required(CONF_TYPE): vol.In([CONF_IS_OFF, CONF_IS_ON]),
|
||||
vol.Optional(CONF_FOR): cv.positive_time_period_dict,
|
||||
}
|
||||
)
|
||||
|
||||
@ -132,6 +133,8 @@ def async_condition_from_config(
|
||||
condition.CONF_ENTITY_ID: config[CONF_ENTITY_ID],
|
||||
condition.CONF_STATE: stat,
|
||||
}
|
||||
if CONF_FOR in config:
|
||||
state_config[CONF_FOR] = config[CONF_FOR]
|
||||
|
||||
return condition.state_from_config(state_config, config_validation)
|
||||
|
||||
@ -213,7 +216,16 @@ async def async_get_triggers(
|
||||
return await _async_get_automations(hass, device_id, ENTITY_TRIGGERS, domain)
|
||||
|
||||
|
||||
async def async_get_trigger_capabilities(hass: HomeAssistant, trigger: dict) -> dict:
|
||||
async def async_get_condition_capabilities(hass: HomeAssistant, config: dict) -> dict:
|
||||
"""List condition capabilities."""
|
||||
return {
|
||||
"extra_fields": vol.Schema(
|
||||
{vol.Optional(CONF_FOR): cv.positive_time_period_dict}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
async def async_get_trigger_capabilities(hass: HomeAssistant, config: dict) -> dict:
|
||||
"""List trigger capabilities."""
|
||||
return {
|
||||
"extra_fields": vol.Schema(
|
||||
|
@ -27,3 +27,8 @@ def async_condition_from_config(
|
||||
async def async_get_conditions(hass: HomeAssistant, device_id: str) -> List[dict]:
|
||||
"""List device conditions."""
|
||||
return await toggle_entity.async_get_conditions(hass, device_id, DOMAIN)
|
||||
|
||||
|
||||
async def async_get_condition_capabilities(hass: HomeAssistant, config: dict) -> dict:
|
||||
"""List condition capabilities."""
|
||||
return await toggle_entity.async_get_condition_capabilities(hass, config)
|
||||
|
@ -32,6 +32,6 @@ async def async_get_triggers(hass: HomeAssistant, device_id: str) -> List[dict]:
|
||||
return await toggle_entity.async_get_triggers(hass, device_id, DOMAIN)
|
||||
|
||||
|
||||
async def async_get_trigger_capabilities(hass: HomeAssistant, trigger: dict) -> dict:
|
||||
async def async_get_trigger_capabilities(hass: HomeAssistant, config: dict) -> dict:
|
||||
"""List trigger capabilities."""
|
||||
return await toggle_entity.async_get_trigger_capabilities(hass, trigger)
|
||||
return await toggle_entity.async_get_trigger_capabilities(hass, config)
|
||||
|
@ -136,7 +136,7 @@ async def async_get_triggers(hass, device_id):
|
||||
return triggers
|
||||
|
||||
|
||||
async def async_get_trigger_capabilities(hass, trigger):
|
||||
async def async_get_trigger_capabilities(hass, config):
|
||||
"""List trigger capabilities."""
|
||||
return {
|
||||
"extra_fields": vol.Schema(
|
||||
|
@ -27,3 +27,8 @@ def async_condition_from_config(
|
||||
async def async_get_conditions(hass: HomeAssistant, device_id: str) -> List[dict]:
|
||||
"""List device conditions."""
|
||||
return await toggle_entity.async_get_conditions(hass, device_id, DOMAIN)
|
||||
|
||||
|
||||
async def async_get_condition_capabilities(hass: HomeAssistant, config: dict) -> dict:
|
||||
"""List condition capabilities."""
|
||||
return await toggle_entity.async_get_condition_capabilities(hass, config)
|
||||
|
@ -32,6 +32,6 @@ async def async_get_triggers(hass: HomeAssistant, device_id: str) -> List[dict]:
|
||||
return await toggle_entity.async_get_triggers(hass, device_id, DOMAIN)
|
||||
|
||||
|
||||
async def async_get_trigger_capabilities(hass: HomeAssistant, trigger: dict) -> dict:
|
||||
async def async_get_trigger_capabilities(hass: HomeAssistant, config: dict) -> dict:
|
||||
"""List trigger capabilities."""
|
||||
return await toggle_entity.async_get_trigger_capabilities(hass, trigger)
|
||||
return await toggle_entity.async_get_trigger_capabilities(hass, config)
|
||||
|
@ -1,5 +1,7 @@
|
||||
"""The test for binary_sensor device automation."""
|
||||
from datetime import timedelta
|
||||
import pytest
|
||||
from unittest.mock import patch
|
||||
|
||||
from homeassistant.components.binary_sensor import DOMAIN, DEVICE_CLASSES
|
||||
from homeassistant.components.binary_sensor.device_condition import ENTITY_CONDITIONS
|
||||
@ -7,6 +9,7 @@ from homeassistant.const import STATE_ON, STATE_OFF, CONF_PLATFORM
|
||||
from homeassistant.setup import async_setup_component
|
||||
import homeassistant.components.automation as automation
|
||||
from homeassistant.helpers import device_registry
|
||||
import homeassistant.util.dt as dt_util
|
||||
|
||||
from tests.common import (
|
||||
MockConfigEntry,
|
||||
@ -14,6 +17,7 @@ from tests.common import (
|
||||
mock_device_registry,
|
||||
mock_registry,
|
||||
async_get_device_automations,
|
||||
async_get_device_automation_capabilities,
|
||||
)
|
||||
|
||||
|
||||
@ -71,6 +75,28 @@ async def test_get_conditions(hass, device_reg, entity_reg):
|
||||
assert conditions == expected_conditions
|
||||
|
||||
|
||||
async def test_get_condition_capabilities(hass, device_reg, entity_reg):
|
||||
"""Test we get the expected capabilities from a binary_sensor condition."""
|
||||
config_entry = MockConfigEntry(domain="test", data={})
|
||||
config_entry.add_to_hass(hass)
|
||||
device_entry = device_reg.async_get_or_create(
|
||||
config_entry_id=config_entry.entry_id,
|
||||
connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
|
||||
)
|
||||
entity_reg.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, "condition", device_entry.id)
|
||||
for condition in conditions:
|
||||
capabilities = await async_get_device_automation_capabilities(
|
||||
hass, "condition", condition
|
||||
)
|
||||
assert capabilities == expected_capabilities
|
||||
|
||||
|
||||
async def test_if_state(hass, calls):
|
||||
"""Test for turn_on and turn_off conditions."""
|
||||
platform = getattr(hass.components, f"test.{DOMAIN}")
|
||||
@ -131,7 +157,6 @@ async def test_if_state(hass, calls):
|
||||
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"
|
||||
@ -142,3 +167,73 @@ async def test_if_state(hass, calls):
|
||||
await hass.async_block_till_done()
|
||||
assert len(calls) == 2
|
||||
assert calls[1].data["some"] == "is_off event - test_event2"
|
||||
|
||||
|
||||
async def test_if_fires_on_for_condition(hass, calls):
|
||||
"""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}")
|
||||
|
||||
platform.init()
|
||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
|
||||
|
||||
sensor1 = platform.ENTITIES["battery"]
|
||||
|
||||
with patch("homeassistant.core.dt_util.utcnow") as mock_utcnow:
|
||||
mock_utcnow.return_value = point1
|
||||
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": sensor1.entity_id,
|
||||
"type": "is_not_bat_low",
|
||||
"for": {"seconds": 5},
|
||||
},
|
||||
"action": {
|
||||
"service": "test.automation",
|
||||
"data_template": {
|
||||
"some": "is_off {{ trigger.%s }}"
|
||||
% "}} - {{ trigger.".join(
|
||||
("platform", "event.event_type")
|
||||
)
|
||||
},
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert hass.states.get(sensor1.entity_id).state == STATE_ON
|
||||
assert len(calls) == 0
|
||||
|
||||
hass.bus.async_fire("test_event1")
|
||||
await hass.async_block_till_done()
|
||||
assert len(calls) == 0
|
||||
|
||||
# Time travel 10 secs into the future
|
||||
mock_utcnow.return_value = point2
|
||||
hass.bus.async_fire("test_event1")
|
||||
await hass.async_block_till_done()
|
||||
assert len(calls) == 0
|
||||
|
||||
hass.states.async_set(sensor1.entity_id, STATE_OFF)
|
||||
hass.bus.async_fire("test_event1")
|
||||
await hass.async_block_till_done()
|
||||
assert len(calls) == 0
|
||||
|
||||
# Time travel 20 secs into the future
|
||||
mock_utcnow.return_value = point3
|
||||
hass.bus.async_fire("test_event1")
|
||||
await hass.async_block_till_done()
|
||||
assert len(calls) == 1
|
||||
assert calls[0].data["some"] == "is_off event - test_event1"
|
||||
|
@ -170,6 +170,103 @@ async def test_websocket_get_triggers(hass, hass_ws_client, device_reg, entity_r
|
||||
assert _same_lists(triggers, expected_triggers)
|
||||
|
||||
|
||||
async def test_websocket_get_condition_capabilities(
|
||||
hass, hass_ws_client, device_reg, entity_reg
|
||||
):
|
||||
"""Test we get the expected condition capabilities for a light through websocket."""
|
||||
await async_setup_component(hass, "device_automation", {})
|
||||
config_entry = MockConfigEntry(domain="test", data={})
|
||||
config_entry.add_to_hass(hass)
|
||||
device_entry = device_reg.async_get_or_create(
|
||||
config_entry_id=config_entry.entry_id,
|
||||
connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
|
||||
)
|
||||
entity_reg.async_get_or_create("light", "test", "5678", device_id=device_entry.id)
|
||||
expected_capabilities = {
|
||||
"extra_fields": [
|
||||
{"name": "for", "optional": True, "type": "positive_time_period_dict"}
|
||||
]
|
||||
}
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
await client.send_json(
|
||||
{
|
||||
"id": 1,
|
||||
"type": "device_automation/condition/list",
|
||||
"device_id": device_entry.id,
|
||||
}
|
||||
)
|
||||
msg = await client.receive_json()
|
||||
|
||||
assert msg["id"] == 1
|
||||
assert msg["type"] == TYPE_RESULT
|
||||
assert msg["success"]
|
||||
conditions = msg["result"]
|
||||
|
||||
id = 2
|
||||
for condition in conditions:
|
||||
await client.send_json(
|
||||
{
|
||||
"id": id,
|
||||
"type": "device_automation/condition/capabilities",
|
||||
"condition": condition,
|
||||
}
|
||||
)
|
||||
msg = await client.receive_json()
|
||||
assert msg["id"] == id
|
||||
assert msg["type"] == TYPE_RESULT
|
||||
assert msg["success"]
|
||||
capabilities = msg["result"]
|
||||
assert capabilities == expected_capabilities
|
||||
id = id + 1
|
||||
|
||||
|
||||
async def test_websocket_get_bad_condition_capabilities(
|
||||
hass, hass_ws_client, device_reg, entity_reg
|
||||
):
|
||||
"""Test we get no condition capabilities for a non existing domain."""
|
||||
await async_setup_component(hass, "device_automation", {})
|
||||
expected_capabilities = {}
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
await client.send_json(
|
||||
{
|
||||
"id": 1,
|
||||
"type": "device_automation/condition/capabilities",
|
||||
"condition": {"domain": "beer"},
|
||||
}
|
||||
)
|
||||
msg = await client.receive_json()
|
||||
assert msg["id"] == 1
|
||||
assert msg["type"] == TYPE_RESULT
|
||||
assert msg["success"]
|
||||
capabilities = msg["result"]
|
||||
assert capabilities == expected_capabilities
|
||||
|
||||
|
||||
async def test_websocket_get_no_condition_capabilities(
|
||||
hass, hass_ws_client, device_reg, entity_reg
|
||||
):
|
||||
"""Test we get no condition capabilities for a domain with no device condition capabilities."""
|
||||
await async_setup_component(hass, "device_automation", {})
|
||||
expected_capabilities = {}
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
await client.send_json(
|
||||
{
|
||||
"id": 1,
|
||||
"type": "device_automation/condition/capabilities",
|
||||
"condition": {"domain": "deconz"},
|
||||
}
|
||||
)
|
||||
msg = await client.receive_json()
|
||||
assert msg["id"] == 1
|
||||
assert msg["type"] == TYPE_RESULT
|
||||
assert msg["success"]
|
||||
capabilities = msg["result"]
|
||||
assert capabilities == expected_capabilities
|
||||
|
||||
|
||||
async def test_websocket_get_trigger_capabilities(
|
||||
hass, hass_ws_client, device_reg, entity_reg
|
||||
):
|
||||
|
@ -1,11 +1,14 @@
|
||||
"""The test for light device automation."""
|
||||
from datetime import timedelta
|
||||
import pytest
|
||||
from unittest.mock import patch
|
||||
|
||||
from homeassistant.components.light import DOMAIN
|
||||
from homeassistant.const import STATE_ON, STATE_OFF, CONF_PLATFORM
|
||||
from homeassistant.setup import async_setup_component
|
||||
import homeassistant.components.automation as automation
|
||||
from homeassistant.helpers import device_registry
|
||||
import homeassistant.util.dt as dt_util
|
||||
|
||||
from tests.common import (
|
||||
MockConfigEntry,
|
||||
@ -13,6 +16,7 @@ from tests.common import (
|
||||
mock_device_registry,
|
||||
mock_registry,
|
||||
async_get_device_automations,
|
||||
async_get_device_automation_capabilities,
|
||||
)
|
||||
|
||||
|
||||
@ -63,6 +67,28 @@ async def test_get_conditions(hass, device_reg, entity_reg):
|
||||
assert conditions == expected_conditions
|
||||
|
||||
|
||||
async def test_get_condition_capabilities(hass, device_reg, entity_reg):
|
||||
"""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_reg.async_get_or_create(
|
||||
config_entry_id=config_entry.entry_id,
|
||||
connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
|
||||
)
|
||||
entity_reg.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, "condition", device_entry.id)
|
||||
for condition in conditions:
|
||||
capabilities = await async_get_device_automation_capabilities(
|
||||
hass, "condition", condition
|
||||
)
|
||||
assert capabilities == expected_capabilities
|
||||
|
||||
|
||||
async def test_if_state(hass, calls):
|
||||
"""Test for turn_on and turn_off conditions."""
|
||||
platform = getattr(hass.components, f"test.{DOMAIN}")
|
||||
@ -134,3 +160,73 @@ async def test_if_state(hass, calls):
|
||||
await hass.async_block_till_done()
|
||||
assert len(calls) == 2
|
||||
assert calls[1].data["some"] == "is_off event - test_event2"
|
||||
|
||||
|
||||
async def test_if_fires_on_for_condition(hass, calls):
|
||||
"""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}")
|
||||
|
||||
platform.init()
|
||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
|
||||
|
||||
ent1, ent2, ent3 = platform.ENTITIES
|
||||
|
||||
with patch("homeassistant.core.dt_util.utcnow") as mock_utcnow:
|
||||
mock_utcnow.return_value = point1
|
||||
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": ent1.entity_id,
|
||||
"type": "is_off",
|
||||
"for": {"seconds": 5},
|
||||
},
|
||||
"action": {
|
||||
"service": "test.automation",
|
||||
"data_template": {
|
||||
"some": "is_off {{ trigger.%s }}"
|
||||
% "}} - {{ trigger.".join(
|
||||
("platform", "event.event_type")
|
||||
)
|
||||
},
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
)
|
||||
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 len(calls) == 0
|
||||
|
||||
# Time travel 10 secs into the future
|
||||
mock_utcnow.return_value = point2
|
||||
hass.bus.async_fire("test_event1")
|
||||
await hass.async_block_till_done()
|
||||
assert len(calls) == 0
|
||||
|
||||
hass.states.async_set(ent1.entity_id, STATE_OFF)
|
||||
hass.bus.async_fire("test_event1")
|
||||
await hass.async_block_till_done()
|
||||
assert len(calls) == 0
|
||||
|
||||
# Time travel 20 secs into the future
|
||||
mock_utcnow.return_value = point3
|
||||
hass.bus.async_fire("test_event1")
|
||||
await hass.async_block_till_done()
|
||||
assert len(calls) == 1
|
||||
assert calls[0].data["some"] == "is_off event - test_event1"
|
||||
|
@ -1,20 +1,22 @@
|
||||
"""The test for switch device automation."""
|
||||
from datetime import timedelta
|
||||
import pytest
|
||||
from unittest.mock import patch
|
||||
|
||||
from homeassistant.components.switch import DOMAIN
|
||||
from homeassistant.const import STATE_ON, STATE_OFF, CONF_PLATFORM
|
||||
from homeassistant.setup import async_setup_component
|
||||
import homeassistant.components.automation as automation
|
||||
from homeassistant.components.device_automation import (
|
||||
_async_get_device_automations as async_get_device_automations,
|
||||
)
|
||||
from homeassistant.helpers import device_registry
|
||||
import homeassistant.util.dt as dt_util
|
||||
|
||||
from tests.common import (
|
||||
MockConfigEntry,
|
||||
async_mock_service,
|
||||
mock_device_registry,
|
||||
mock_registry,
|
||||
async_get_device_automations,
|
||||
async_get_device_automation_capabilities,
|
||||
)
|
||||
|
||||
|
||||
@ -65,6 +67,28 @@ async def test_get_conditions(hass, device_reg, entity_reg):
|
||||
assert conditions == expected_conditions
|
||||
|
||||
|
||||
async def test_get_condition_capabilities(hass, device_reg, entity_reg):
|
||||
"""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_reg.async_get_or_create(
|
||||
config_entry_id=config_entry.entry_id,
|
||||
connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
|
||||
)
|
||||
entity_reg.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, "condition", device_entry.id)
|
||||
for condition in conditions:
|
||||
capabilities = await async_get_device_automation_capabilities(
|
||||
hass, "condition", condition
|
||||
)
|
||||
assert capabilities == expected_capabilities
|
||||
|
||||
|
||||
async def test_if_state(hass, calls):
|
||||
"""Test for turn_on and turn_off conditions."""
|
||||
platform = getattr(hass.components, f"test.{DOMAIN}")
|
||||
@ -136,3 +160,73 @@ async def test_if_state(hass, calls):
|
||||
await hass.async_block_till_done()
|
||||
assert len(calls) == 2
|
||||
assert calls[1].data["some"] == "is_off event - test_event2"
|
||||
|
||||
|
||||
async def test_if_fires_on_for_condition(hass, calls):
|
||||
"""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}")
|
||||
|
||||
platform.init()
|
||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
|
||||
|
||||
ent1, ent2, ent3 = platform.ENTITIES
|
||||
|
||||
with patch("homeassistant.core.dt_util.utcnow") as mock_utcnow:
|
||||
mock_utcnow.return_value = point1
|
||||
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": ent1.entity_id,
|
||||
"type": "is_off",
|
||||
"for": {"seconds": 5},
|
||||
},
|
||||
"action": {
|
||||
"service": "test.automation",
|
||||
"data_template": {
|
||||
"some": "is_off {{ trigger.%s }}"
|
||||
% "}} - {{ trigger.".join(
|
||||
("platform", "event.event_type")
|
||||
)
|
||||
},
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
)
|
||||
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 len(calls) == 0
|
||||
|
||||
# Time travel 10 secs into the future
|
||||
mock_utcnow.return_value = point2
|
||||
hass.bus.async_fire("test_event1")
|
||||
await hass.async_block_till_done()
|
||||
assert len(calls) == 0
|
||||
|
||||
hass.states.async_set(ent1.entity_id, STATE_OFF)
|
||||
hass.bus.async_fire("test_event1")
|
||||
await hass.async_block_till_done()
|
||||
assert len(calls) == 0
|
||||
|
||||
# Time travel 20 secs into the future
|
||||
mock_utcnow.return_value = point3
|
||||
hass.bus.async_fire("test_event1")
|
||||
await hass.async_block_till_done()
|
||||
assert len(calls) == 1
|
||||
assert calls[0].data["some"] == "is_off event - test_event1"
|
||||
|
Loading…
x
Reference in New Issue
Block a user