Allow core integrations to describe their triggers (#147075)

Co-authored-by: Abílio Costa <abmantis@users.noreply.github.com>
This commit is contained in:
Erik Montnemery
2025-06-25 18:35:15 +02:00
committed by GitHub
parent d8258924f7
commit 1fb587bf03
15 changed files with 908 additions and 13 deletions

View File

@@ -2,6 +2,7 @@
import asyncio
from copy import deepcopy
import io
import logging
from typing import Any
from unittest.mock import ANY, AsyncMock, Mock, patch
@@ -19,6 +20,7 @@ from homeassistant.components.websocket_api.auth import (
)
from homeassistant.components.websocket_api.commands import (
ALL_SERVICE_DESCRIPTIONS_JSON_CACHE,
ALL_TRIGGER_DESCRIPTIONS_JSON_CACHE,
)
from homeassistant.components.websocket_api.const import FEATURE_COALESCE_MESSAGES, URL
from homeassistant.config_entries import ConfigEntryState
@@ -28,9 +30,10 @@ from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.dispatcher import async_dispatcher_send
from homeassistant.helpers.event import async_track_state_change_event
from homeassistant.loader import async_get_integration
from homeassistant.loader import Integration, async_get_integration
from homeassistant.setup import async_set_domains_to_be_loaded, async_setup_component
from homeassistant.util.json import json_loads
from homeassistant.util.yaml.loader import parse_yaml
from tests.common import (
MockConfigEntry,
@@ -707,6 +710,91 @@ async def test_get_services(
assert hass.data[ALL_SERVICE_DESCRIPTIONS_JSON_CACHE] is old_cache
@patch("annotatedyaml.loader.load_yaml")
@patch.object(Integration, "has_triggers", return_value=True)
async def test_subscribe_triggers(
mock_has_triggers: Mock,
mock_load_yaml: Mock,
hass: HomeAssistant,
websocket_client: MockHAClientWebSocket,
) -> None:
"""Test trigger_platforms/subscribe command."""
sun_trigger_descriptions = """
sun: {}
"""
tag_trigger_descriptions = """
tag: {}
"""
def _load_yaml(fname, secrets=None):
if fname.endswith("sun/triggers.yaml"):
trigger_descriptions = sun_trigger_descriptions
elif fname.endswith("tag/triggers.yaml"):
trigger_descriptions = tag_trigger_descriptions
else:
raise FileNotFoundError
with io.StringIO(trigger_descriptions) as file:
return parse_yaml(file)
mock_load_yaml.side_effect = _load_yaml
assert await async_setup_component(hass, "sun", {})
assert await async_setup_component(hass, "system_health", {})
await hass.async_block_till_done()
assert ALL_TRIGGER_DESCRIPTIONS_JSON_CACHE not in hass.data
await websocket_client.send_json_auto_id({"type": "trigger_platforms/subscribe"})
# Test start subscription with initial event
msg = await websocket_client.receive_json()
assert msg == {"id": 1, "result": None, "success": True, "type": "result"}
msg = await websocket_client.receive_json()
assert msg == {"event": {"sun": {"fields": {}}}, "id": 1, "type": "event"}
old_cache = hass.data[ALL_TRIGGER_DESCRIPTIONS_JSON_CACHE]
# Test we receive an event when a new platform is loaded, if it has descriptions
assert await async_setup_component(hass, "calendar", {})
assert await async_setup_component(hass, "tag", {})
await hass.async_block_till_done()
msg = await websocket_client.receive_json()
assert msg == {
"event": {"tag": {"fields": {}}},
"id": 1,
"type": "event",
}
# Initiate a second subscription to check the cache is updated because of the new
# trigger
await websocket_client.send_json_auto_id({"type": "trigger_platforms/subscribe"})
msg = await websocket_client.receive_json()
assert msg == {"id": 2, "result": None, "success": True, "type": "result"}
msg = await websocket_client.receive_json()
assert msg == {
"event": {"sun": {"fields": {}}, "tag": {"fields": {}}},
"id": 2,
"type": "event",
}
assert hass.data[ALL_TRIGGER_DESCRIPTIONS_JSON_CACHE] is not old_cache
# Initiate a third subscription to check the cache is not updated because no new
# trigger was added
old_cache = hass.data[ALL_TRIGGER_DESCRIPTIONS_JSON_CACHE]
await websocket_client.send_json_auto_id({"type": "trigger_platforms/subscribe"})
msg = await websocket_client.receive_json()
assert msg == {"id": 3, "result": None, "success": True, "type": "result"}
msg = await websocket_client.receive_json()
assert msg == {
"event": {"sun": {"fields": {}}, "tag": {"fields": {}}},
"id": 3,
"type": "event",
}
assert hass.data[ALL_TRIGGER_DESCRIPTIONS_JSON_CACHE] is old_cache
async def test_get_config(
hass: HomeAssistant, websocket_client: MockHAClientWebSocket
) -> None: