Files
core/tests/components/switch/test_trigger.py

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

216 lines
7.3 KiB
Python
Raw Permalink Normal View History

"""Test switch triggers."""
from typing import Any
import pytest
from homeassistant.components.switch import DOMAIN
from homeassistant.const import ATTR_LABEL_ID, CONF_ENTITY_ID, STATE_OFF, STATE_ON
from homeassistant.core import HomeAssistant, ServiceCall
from tests.components import (
TriggerStateDescription,
arm_trigger,
parametrize_target_entities,
parametrize_trigger_states,
set_or_remove_state,
target_entities,
)
@pytest.fixture
async def target_switches(hass: HomeAssistant) -> list[str]:
"""Create multiple switch entities associated with different targets."""
return (await target_entities(hass, DOMAIN))["included"]
@pytest.mark.parametrize(
"trigger_key",
[
"switch.turned_off",
"switch.turned_on",
],
)
async def test_switch_triggers_gated_by_labs_flag(
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, trigger_key: str
) -> None:
"""Test the switch triggers are gated by the labs flag."""
await arm_trigger(hass, trigger_key, None, {ATTR_LABEL_ID: "test_label"})
assert (
"Unnamed automation failed to setup triggers and has been disabled: Trigger "
f"'{trigger_key}' requires the experimental 'New triggers and conditions' "
"feature to be enabled in Home Assistant Labs settings (feature flag: "
"'new_triggers_conditions')"
) in caplog.text
@pytest.mark.usefixtures("enable_labs_preview_features")
@pytest.mark.parametrize(
("trigger_target_config", "entity_id", "entities_in_target"),
parametrize_target_entities(DOMAIN),
)
@pytest.mark.parametrize(
("trigger", "trigger_options", "states"),
[
*parametrize_trigger_states(
trigger="switch.turned_off",
target_states=[STATE_OFF],
other_states=[STATE_ON],
),
*parametrize_trigger_states(
trigger="switch.turned_on",
target_states=[STATE_ON],
other_states=[STATE_OFF],
),
],
)
async def test_switch_state_trigger_behavior_any(
hass: HomeAssistant,
service_calls: list[ServiceCall],
target_switches: list[str],
trigger_target_config: dict,
entity_id: str,
entities_in_target: int,
trigger: str,
trigger_options: dict[str, Any],
states: list[TriggerStateDescription],
) -> None:
"""Test that the switch state trigger fires when any switch state changes to a specific state."""
other_entity_ids = set(target_switches) - {entity_id}
# Set all switches, including the tested one, to the initial state
for eid in target_switches:
set_or_remove_state(hass, eid, states[0]["included"])
await hass.async_block_till_done()
await arm_trigger(hass, trigger, {}, trigger_target_config)
for state in states[1:]:
included_state = state["included"]
set_or_remove_state(hass, entity_id, included_state)
await hass.async_block_till_done()
assert len(service_calls) == state["count"]
for service_call in service_calls:
assert service_call.data[CONF_ENTITY_ID] == entity_id
service_calls.clear()
# Check if changing other switches also triggers
for other_entity_id in other_entity_ids:
set_or_remove_state(hass, other_entity_id, included_state)
await hass.async_block_till_done()
assert len(service_calls) == (entities_in_target - 1) * state["count"]
service_calls.clear()
@pytest.mark.usefixtures("enable_labs_preview_features")
@pytest.mark.parametrize(
("trigger_target_config", "entity_id", "entities_in_target"),
parametrize_target_entities(DOMAIN),
)
@pytest.mark.parametrize(
("trigger", "trigger_options", "states"),
[
*parametrize_trigger_states(
trigger="switch.turned_off",
target_states=[STATE_OFF],
other_states=[STATE_ON],
),
*parametrize_trigger_states(
trigger="switch.turned_on",
target_states=[STATE_ON],
other_states=[STATE_OFF],
),
],
)
async def test_switch_state_trigger_behavior_first(
hass: HomeAssistant,
service_calls: list[ServiceCall],
target_switches: list[str],
trigger_target_config: dict,
entity_id: str,
entities_in_target: int,
trigger: str,
trigger_options: dict[str, Any],
states: list[TriggerStateDescription],
) -> None:
"""Test that the switch state trigger fires when the first switch changes to a specific state."""
other_entity_ids = set(target_switches) - {entity_id}
# Set all switches, including the tested one, to the initial state
for eid in target_switches:
set_or_remove_state(hass, eid, states[0]["included"])
await hass.async_block_till_done()
await arm_trigger(hass, trigger, {"behavior": "first"}, trigger_target_config)
for state in states[1:]:
included_state = state["included"]
set_or_remove_state(hass, entity_id, included_state)
await hass.async_block_till_done()
assert len(service_calls) == state["count"]
for service_call in service_calls:
assert service_call.data[CONF_ENTITY_ID] == entity_id
service_calls.clear()
# Triggering other switches should not cause the trigger to fire again
for other_entity_id in other_entity_ids:
set_or_remove_state(hass, other_entity_id, included_state)
await hass.async_block_till_done()
assert len(service_calls) == 0
@pytest.mark.usefixtures("enable_labs_preview_features")
@pytest.mark.parametrize(
("trigger_target_config", "entity_id", "entities_in_target"),
parametrize_target_entities(DOMAIN),
)
@pytest.mark.parametrize(
("trigger", "trigger_options", "states"),
[
*parametrize_trigger_states(
trigger="switch.turned_off",
target_states=[STATE_OFF],
other_states=[STATE_ON],
),
*parametrize_trigger_states(
trigger="switch.turned_on",
target_states=[STATE_ON],
other_states=[STATE_OFF],
),
],
)
async def test_switch_state_trigger_behavior_last(
hass: HomeAssistant,
service_calls: list[ServiceCall],
target_switches: list[str],
trigger_target_config: dict,
entity_id: str,
entities_in_target: int,
trigger: str,
trigger_options: dict[str, Any],
states: list[TriggerStateDescription],
) -> None:
"""Test that the switch state trigger fires when the last switch changes to a specific state."""
other_entity_ids = set(target_switches) - {entity_id}
# Set all switches, including the tested one, to the initial state
for eid in target_switches:
set_or_remove_state(hass, eid, states[0]["included"])
await hass.async_block_till_done()
await arm_trigger(hass, trigger, {"behavior": "last"}, trigger_target_config)
for state in states[1:]:
included_state = state["included"]
for other_entity_id in other_entity_ids:
set_or_remove_state(hass, other_entity_id, included_state)
await hass.async_block_till_done()
assert len(service_calls) == 0
set_or_remove_state(hass, entity_id, included_state)
await hass.async_block_till_done()
assert len(service_calls) == state["count"]
for service_call in service_calls:
assert service_call.data[CONF_ENTITY_ID] == entity_id
service_calls.clear()