Skip to content

Commit ef4062a

Browse files
emontnemeryfrenck
authored andcommitted
Improve helpers.trigger.async_subscribe_platform_events (home-assistant#157709)
1 parent e31cce5 commit ef4062a

File tree

2 files changed

+135
-1
lines changed

2 files changed

+135
-1
lines changed

homeassistant/helpers/trigger.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,12 @@ def remove_subscription() -> None:
169169
async def _register_trigger_platform(
170170
hass: HomeAssistant, integration_domain: str, platform: TriggerProtocol
171171
) -> None:
172-
"""Register a trigger platform."""
172+
"""Register a trigger platform and notify listeners.
173+
174+
If the trigger platform does not provide any triggers, or it is disabled,
175+
listeners will not be notified.
176+
"""
177+
from homeassistant.components import automation # noqa: PLC0415
173178

174179
new_triggers: set[str] = set()
175180

@@ -178,6 +183,12 @@ async def _register_trigger_platform(
178183
trigger_key = get_absolute_description_key(integration_domain, trigger_key)
179184
hass.data[TRIGGERS][trigger_key] = integration_domain
180185
new_triggers.add(trigger_key)
186+
if not new_triggers:
187+
_LOGGER.debug(
188+
"Integration %s returned no triggers in async_get_triggers",
189+
integration_domain,
190+
)
191+
return
181192
elif hasattr(platform, "async_validate_trigger_config") or hasattr(
182193
platform, "TRIGGER_SCHEMA"
183194
):
@@ -190,6 +201,10 @@ async def _register_trigger_platform(
190201
)
191202
return
192203

204+
if automation.is_disabled_experimental_trigger(hass, integration_domain):
205+
_LOGGER.debug("Triggers for integration %s are disabled", integration_domain)
206+
return
207+
193208
# We don't use gather here because gather adds additional overhead
194209
# when wrapping each coroutine in a task, and we expect our listeners
195210
# to call trigger.async_get_all_descriptions which will only yield

tests/helpers/test_trigger.py

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,3 +1006,122 @@ async def good_subscriber(new_triggers: set[str]):
10061006
assert await async_setup_component(hass, "sun", {})
10071007
assert trigger_events == [{"sun"}]
10081008
assert "Error while notifying trigger platform listener" in caplog.text
1009+
1010+
1011+
@patch("annotatedyaml.loader.load_yaml")
1012+
@patch.object(Integration, "has_triggers", return_value=True)
1013+
@pytest.mark.parametrize(
1014+
("new_triggers_conditions_enabled", "expected_events"),
1015+
[
1016+
(True, [{"light.turned_off", "light.turned_on"}]),
1017+
(False, []),
1018+
],
1019+
)
1020+
async def test_subscribe_triggers_experimental_triggers(
1021+
mock_has_triggers: Mock,
1022+
mock_load_yaml: Mock,
1023+
hass: HomeAssistant,
1024+
hass_ws_client: WebSocketGenerator,
1025+
caplog: pytest.LogCaptureFixture,
1026+
new_triggers_conditions_enabled: bool,
1027+
expected_events: list[set[str]],
1028+
) -> None:
1029+
"""Test trigger.async_subscribe_platform_events doesn't send events for disabled triggers."""
1030+
# Return empty triggers.yaml for light integration, the actual trigger descriptions
1031+
# are irrelevant for this test
1032+
light_trigger_descriptions = ""
1033+
1034+
def _load_yaml(fname, secrets=None):
1035+
if fname.endswith("light/triggers.yaml"):
1036+
trigger_descriptions = light_trigger_descriptions
1037+
else:
1038+
raise FileNotFoundError
1039+
with io.StringIO(trigger_descriptions) as file:
1040+
return parse_yaml(file)
1041+
1042+
mock_load_yaml.side_effect = _load_yaml
1043+
1044+
trigger_events = []
1045+
1046+
async def good_subscriber(new_triggers: set[str]):
1047+
"""Simulate a working subscriber."""
1048+
trigger_events.append(new_triggers)
1049+
1050+
ws_client = await hass_ws_client(hass)
1051+
1052+
assert await async_setup_component(hass, "labs", {})
1053+
await ws_client.send_json_auto_id(
1054+
{
1055+
"type": "labs/update",
1056+
"domain": "automation",
1057+
"preview_feature": "new_triggers_conditions",
1058+
"enabled": new_triggers_conditions_enabled,
1059+
}
1060+
)
1061+
1062+
msg = await ws_client.receive_json()
1063+
assert msg["success"]
1064+
await hass.async_block_till_done()
1065+
1066+
trigger.async_subscribe_platform_events(hass, good_subscriber)
1067+
1068+
assert await async_setup_component(hass, "light", {})
1069+
await hass.async_block_till_done()
1070+
assert trigger_events == expected_events
1071+
1072+
1073+
@patch("annotatedyaml.loader.load_yaml")
1074+
@patch.object(Integration, "has_triggers", return_value=True)
1075+
@patch(
1076+
"homeassistant.components.light.trigger.async_get_triggers",
1077+
new=AsyncMock(return_value={}),
1078+
)
1079+
async def test_subscribe_triggers_no_triggers(
1080+
mock_has_triggers: Mock,
1081+
mock_load_yaml: Mock,
1082+
hass: HomeAssistant,
1083+
hass_ws_client: WebSocketGenerator,
1084+
caplog: pytest.LogCaptureFixture,
1085+
) -> None:
1086+
"""Test trigger.async_subscribe_platform_events doesn't send events for platforms without triggers."""
1087+
# Return empty triggers.yaml for light integration, the actual trigger descriptions
1088+
# are irrelevant for this test
1089+
light_trigger_descriptions = ""
1090+
1091+
def _load_yaml(fname, secrets=None):
1092+
if fname.endswith("light/triggers.yaml"):
1093+
trigger_descriptions = light_trigger_descriptions
1094+
else:
1095+
raise FileNotFoundError
1096+
with io.StringIO(trigger_descriptions) as file:
1097+
return parse_yaml(file)
1098+
1099+
mock_load_yaml.side_effect = _load_yaml
1100+
1101+
trigger_events = []
1102+
1103+
async def good_subscriber(new_triggers: set[str]):
1104+
"""Simulate a working subscriber."""
1105+
trigger_events.append(new_triggers)
1106+
1107+
ws_client = await hass_ws_client(hass)
1108+
1109+
assert await async_setup_component(hass, "labs", {})
1110+
await ws_client.send_json_auto_id(
1111+
{
1112+
"type": "labs/update",
1113+
"domain": "automation",
1114+
"preview_feature": "new_triggers_conditions",
1115+
"enabled": True,
1116+
}
1117+
)
1118+
1119+
msg = await ws_client.receive_json()
1120+
assert msg["success"]
1121+
await hass.async_block_till_done()
1122+
1123+
trigger.async_subscribe_platform_events(hass, good_subscriber)
1124+
1125+
assert await async_setup_component(hass, "light", {})
1126+
await hass.async_block_till_done()
1127+
assert trigger_events == []

0 commit comments

Comments
 (0)