mirror of
https://github.com/home-assistant/core.git
synced 2026-07-03 20:56:06 +01:00
696 lines
20 KiB
Python
696 lines
20 KiB
Python
"""The tests for the Template event platform."""
|
|
|
|
from typing import Any
|
|
|
|
import pytest
|
|
from syrupy.assertion import SnapshotAssertion
|
|
|
|
from homeassistant.components import event, template
|
|
from homeassistant.components.template.const import CONF_ATTRIBUTES, CONF_PICTURE
|
|
from homeassistant.components.template.coordinator import TriggerUpdateCoordinator
|
|
from homeassistant.components.template.event import (
|
|
CONF_EVENT_TYPE,
|
|
CONF_EVENT_TYPES,
|
|
TriggerEventEntity,
|
|
)
|
|
from homeassistant.const import (
|
|
ATTR_ENTITY_PICTURE,
|
|
ATTR_FRIENDLY_NAME,
|
|
ATTR_ICON,
|
|
CONF_ICON,
|
|
CONF_NAME,
|
|
STATE_UNAVAILABLE,
|
|
STATE_UNKNOWN,
|
|
)
|
|
from homeassistant.core import HomeAssistant, State
|
|
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
|
from homeassistant.helpers.template import Template
|
|
|
|
from .conftest import (
|
|
RESTORE_STATE_SAVED_ATTRIBUTES,
|
|
RESTORE_STATE_UPDATED_ATTRIBUTES,
|
|
ConfigurationStyle,
|
|
TemplatePlatformSetup,
|
|
assert_state_and_attributes,
|
|
async_get_flow_preview_state,
|
|
async_trigger,
|
|
make_test_trigger,
|
|
setup_and_test_nested_unique_id,
|
|
setup_and_test_unique_id,
|
|
setup_entity,
|
|
setup_mock_template_entity_restore_state,
|
|
setup_restore_template_entity,
|
|
)
|
|
|
|
from tests.common import MockConfigEntry, MockEntityPlatform, mock_restore_cache
|
|
from tests.conftest import WebSocketGenerator
|
|
|
|
TEST_STATE_ENTITY_ID = "sensor.test_state"
|
|
TEST_ATTRIBUTE_ENTITY_ID = "sensor.test_attribute"
|
|
TEST_EVENT = TemplatePlatformSetup(
|
|
event.DOMAIN,
|
|
"template_event",
|
|
make_test_trigger(TEST_STATE_ENTITY_ID, TEST_ATTRIBUTE_ENTITY_ID),
|
|
)
|
|
|
|
TEST_EVENT_TYPES_TEMPLATE = "{{ ['single', 'double', 'hold'] }}"
|
|
TEST_EVENT_TYPE_TEMPLATE = "{{ 'single' }}"
|
|
|
|
TEST_EVENT_CONFIG = {
|
|
"event_types": TEST_EVENT_TYPES_TEMPLATE,
|
|
"event_type": TEST_EVENT_TYPE_TEMPLATE,
|
|
}
|
|
TEST_FROZEN_INPUT = "2024-07-09 00:00:00+00:00"
|
|
TEST_FROZEN_STATE = "2024-07-09T00:00:00.000+00:00"
|
|
|
|
|
|
@pytest.fixture
|
|
async def setup_base_event(
|
|
hass: HomeAssistant,
|
|
count: int,
|
|
style: ConfigurationStyle,
|
|
config: dict[str, Any],
|
|
) -> None:
|
|
"""Do setup of event integration."""
|
|
await setup_entity(hass, TEST_EVENT, style, count, config)
|
|
|
|
|
|
@pytest.fixture
|
|
async def setup_event(
|
|
hass: HomeAssistant,
|
|
count: int,
|
|
style: ConfigurationStyle,
|
|
event_type_template: str,
|
|
event_types_template: str,
|
|
extra_config: dict[str, Any] | None,
|
|
) -> None:
|
|
"""Do setup of event integration."""
|
|
await setup_entity(
|
|
hass,
|
|
TEST_EVENT,
|
|
style,
|
|
count,
|
|
{
|
|
"event_type": event_type_template,
|
|
"event_types": event_types_template,
|
|
},
|
|
extra_config=extra_config,
|
|
)
|
|
|
|
|
|
@pytest.fixture
|
|
async def setup_single_attribute_state_event(
|
|
hass: HomeAssistant,
|
|
count: int,
|
|
style: ConfigurationStyle,
|
|
event_type_template: str,
|
|
event_types_template: str,
|
|
attribute: str,
|
|
attribute_template: str,
|
|
) -> None:
|
|
"""Do setup of event integration testing a single attribute."""
|
|
await setup_entity(
|
|
hass,
|
|
TEST_EVENT,
|
|
style,
|
|
count,
|
|
{
|
|
"event_type": event_type_template,
|
|
"event_types": event_types_template,
|
|
},
|
|
extra_config={attribute: attribute_template}
|
|
if attribute and attribute_template
|
|
else {},
|
|
)
|
|
|
|
|
|
@pytest.mark.freeze_time(TEST_FROZEN_INPUT)
|
|
async def test_setup_config_entry(
|
|
hass: HomeAssistant,
|
|
snapshot: SnapshotAssertion,
|
|
) -> None:
|
|
"""Test the config flow."""
|
|
|
|
await async_trigger(
|
|
hass,
|
|
TEST_STATE_ENTITY_ID,
|
|
"single",
|
|
{},
|
|
)
|
|
|
|
template_config_entry = MockConfigEntry(
|
|
data={},
|
|
domain=template.DOMAIN,
|
|
options={
|
|
"name": TEST_EVENT.object_id,
|
|
**TEST_EVENT_CONFIG,
|
|
"template_type": event.DOMAIN,
|
|
},
|
|
title="My template",
|
|
)
|
|
template_config_entry.add_to_hass(hass)
|
|
|
|
assert await hass.config_entries.async_setup(template_config_entry.entry_id)
|
|
await hass.async_block_till_done()
|
|
|
|
state = hass.states.get(TEST_EVENT.entity_id)
|
|
assert state is not None
|
|
assert state == snapshot
|
|
|
|
|
|
@pytest.mark.freeze_time(TEST_FROZEN_INPUT)
|
|
async def test_device_id(
|
|
hass: HomeAssistant,
|
|
device_registry: dr.DeviceRegistry,
|
|
entity_registry: er.EntityRegistry,
|
|
) -> None:
|
|
"""Test for device for Template."""
|
|
|
|
device_config_entry = MockConfigEntry()
|
|
device_config_entry.add_to_hass(hass)
|
|
device_entry = device_registry.async_get_or_create(
|
|
config_entry_id=device_config_entry.entry_id,
|
|
identifiers={("test", "identifier_test")},
|
|
connections={("mac", "30:31:32:33:34:35")},
|
|
)
|
|
await hass.async_block_till_done()
|
|
assert device_entry is not None
|
|
assert device_entry.id is not None
|
|
|
|
template_config_entry = MockConfigEntry(
|
|
data={},
|
|
domain=template.DOMAIN,
|
|
options={
|
|
"name": "My template",
|
|
"event_type": TEST_EVENT_TYPE_TEMPLATE,
|
|
"event_types": TEST_EVENT_TYPES_TEMPLATE,
|
|
"template_type": "event",
|
|
"device_id": device_entry.id,
|
|
},
|
|
title="My template",
|
|
)
|
|
template_config_entry.add_to_hass(hass)
|
|
|
|
assert await hass.config_entries.async_setup(template_config_entry.entry_id)
|
|
await hass.async_block_till_done()
|
|
|
|
template_entity = entity_registry.async_get("event.my_template")
|
|
assert template_entity is not None
|
|
assert template_entity.device_id == device_entry.id
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("count", "event_types_template", "extra_config"),
|
|
[(1, TEST_EVENT_TYPES_TEMPLATE, None)],
|
|
)
|
|
@pytest.mark.parametrize(
|
|
("style", "expected_state"),
|
|
[
|
|
(ConfigurationStyle.MODERN, STATE_UNKNOWN),
|
|
(ConfigurationStyle.TRIGGER, STATE_UNKNOWN),
|
|
],
|
|
)
|
|
@pytest.mark.parametrize("event_type_template", ["{{states.test['big.fat...']}}"])
|
|
@pytest.mark.usefixtures("setup_event")
|
|
async def test_event_type_syntax_error(
|
|
hass: HomeAssistant,
|
|
expected_state: str,
|
|
) -> None:
|
|
"""Test template event_type with render error."""
|
|
state = hass.states.get(TEST_EVENT.entity_id)
|
|
assert state.state == expected_state
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("count", "event_type_template", "event_types_template", "extra_config"),
|
|
[(1, "{{ states('sensor.test_state') }}", TEST_EVENT_TYPES_TEMPLATE, None)],
|
|
)
|
|
@pytest.mark.parametrize(
|
|
"style",
|
|
[ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER],
|
|
)
|
|
@pytest.mark.parametrize(
|
|
("event", "expected"),
|
|
[
|
|
("single", "single"),
|
|
("double", "double"),
|
|
("hold", "hold"),
|
|
],
|
|
)
|
|
@pytest.mark.usefixtures("setup_event")
|
|
async def test_event_type_template(
|
|
hass: HomeAssistant,
|
|
event: str,
|
|
expected: str,
|
|
) -> None:
|
|
"""Test template event_type."""
|
|
await async_trigger(hass, TEST_STATE_ENTITY_ID, event)
|
|
|
|
state = hass.states.get(TEST_EVENT.entity_id)
|
|
assert state.attributes["event_type"] == expected
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("count", "event_type_template", "event_types_template", "extra_config"),
|
|
[(1, "{{ states('sensor.test_state') }}", TEST_EVENT_TYPES_TEMPLATE, None)],
|
|
)
|
|
@pytest.mark.parametrize(
|
|
"style",
|
|
[ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER],
|
|
)
|
|
@pytest.mark.usefixtures("setup_event")
|
|
@pytest.mark.freeze_time(TEST_FROZEN_INPUT)
|
|
async def test_event_type_template_updates(
|
|
hass: HomeAssistant,
|
|
) -> None:
|
|
"""Test template event_type updates."""
|
|
await async_trigger(hass, TEST_STATE_ENTITY_ID, "single")
|
|
|
|
state = hass.states.get(TEST_EVENT.entity_id)
|
|
assert state.state == TEST_FROZEN_STATE
|
|
assert state.attributes["event_type"] == "single"
|
|
|
|
await async_trigger(hass, TEST_STATE_ENTITY_ID, "double")
|
|
|
|
state = hass.states.get(TEST_EVENT.entity_id)
|
|
assert state.state == TEST_FROZEN_STATE
|
|
assert state.attributes["event_type"] == "double"
|
|
|
|
await async_trigger(hass, TEST_STATE_ENTITY_ID, "hold")
|
|
|
|
state = hass.states.get(TEST_EVENT.entity_id)
|
|
assert state.state == TEST_FROZEN_STATE
|
|
assert state.attributes["event_type"] == "hold"
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("count", "event_types_template", "extra_config"),
|
|
[(1, TEST_EVENT_TYPES_TEMPLATE, None)],
|
|
)
|
|
@pytest.mark.parametrize(
|
|
"style",
|
|
[ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER],
|
|
)
|
|
@pytest.mark.parametrize(
|
|
"event_type_template",
|
|
[
|
|
"{{ None }}",
|
|
"{{ 7 }}",
|
|
"{{ 'unknown' }}",
|
|
"{{ 'tripple_double' }}",
|
|
],
|
|
)
|
|
@pytest.mark.usefixtures("setup_event")
|
|
async def test_event_type_invalid(
|
|
hass: HomeAssistant,
|
|
) -> None:
|
|
"""Test template event_type."""
|
|
state = hass.states.get(TEST_EVENT.entity_id)
|
|
assert state.state == STATE_UNKNOWN
|
|
assert state.attributes["event_type"] is None
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("count", "event_type_template", "event_types_template"),
|
|
[(1, "{{ states('sensor.test_state') }}", TEST_EVENT_TYPES_TEMPLATE)],
|
|
)
|
|
@pytest.mark.parametrize(
|
|
"style",
|
|
[ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER],
|
|
)
|
|
@pytest.mark.parametrize(
|
|
("attribute", "attribute_template", "key", "expected"),
|
|
[
|
|
(
|
|
"picture",
|
|
"{% if is_state('sensor.test_state', 'double') %}something{% endif %}",
|
|
ATTR_ENTITY_PICTURE,
|
|
"something",
|
|
),
|
|
(
|
|
"icon",
|
|
"{% if is_state('sensor.test_state', 'double') %}mdi:something{% endif %}",
|
|
ATTR_ICON,
|
|
"mdi:something",
|
|
),
|
|
],
|
|
)
|
|
@pytest.mark.usefixtures("setup_single_attribute_state_event")
|
|
async def test_entity_picture_and_icon_templates(
|
|
hass: HomeAssistant, key: str, expected: str
|
|
) -> None:
|
|
"""Test picture and icon template."""
|
|
state = await async_trigger(hass, TEST_STATE_ENTITY_ID, "single")
|
|
|
|
state = hass.states.get(TEST_EVENT.entity_id)
|
|
assert state.attributes.get(key) in ("", None)
|
|
|
|
state = await async_trigger(hass, TEST_STATE_ENTITY_ID, "double")
|
|
|
|
state = hass.states.get(TEST_EVENT.entity_id)
|
|
|
|
assert state.attributes[key] == expected
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("count", "event_type_template", "extra_config"),
|
|
[(1, "{{ None }}", None)],
|
|
)
|
|
@pytest.mark.parametrize(
|
|
"style",
|
|
[ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER],
|
|
)
|
|
@pytest.mark.parametrize(
|
|
("event_types_template", "expected"),
|
|
[
|
|
(
|
|
"{{ ['Strobe color', 'Police', 'Christmas', 'RGB', 'Random Loop'] }}",
|
|
["Strobe color", "Police", "Christmas", "RGB", "Random Loop"],
|
|
),
|
|
(
|
|
"{{ ['Police', 'RGB', 'Random Loop'] }}",
|
|
["Police", "RGB", "Random Loop"],
|
|
),
|
|
("{{ [] }}", []),
|
|
("{{ '[]' }}", []),
|
|
("{{ 124 }}", []),
|
|
("{{ '124' }}", []),
|
|
("{{ none }}", []),
|
|
("", []),
|
|
],
|
|
)
|
|
@pytest.mark.usefixtures("setup_event")
|
|
async def test_event_types_template(hass: HomeAssistant, expected: str) -> None:
|
|
"""Test template event_types."""
|
|
await async_trigger(hass, TEST_STATE_ENTITY_ID, "anything")
|
|
|
|
state = hass.states.get(TEST_EVENT.entity_id)
|
|
assert state.attributes["event_types"] == expected
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("count", "event_type_template", "event_types_template", "extra_config"),
|
|
[
|
|
(
|
|
1,
|
|
"{{ states('sensor.test_state') }}",
|
|
"{{ state_attr('sensor.test_state', 'options') or ['unknown'] }}",
|
|
None,
|
|
)
|
|
],
|
|
)
|
|
@pytest.mark.parametrize(
|
|
"style",
|
|
[ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER],
|
|
)
|
|
@pytest.mark.usefixtures("setup_event")
|
|
@pytest.mark.freeze_time(TEST_FROZEN_INPUT)
|
|
async def test_event_types_template_updates(hass: HomeAssistant) -> None:
|
|
"""Test template event_type update with entity."""
|
|
await async_trigger(
|
|
hass, TEST_STATE_ENTITY_ID, "single", {"options": ["single", "double", "hold"]}
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
state = hass.states.get(TEST_EVENT.entity_id)
|
|
assert state.state == TEST_FROZEN_STATE
|
|
assert state.attributes["event_type"] == "single"
|
|
assert state.attributes["event_types"] == ["single", "double", "hold"]
|
|
|
|
await async_trigger(
|
|
hass, TEST_STATE_ENTITY_ID, "double", {"options": ["double", "hold"]}
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
state = hass.states.get(TEST_EVENT.entity_id)
|
|
assert state.state == TEST_FROZEN_STATE
|
|
assert state.attributes["event_type"] == "double"
|
|
assert state.attributes["event_types"] == ["double", "hold"]
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
(
|
|
"count",
|
|
"event_type_template",
|
|
"event_types_template",
|
|
"attribute",
|
|
"attribute_template",
|
|
),
|
|
[
|
|
(
|
|
1,
|
|
"{{ states('sensor.test_state') }}",
|
|
TEST_EVENT_TYPES_TEMPLATE,
|
|
"availability",
|
|
"{{ states('sensor.test_state') in ['single', 'double', 'hold'] }}",
|
|
)
|
|
],
|
|
)
|
|
@pytest.mark.parametrize(
|
|
"style",
|
|
[ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER],
|
|
)
|
|
@pytest.mark.usefixtures("setup_single_attribute_state_event")
|
|
async def test_available_template_with_entities(hass: HomeAssistant) -> None:
|
|
"""Test availability templates with values from other entities."""
|
|
await async_trigger(hass, TEST_STATE_ENTITY_ID, "single")
|
|
|
|
state = hass.states.get(TEST_EVENT.entity_id)
|
|
assert state.state != STATE_UNAVAILABLE
|
|
assert state.attributes["event_type"] == "single"
|
|
|
|
await async_trigger(hass, TEST_STATE_ENTITY_ID, "triple")
|
|
|
|
state = hass.states.get(TEST_EVENT.entity_id)
|
|
assert state.state == STATE_UNAVAILABLE
|
|
assert "event_type" not in state.attributes
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"style", [ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER]
|
|
)
|
|
@pytest.mark.parametrize(
|
|
"config",
|
|
[
|
|
{
|
|
"event_type": "{{ states('sensor.test_state') }}",
|
|
"event_types": TEST_EVENT_TYPES_TEMPLATE,
|
|
"attributes": {
|
|
"plus_one": "{{ states('sensor.test_attribute') | int(0) + 1 }}",
|
|
"plus_two": "{{ states('sensor.test_attribute') | int(0) + 2 }}",
|
|
},
|
|
},
|
|
],
|
|
)
|
|
async def test_restore_state(
|
|
hass: HomeAssistant,
|
|
style: ConfigurationStyle,
|
|
config: dict,
|
|
) -> None:
|
|
"""Test restoring template event entities."""
|
|
|
|
# Ensure the initial state is None so that restore data is honored
|
|
await async_trigger(hass, TEST_STATE_ENTITY_ID, None)
|
|
|
|
restored_attributes = {
|
|
"plus_one": 55,
|
|
}
|
|
setup_mock_template_entity_restore_state(
|
|
hass,
|
|
TEST_EVENT,
|
|
"2021-01-01T23:59:59.123+00:00",
|
|
saved_extra_data={
|
|
"last_event_type": "hold",
|
|
"last_event_attributes": restored_attributes,
|
|
},
|
|
saved_attributes=restored_attributes,
|
|
)
|
|
await setup_restore_template_entity(
|
|
hass, TEST_EVENT, style, config, "is_state('sensor.test_attribute', '2')"
|
|
)
|
|
|
|
test_state = "2021-01-01T23:59:59.123+00:00"
|
|
state = assert_state_and_attributes(
|
|
hass,
|
|
TEST_EVENT,
|
|
test_state,
|
|
{**restored_attributes, **RESTORE_STATE_SAVED_ATTRIBUTES},
|
|
)
|
|
assert "plus_two" not in state.attributes
|
|
|
|
await async_trigger(hass, TEST_STATE_ENTITY_ID, "double")
|
|
await async_trigger(hass, TEST_ATTRIBUTE_ENTITY_ID, 2)
|
|
|
|
state = assert_state_and_attributes(
|
|
hass,
|
|
TEST_EVENT,
|
|
expected_attributes={
|
|
"plus_one": 3,
|
|
"plus_two": 4,
|
|
"event_type": "double",
|
|
"event_types": ["single", "double", "hold"],
|
|
**RESTORE_STATE_UPDATED_ATTRIBUTES,
|
|
},
|
|
)
|
|
assert state.state != test_state
|
|
|
|
|
|
def _make_trigger_event_entity(hass: HomeAssistant) -> TriggerEventEntity:
|
|
"""Create a trigger event entity that renders fresh, static attributes."""
|
|
config = {
|
|
CONF_NAME: Template("fresh_name", hass),
|
|
CONF_ICON: Template("mdi:fresh", hass),
|
|
CONF_PICTURE: Template("/local/fresh.png", hass),
|
|
CONF_EVENT_TYPE: Template("fresh", hass),
|
|
CONF_EVENT_TYPES: Template("{{ ['fresh'] }}", hass),
|
|
CONF_ATTRIBUTES: {"attr": Template("fresh_attr", hass)},
|
|
}
|
|
coordinator = TriggerUpdateCoordinator(hass, {})
|
|
entity = TriggerEventEntity(hass, coordinator, config)
|
|
entity.entity_id = "event.test"
|
|
entity.platform = MockEntityPlatform(hass)
|
|
return entity
|
|
|
|
|
|
def _mock_stale_restore_cache(hass: HomeAssistant) -> None:
|
|
"""Prime the restore cache with stale attributes for the test entity."""
|
|
mock_restore_cache(
|
|
hass,
|
|
(
|
|
State(
|
|
"event.test",
|
|
"2021-01-01T00:00:00+00:00",
|
|
{
|
|
ATTR_FRIENDLY_NAME: "stale_name",
|
|
ATTR_ICON: "mdi:stale",
|
|
ATTR_ENTITY_PICTURE: "/local/stale.png",
|
|
"attr": "stale_attr",
|
|
},
|
|
),
|
|
),
|
|
)
|
|
|
|
|
|
async def test_trigger_restore_does_not_clobber_rendered_attributes(
|
|
hass: HomeAssistant,
|
|
) -> None:
|
|
"""A trigger that already fired must win over restored state.
|
|
|
|
Regression test for the race where the trigger fires (populating the
|
|
coordinator) before the entity is added to hass. ``_process_data`` renders
|
|
fresh attributes which restore would otherwise overwrite with stale values.
|
|
"""
|
|
entity = _make_trigger_event_entity(hass)
|
|
# Simulate the trigger having already fired before the entity is added.
|
|
entity.coordinator._execute_update({})
|
|
assert entity.coordinator.data is not None
|
|
|
|
_mock_stale_restore_cache(hass)
|
|
|
|
await entity.async_added_to_hass()
|
|
await hass.async_block_till_done()
|
|
|
|
# The freshly rendered values must win over the stale restored ones.
|
|
assert entity.name == "fresh_name"
|
|
assert entity.icon == "mdi:fresh"
|
|
assert entity.entity_picture == "/local/fresh.png"
|
|
assert entity.extra_state_attributes == {"attr": "fresh_attr"}
|
|
|
|
|
|
async def test_trigger_restores_when_not_yet_triggered(
|
|
hass: HomeAssistant,
|
|
) -> None:
|
|
"""When the trigger has not fired, restored attributes are applied."""
|
|
entity = _make_trigger_event_entity(hass)
|
|
assert entity.coordinator.data is None
|
|
|
|
_mock_stale_restore_cache(hass)
|
|
|
|
await entity.async_added_to_hass()
|
|
await hass.async_block_till_done()
|
|
|
|
# No fresh data yet, so the restored values are surfaced.
|
|
assert entity.name == "stale_name"
|
|
assert entity.icon == "mdi:stale"
|
|
assert entity.entity_picture == "/local/stale.png"
|
|
assert entity.extra_state_attributes == {"attr": "stale_attr"}
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
(
|
|
"count",
|
|
"event_type_template",
|
|
"event_types_template",
|
|
"attribute",
|
|
"attribute_template",
|
|
),
|
|
[
|
|
(
|
|
1,
|
|
TEST_EVENT_TYPE_TEMPLATE,
|
|
TEST_EVENT_TYPES_TEMPLATE,
|
|
"availability",
|
|
"{{ x - 12 }}",
|
|
)
|
|
],
|
|
)
|
|
@pytest.mark.parametrize(
|
|
"style",
|
|
[ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER],
|
|
)
|
|
@pytest.mark.usefixtures("setup_single_attribute_state_event")
|
|
async def test_invalid_availability_template_keeps_component_available(
|
|
hass: HomeAssistant,
|
|
caplog: pytest.LogCaptureFixture,
|
|
caplog_setup_text,
|
|
) -> None:
|
|
"""Test that an invalid availability keeps the device available."""
|
|
await async_trigger(hass, TEST_STATE_ENTITY_ID, "anything")
|
|
|
|
assert hass.states.get(TEST_EVENT.entity_id).state != STATE_UNAVAILABLE
|
|
|
|
error = "UndefinedError: 'x' is undefined"
|
|
assert error in caplog_setup_text or error in caplog.text
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"style",
|
|
[ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER],
|
|
)
|
|
async def test_unique_id(hass: HomeAssistant, style: ConfigurationStyle) -> None:
|
|
"""Test unique_id option only creates one event per id."""
|
|
await setup_and_test_unique_id(hass, TEST_EVENT, style, TEST_EVENT_CONFIG)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"style", [ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER]
|
|
)
|
|
async def test_nested_unique_id(
|
|
hass: HomeAssistant,
|
|
style: ConfigurationStyle,
|
|
entity_registry: er.EntityRegistry,
|
|
) -> None:
|
|
"""Test a template unique_id propagates to event unique_ids."""
|
|
await setup_and_test_nested_unique_id(
|
|
hass, TEST_EVENT, style, entity_registry, TEST_EVENT_CONFIG
|
|
)
|
|
|
|
|
|
@pytest.mark.freeze_time(TEST_FROZEN_INPUT)
|
|
async def test_flow_preview(
|
|
hass: HomeAssistant,
|
|
hass_ws_client: WebSocketGenerator,
|
|
) -> None:
|
|
"""Test the config flow preview."""
|
|
|
|
state = await async_get_flow_preview_state(
|
|
hass,
|
|
hass_ws_client,
|
|
event.DOMAIN,
|
|
{"name": "My template", **TEST_EVENT_CONFIG},
|
|
)
|
|
|
|
assert state["state"] == TEST_FROZEN_STATE
|
|
assert state["attributes"]["event_type"] == "single"
|
|
assert state["attributes"]["event_types"] == ["single", "double", "hold"]
|