Files
core/tests/components/template/test_trigger_entity.py

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

232 lines
8.2 KiB
Python
Raw Permalink Normal View History

"""Test trigger template entity."""
import pytest
from homeassistant.components.template import DOMAIN, trigger_entity
from homeassistant.components.template.coordinator import TriggerUpdateCoordinator
from homeassistant.const import CONF_ICON, CONF_NAME, CONF_STATE, STATE_OFF, STATE_ON
from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.helpers import template
from homeassistant.helpers.trigger_template_entity import CONF_PICTURE
from homeassistant.setup import async_setup_component
from .conftest import async_trigger
from tests.common import assert_setup_component
_ICON_TEMPLATE = 'mdi:o{{ "n" if value=="on" else "ff" }}'
_PICTURE_TEMPLATE = '/local/picture_o{{ "n" if value=="on" else "ff" }}'
class TestEntity(trigger_entity.TriggerEntity):
"""Test entity class."""
__test__ = False
_entity_id_format = "test.{}"
extra_template_keys = (CONF_STATE,)
@property
def state(self) -> bool | None:
"""Return extra attributes."""
return self._rendered.get(CONF_STATE)
async def test_reference_blueprints_is_none(hass: HomeAssistant) -> None:
"""Test template entity requires hass to be set before accepting templates."""
coordinator = TriggerUpdateCoordinator(hass, {})
entity = trigger_entity.TriggerEntity(hass, coordinator, {})
assert entity.referenced_blueprint is None
async def test_template_state(hass: HomeAssistant) -> None:
"""Test manual trigger template entity with a state."""
config = {
CONF_NAME: template.Template("test_entity", hass),
CONF_ICON: template.Template(_ICON_TEMPLATE, hass),
CONF_PICTURE: template.Template(_PICTURE_TEMPLATE, hass),
CONF_STATE: template.Template("{{ value == 'on' }}", hass),
}
coordinator = TriggerUpdateCoordinator(hass, {})
entity = TestEntity(hass, coordinator, config)
entity.entity_id = "test.entity"
coordinator._execute_update({"value": STATE_ON})
entity._handle_coordinator_update()
await hass.async_block_till_done()
assert entity.state == "True"
assert entity.icon == "mdi:on"
assert entity.entity_picture == "/local/picture_on"
coordinator._execute_update({"value": STATE_OFF})
entity._handle_coordinator_update()
await hass.async_block_till_done()
assert entity.state == "False"
assert entity.icon == "mdi:off"
assert entity.entity_picture == "/local/picture_off"
async def test_bad_template_state(hass: HomeAssistant) -> None:
"""Test manual trigger template entity with a state."""
config = {
CONF_NAME: template.Template("test_entity", hass),
CONF_ICON: template.Template(_ICON_TEMPLATE, hass),
CONF_PICTURE: template.Template(_PICTURE_TEMPLATE, hass),
CONF_STATE: template.Template("{{ x - 1 }}", hass),
}
coordinator = TriggerUpdateCoordinator(hass, {})
entity = TestEntity(hass, coordinator, config)
entity.entity_id = "test.entity"
coordinator._execute_update({"x": 1})
entity._handle_coordinator_update()
await hass.async_block_till_done()
assert entity.available is True
assert entity.state == "0"
assert entity.icon == "mdi:off"
assert entity.entity_picture == "/local/picture_off"
coordinator._execute_update({"value": STATE_OFF})
entity._handle_coordinator_update()
await hass.async_block_till_done()
assert entity.available is False
assert entity.state is None
assert entity.icon is None
assert entity.entity_picture is None
async def test_template_state_syntax_error(
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
) -> None:
"""Test manual trigger template entity when state render fails."""
config = {
CONF_NAME: template.Template("test_entity", hass),
CONF_ICON: template.Template(_ICON_TEMPLATE, hass),
CONF_PICTURE: template.Template(_PICTURE_TEMPLATE, hass),
CONF_STATE: template.Template("{{ incorrect ", hass),
}
coordinator = TriggerUpdateCoordinator(hass, {})
entity = TestEntity(hass, coordinator, config)
entity.entity_id = "test.entity"
coordinator._execute_update({"value": STATE_ON})
entity._handle_coordinator_update()
await hass.async_block_till_done()
assert f"Error rendering {CONF_STATE} template for test.entity" in caplog.text
assert entity.state is None
assert entity.icon is None
assert entity.entity_picture is None
async def test_script_variables_from_coordinator(
hass: HomeAssistant, calls: list[ServiceCall], caplog: pytest.LogCaptureFixture
) -> None:
"""Test script variables."""
await async_trigger(hass, "sensor.start", "1")
with assert_setup_component(1, DOMAIN):
assert await async_setup_component(
hass,
DOMAIN,
{
"template": {
"variables": {"a": "{{ states('sensor.start') }}", "c": 0},
"triggers": {
"trigger": "state",
"entity_id": ["sensor.trigger"],
},
"actions": [
{
"action": "test.automation",
"data": {
"a": "{{ a }}",
"b": "{{ b }}",
"c": "{{ c }}",
},
}
],
"sensor": {
"name": "test",
"state": "{{ 'on' }}",
"variables": {"b": "{{ a + 1 }}", "c": 1},
"attributes": {
"a": "{{ a }}",
"b": "{{ b }}",
"c": "{{ c }}",
},
},
},
},
)
await async_trigger(hass, "sensor.trigger", "anything")
assert len(calls) == 1
assert calls[0].data["a"] == 1
assert calls[0].data["c"] == 0
assert "'b' is undefined when rendering '{{ b }}'" in caplog.text
state = hass.states.get("sensor.test")
assert state
assert state.state == "on"
assert state.attributes["a"] == 1
assert state.attributes["b"] == 2
assert state.attributes["c"] == 1
async def test_default_entity_id(hass: HomeAssistant) -> None:
"""Test template entity creates suggested entity_id from the default_entity_id."""
coordinator = TriggerUpdateCoordinator(hass, {})
entity = TestEntity(hass, coordinator, {"default_entity_id": "test.test"})
assert entity.entity_id == "test.test"
async def test_bad_default_entity_id(hass: HomeAssistant) -> None:
"""Test template entity creates suggested entity_id from the default_entity_id."""
coordinator = TriggerUpdateCoordinator(hass, {})
entity = TestEntity(hass, coordinator, {"default_entity_id": "bad.test"})
assert entity.entity_id == "test.test"
async def test_multiple_template_validators(hass: HomeAssistant) -> None:
"""Tests multiple templates execute validators."""
await async_trigger(hass, "sensor.state", "opening")
await async_trigger(hass, "sensor.position", "50")
await async_trigger(hass, "sensor.tilt", "49")
with assert_setup_component(1, DOMAIN):
assert await async_setup_component(
hass,
DOMAIN,
{
"template": {
"triggers": {
"trigger": "state",
"entity_id": ["sensor.trigger"],
},
"cover": {
"name": "test",
"state": "{{ states('sensor.state') }}",
"position": "{{ states('sensor.position') }}",
"tilt": "{{ states('sensor.tilt') }}",
"set_cover_position": [],
"set_cover_tilt_position": [],
"open_cover": [],
"close_cover": [],
},
},
},
)
await async_trigger(hass, "sensor.trigger", "anything")
state = hass.states.get("cover.test")
assert state
assert state.state == "opening"
assert state.attributes["current_position"] == 50
assert state.attributes["current_tilt_position"] == 49