core/tests/components/automation/test_template.py

784 lines
24 KiB
Python
Raw Normal View History

"""The tests for the Template automation."""
from datetime import timedelta
from unittest import mock
import pytest
2015-12-16 21:27:43 +00:00
import homeassistant.components.automation as automation
from homeassistant.core import Context
from homeassistant.setup import async_setup_component
import homeassistant.util.dt as dt_util
2015-12-16 21:27:43 +00:00
from tests.common import (
assert_setup_component,
async_fire_time_changed,
async_mock_service,
mock_component,
)
from tests.components.automation import common
2016-02-14 23:08:23 +00:00
2015-12-16 21:27:43 +00:00
@pytest.fixture
def calls(hass):
"""Track calls to a mock serivce."""
2019-07-31 19:25:30 +00:00
return async_mock_service(hass, "test", "automation")
2015-12-16 21:27:43 +00:00
@pytest.fixture(autouse=True)
def setup_comp(hass):
"""Initialize components."""
2019-07-31 19:25:30 +00:00
mock_component(hass, "group")
hass.states.async_set("test.entity", "hello")
2015-12-16 21:27:43 +00:00
async def test_if_fires_on_change_bool(hass, calls):
"""Test for firing on boolean change."""
2019-07-31 19:25:30 +00:00
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {"platform": "template", "value_template": "{{ true }}"},
"action": {"service": "test.automation"},
2015-12-16 21:27:43 +00:00
}
2019-07-31 19:25:30 +00:00
},
)
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "world")
await hass.async_block_till_done()
assert 1 == len(calls)
await common.async_turn_off(hass)
await hass.async_block_till_done()
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "planet")
await hass.async_block_till_done()
assert 1 == len(calls)
async def test_if_fires_on_change_str(hass, calls):
"""Test for firing on change."""
2019-07-31 19:25:30 +00:00
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {"platform": "template", "value_template": '{{ "true" }}'},
"action": {"service": "test.automation"},
2015-12-16 21:27:43 +00:00
}
2019-07-31 19:25:30 +00:00
},
)
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "world")
await hass.async_block_till_done()
assert 1 == len(calls)
async def test_if_fires_on_change_str_crazy(hass, calls):
"""Test for firing on change."""
2019-07-31 19:25:30 +00:00
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {"platform": "template", "value_template": '{{ "TrUE" }}'},
"action": {"service": "test.automation"},
2015-12-16 21:27:43 +00:00
}
2019-07-31 19:25:30 +00:00
},
)
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "world")
await hass.async_block_till_done()
assert 1 == len(calls)
async def test_if_not_fires_on_change_bool(hass, calls):
"""Test for not firing on boolean change."""
2019-07-31 19:25:30 +00:00
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {"platform": "template", "value_template": "{{ false }}"},
"action": {"service": "test.automation"},
2015-12-16 21:27:43 +00:00
}
2019-07-31 19:25:30 +00:00
},
)
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "world")
await hass.async_block_till_done()
assert 0 == len(calls)
async def test_if_not_fires_on_change_str(hass, calls):
"""Test for not firing on string change."""
2019-07-31 19:25:30 +00:00
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {"platform": "template", "value_template": "true"},
"action": {"service": "test.automation"},
2015-12-16 21:27:43 +00:00
}
2019-07-31 19:25:30 +00:00
},
)
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "world")
await hass.async_block_till_done()
assert 0 == len(calls)
async def test_if_not_fires_on_change_str_crazy(hass, calls):
"""Test for not firing on string change."""
2019-07-31 19:25:30 +00:00
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {
"platform": "template",
"value_template": '{{ "Anything other than true is false." }}',
},
"action": {"service": "test.automation"},
2015-12-16 21:27:43 +00:00
}
2019-07-31 19:25:30 +00:00
},
)
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "world")
await hass.async_block_till_done()
assert 0 == len(calls)
async def test_if_fires_on_no_change(hass, calls):
"""Test for firing on no change."""
2019-07-31 19:25:30 +00:00
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {"platform": "template", "value_template": "{{ true }}"},
"action": {"service": "test.automation"},
2015-12-16 21:27:43 +00:00
}
2019-07-31 19:25:30 +00:00
},
)
await hass.async_block_till_done()
cur_len = len(calls)
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "hello")
await hass.async_block_till_done()
assert cur_len == len(calls)
async def test_if_fires_on_two_change(hass, calls):
"""Test for firing on two changes."""
2019-07-31 19:25:30 +00:00
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {"platform": "template", "value_template": "{{ true }}"},
"action": {"service": "test.automation"},
2015-12-16 21:27:43 +00:00
}
2019-07-31 19:25:30 +00:00
},
)
# Trigger once
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "world")
await hass.async_block_till_done()
assert 1 == len(calls)
# Trigger again
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "world")
await hass.async_block_till_done()
assert 1 == len(calls)
async def test_if_fires_on_change_with_template(hass, calls):
"""Test for firing on change with template."""
2019-07-31 19:25:30 +00:00
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {
"platform": "template",
"value_template": '{{ is_state("test.entity", "world") }}',
},
"action": {"service": "test.automation"},
2015-12-16 21:27:43 +00:00
}
2019-07-31 19:25:30 +00:00
},
)
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "world")
await hass.async_block_till_done()
assert 1 == len(calls)
async def test_if_not_fires_on_change_with_template(hass, calls):
"""Test for not firing on change with template."""
2019-07-31 19:25:30 +00:00
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {
"platform": "template",
"value_template": '{{ is_state("test.entity", "hello") }}',
},
"action": {"service": "test.automation"},
2015-12-16 21:27:43 +00:00
}
2019-07-31 19:25:30 +00:00
},
)
await hass.async_block_till_done()
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "world")
await hass.async_block_till_done()
assert len(calls) == 0
async def test_if_fires_on_change_with_template_advanced(hass, calls):
"""Test for firing on change with template advanced."""
context = Context()
2019-07-31 19:25:30 +00:00
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {
"platform": "template",
"value_template": '{{ is_state("test.entity", "world") }}',
},
"action": {
"service": "test.automation",
"data_template": {
"some": "{{ trigger.%s }}"
% "}} - {{ trigger.".join(
(
"platform",
"entity_id",
"from_state.state",
"to_state.state",
"for",
)
)
},
2015-12-16 21:27:43 +00:00
},
}
2019-07-31 19:25:30 +00:00
},
)
await hass.async_block_till_done()
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "world", context=context)
await hass.async_block_till_done()
assert 1 == len(calls)
assert calls[0].context.parent_id == context.id
2019-07-31 19:25:30 +00:00
assert "template - test.entity - hello - world - None" == calls[0].data["some"]
async def test_if_fires_on_no_change_with_template_advanced(hass, calls):
"""Test for firing on no change with template advanced."""
2019-07-31 19:25:30 +00:00
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {
"platform": "template",
"value_template": """{%- if is_state("test.entity", "world") -%}
true
{%- else -%}
false
2019-07-31 19:25:30 +00:00
{%- endif -%}""",
},
"action": {"service": "test.automation"},
2015-12-16 21:27:43 +00:00
}
2019-07-31 19:25:30 +00:00
},
)
# Different state
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "worldz")
await hass.async_block_till_done()
assert 0 == len(calls)
# Different state
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "hello")
await hass.async_block_till_done()
assert 0 == len(calls)
async def test_if_fires_on_change_with_template_2(hass, calls):
"""Test for firing on change with template."""
2019-07-31 19:25:30 +00:00
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {
"platform": "template",
"value_template": '{{ not is_state("test.entity", "world") }}',
},
"action": {"service": "test.automation"},
2015-12-16 21:27:43 +00:00
}
2019-07-31 19:25:30 +00:00
},
)
await hass.async_block_till_done()
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "world")
await hass.async_block_till_done()
assert len(calls) == 0
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "home")
await hass.async_block_till_done()
assert len(calls) == 1
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "work")
await hass.async_block_till_done()
assert len(calls) == 1
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "not_home")
await hass.async_block_till_done()
assert len(calls) == 1
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "world")
await hass.async_block_till_done()
assert len(calls) == 1
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "home")
await hass.async_block_till_done()
assert len(calls) == 2
async def test_if_action(hass, calls):
"""Test for firing if action."""
2019-07-31 19:25:30 +00:00
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {"platform": "event", "event_type": "test_event"},
"condition": [
{
"condition": "template",
"value_template": '{{ is_state("test.entity", "world") }}',
}
],
"action": {"service": "test.automation"},
}
2019-07-31 19:25:30 +00:00
},
)
2015-12-16 21:27:43 +00:00
# Condition is not true yet
2019-07-31 19:25:30 +00:00
hass.bus.async_fire("test_event")
await hass.async_block_till_done()
assert 0 == len(calls)
2015-12-16 22:07:14 +00:00
# Change condition to true, but it shouldn't be triggered yet
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "world")
await hass.async_block_till_done()
assert 0 == len(calls)
2015-12-16 21:27:43 +00:00
# Condition is true and event is triggered
2019-07-31 19:25:30 +00:00
hass.bus.async_fire("test_event")
await hass.async_block_till_done()
assert 1 == len(calls)
2015-12-16 21:27:43 +00:00
async def test_if_fires_on_change_with_bad_template(hass, calls):
"""Test for firing on change with bad template."""
2019-04-09 20:59:15 +00:00
with assert_setup_component(0, automation.DOMAIN):
2019-07-31 19:25:30 +00:00
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {"platform": "template", "value_template": "{{ "},
"action": {"service": "test.automation"},
2015-12-16 21:27:43 +00:00
}
2019-07-31 19:25:30 +00:00
},
)
2015-12-16 21:27:43 +00:00
async def test_if_fires_on_change_with_bad_template_2(hass, calls):
"""Test for firing on change with bad template."""
2019-07-31 19:25:30 +00:00
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {
"platform": "template",
"value_template": "{{ xyz | round(0) }}",
},
"action": {"service": "test.automation"},
}
2019-07-31 19:25:30 +00:00
},
)
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "world")
await hass.async_block_till_done()
assert 0 == len(calls)
async def test_wait_template_with_trigger(hass, calls):
"""Test using wait template with 'trigger.entity_id'."""
2019-07-31 19:25:30 +00:00
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {
"platform": "template",
"value_template": "{{ states.test.entity.state == 'world' }}",
},
"action": [
{"wait_template": "{{ is_state(trigger.entity_id, 'hello') }}"},
{
"service": "test.automation",
"data_template": {
"some": "{{ trigger.%s }}"
% "}} - {{ trigger.".join(
(
"platform",
"entity_id",
"from_state.state",
"to_state.state",
"for",
)
)
},
},
],
}
},
)
await hass.async_block_till_done()
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "world")
await hass.async_block_till_done()
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "hello")
await hass.async_block_till_done()
assert 1 == len(calls)
2019-07-31 19:25:30 +00:00
assert "template - test.entity - hello - world - None" == calls[0].data["some"]
async def test_if_fires_on_change_with_for(hass, calls):
"""Test for firing on change with for."""
2019-07-31 19:25:30 +00:00
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {
"platform": "template",
"value_template": "{{ is_state('test.entity', 'world') }}",
"for": {"seconds": 5},
},
2019-07-31 19:25:30 +00:00
"action": {"service": "test.automation"},
}
2019-07-31 19:25:30 +00:00
},
)
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "world")
await hass.async_block_till_done()
assert 0 == len(calls)
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=10))
await hass.async_block_till_done()
assert 1 == len(calls)
async def test_if_fires_on_change_with_for_advanced(hass, calls):
"""Test for firing on change with for advanced."""
context = Context()
2019-07-31 19:25:30 +00:00
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {
"platform": "template",
"value_template": '{{ is_state("test.entity", "world") }}',
"for": {"seconds": 5},
},
2019-07-31 19:25:30 +00:00
"action": {
"service": "test.automation",
"data_template": {
"some": "{{ trigger.%s }}"
% "}} - {{ trigger.".join(
(
"platform",
"entity_id",
"from_state.state",
"to_state.state",
"for",
)
)
},
},
}
2019-07-31 19:25:30 +00:00
},
)
await hass.async_block_till_done()
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "world", context=context)
await hass.async_block_till_done()
assert 0 == len(calls)
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=10))
await hass.async_block_till_done()
assert 1 == len(calls)
assert calls[0].context.parent_id == context.id
2019-07-31 19:25:30 +00:00
assert "template - test.entity - hello - world - 0:00:05" == calls[0].data["some"]
async def test_if_fires_on_change_with_for_0(hass, calls):
"""Test for firing on change with for: 0."""
2019-07-31 19:25:30 +00:00
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {
"platform": "template",
"value_template": "{{ is_state('test.entity', 'world') }}",
"for": {"seconds": 0},
},
2019-07-31 19:25:30 +00:00
"action": {"service": "test.automation"},
}
2019-07-31 19:25:30 +00:00
},
)
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "world")
await hass.async_block_till_done()
assert 1 == len(calls)
async def test_if_fires_on_change_with_for_0_advanced(hass, calls):
"""Test for firing on change with for: 0 advanced."""
context = Context()
2019-07-31 19:25:30 +00:00
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {
"platform": "template",
"value_template": '{{ is_state("test.entity", "world") }}',
"for": {"seconds": 0},
},
2019-07-31 19:25:30 +00:00
"action": {
"service": "test.automation",
"data_template": {
"some": "{{ trigger.%s }}"
% "}} - {{ trigger.".join(
(
"platform",
"entity_id",
"from_state.state",
"to_state.state",
"for",
)
)
},
},
}
2019-07-31 19:25:30 +00:00
},
)
await hass.async_block_till_done()
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "world", context=context)
await hass.async_block_till_done()
assert 1 == len(calls)
assert calls[0].context.parent_id == context.id
2019-07-31 19:25:30 +00:00
assert "template - test.entity - hello - world - 0:00:00" == calls[0].data["some"]
async def test_if_fires_on_change_with_for_2(hass, calls):
"""Test for firing on change with for."""
2019-07-31 19:25:30 +00:00
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {
"platform": "template",
"value_template": "{{ is_state('test.entity', 'world') }}",
"for": 5,
},
"action": {"service": "test.automation"},
}
2019-07-31 19:25:30 +00:00
},
)
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "world")
await hass.async_block_till_done()
assert 0 == len(calls)
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=10))
await hass.async_block_till_done()
assert 1 == len(calls)
async def test_if_not_fires_on_change_with_for(hass, calls):
"""Test for firing on change with for."""
2019-07-31 19:25:30 +00:00
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {
"platform": "template",
"value_template": "{{ is_state('test.entity', 'world') }}",
"for": {"seconds": 5},
},
2019-07-31 19:25:30 +00:00
"action": {"service": "test.automation"},
}
2019-07-31 19:25:30 +00:00
},
)
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "world")
await hass.async_block_till_done()
assert 0 == len(calls)
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=4))
await hass.async_block_till_done()
assert 0 == len(calls)
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "hello")
await hass.async_block_till_done()
assert 0 == len(calls)
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=6))
await hass.async_block_till_done()
assert 0 == len(calls)
async def test_if_not_fires_when_turned_off_with_for(hass, calls):
"""Test for firing on change with for."""
2019-07-31 19:25:30 +00:00
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {
"platform": "template",
"value_template": "{{ is_state('test.entity', 'world') }}",
"for": {"seconds": 5},
},
2019-07-31 19:25:30 +00:00
"action": {"service": "test.automation"},
}
2019-07-31 19:25:30 +00:00
},
)
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "world")
await hass.async_block_till_done()
assert 0 == len(calls)
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=4))
await hass.async_block_till_done()
assert 0 == len(calls)
await common.async_turn_off(hass)
await hass.async_block_till_done()
assert 0 == len(calls)
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=6))
await hass.async_block_till_done()
assert 0 == len(calls)
async def test_if_fires_on_change_with_for_template_1(hass, calls):
"""Test for firing on change with for template."""
2019-07-31 19:25:30 +00:00
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {
"platform": "template",
"value_template": "{{ is_state('test.entity', 'world') }}",
"for": {"seconds": "{{ 5 }}"},
},
2019-07-31 19:25:30 +00:00
"action": {"service": "test.automation"},
}
2019-07-31 19:25:30 +00:00
},
)
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "world")
await hass.async_block_till_done()
assert 0 == len(calls)
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=10))
await hass.async_block_till_done()
assert 1 == len(calls)
async def test_if_fires_on_change_with_for_template_2(hass, calls):
"""Test for firing on change with for template."""
2019-07-31 19:25:30 +00:00
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {
"platform": "template",
"value_template": "{{ is_state('test.entity', 'world') }}",
"for": "{{ 5 }}",
},
"action": {"service": "test.automation"},
}
2019-07-31 19:25:30 +00:00
},
)
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "world")
await hass.async_block_till_done()
assert 0 == len(calls)
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=10))
await hass.async_block_till_done()
assert 1 == len(calls)
async def test_if_fires_on_change_with_for_template_3(hass, calls):
"""Test for firing on change with for template."""
2019-07-31 19:25:30 +00:00
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {
"platform": "template",
"value_template": "{{ is_state('test.entity', 'world') }}",
"for": "00:00:{{ 5 }}",
},
"action": {"service": "test.automation"},
}
2019-07-31 19:25:30 +00:00
},
)
2019-07-31 19:25:30 +00:00
hass.states.async_set("test.entity", "world")
await hass.async_block_till_done()
assert 0 == len(calls)
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=10))
await hass.async_block_till_done()
assert 1 == len(calls)
async def test_invalid_for_template_1(hass, calls):
"""Test for invalid for template."""
2019-07-31 19:25:30 +00:00
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {
"platform": "template",
"value_template": "{{ is_state('test.entity', 'world') }}",
"for": {"seconds": "{{ five }}"},
},
2019-07-31 19:25:30 +00:00
"action": {"service": "test.automation"},
}
2019-07-31 19:25:30 +00:00
},
)
2019-07-31 19:25:30 +00:00
with mock.patch.object(automation.template, "_LOGGER") as mock_logger:
hass.states.async_set("test.entity", "world")
await hass.async_block_till_done()
assert mock_logger.error.called