forked from home-assistant/core
Exclude triggers without description from WS command response
This commit is contained in:
@@ -536,7 +536,13 @@ async def _async_get_all_trigger_descriptions_json(hass: HomeAssistant) -> bytes
|
|||||||
# If the descriptions are the same, return the cached JSON payload
|
# If the descriptions are the same, return the cached JSON payload
|
||||||
if cached_descriptions is descriptions:
|
if cached_descriptions is descriptions:
|
||||||
return cast(bytes, cached_json_payload)
|
return cast(bytes, cached_json_payload)
|
||||||
json_payload = json_bytes(descriptions)
|
json_payload = json_bytes(
|
||||||
|
{
|
||||||
|
trigger: description
|
||||||
|
for trigger, description in descriptions.items()
|
||||||
|
if description is not None
|
||||||
|
}
|
||||||
|
)
|
||||||
hass.data[ALL_TRIGGER_DESCRIPTIONS_JSON_CACHE] = (descriptions, json_payload)
|
hass.data[ALL_TRIGGER_DESCRIPTIONS_JSON_CACHE] = (descriptions, json_payload)
|
||||||
return json_payload
|
return json_payload
|
||||||
|
|
||||||
@@ -553,8 +559,10 @@ async def handle_subscribe_trigger_platforms(
|
|||||||
descriptions = await async_get_all_trigger_descriptions(hass)
|
descriptions = await async_get_all_trigger_descriptions(hass)
|
||||||
new_trigger_descriptions = {}
|
new_trigger_descriptions = {}
|
||||||
for trigger in new_triggers:
|
for trigger in new_triggers:
|
||||||
if trigger in descriptions:
|
if (description := descriptions[trigger]) is not None:
|
||||||
new_trigger_descriptions[trigger] = descriptions[trigger]
|
new_trigger_descriptions[trigger] = description
|
||||||
|
if not new_trigger_descriptions:
|
||||||
|
return
|
||||||
connection.send_event(msg["id"], new_trigger_descriptions)
|
connection.send_event(msg["id"], new_trigger_descriptions)
|
||||||
|
|
||||||
connection.subscriptions[msg["id"]] = async_subscribe_trigger_platform_events(
|
connection.subscriptions[msg["id"]] = async_subscribe_trigger_platform_events(
|
||||||
|
@@ -60,7 +60,7 @@ DATA_PLUGGABLE_ACTIONS: HassKey[defaultdict[tuple, PluggableActionsEntry]] = Has
|
|||||||
"pluggable_actions"
|
"pluggable_actions"
|
||||||
)
|
)
|
||||||
|
|
||||||
TRIGGER_DESCRIPTION_CACHE: HassKey[dict[str, dict[str, Any]]] = HassKey(
|
TRIGGER_DESCRIPTION_CACHE: HassKey[dict[str, dict[str, Any] | None]] = HassKey(
|
||||||
"trigger_description_cache"
|
"trigger_description_cache"
|
||||||
)
|
)
|
||||||
TRIGGER_PLATFORM_SUBSCRIPTIONS: HassKey[
|
TRIGGER_PLATFORM_SUBSCRIPTIONS: HassKey[
|
||||||
@@ -550,7 +550,7 @@ def _load_triggers_files(
|
|||||||
|
|
||||||
async def async_get_all_descriptions(
|
async def async_get_all_descriptions(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
) -> dict[str, dict[str, Any]]:
|
) -> dict[str, dict[str, Any] | None]:
|
||||||
"""Return descriptions (i.e. user documentation) for all triggers."""
|
"""Return descriptions (i.e. user documentation) for all triggers."""
|
||||||
descriptions_cache = hass.data[TRIGGER_DESCRIPTION_CACHE]
|
descriptions_cache = hass.data[TRIGGER_DESCRIPTION_CACHE]
|
||||||
|
|
||||||
@@ -599,12 +599,17 @@ async def async_get_all_descriptions(
|
|||||||
for missing_trigger in missing_triggers:
|
for missing_trigger in missing_triggers:
|
||||||
domain = triggers[missing_trigger]
|
domain = triggers[missing_trigger]
|
||||||
|
|
||||||
# Cache missing descriptions
|
if (
|
||||||
domain_yaml = new_triggers_descriptions.get(domain) or {}
|
yaml_description := new_triggers_descriptions.get(domain, {}).get( # type: ignore[union-attr]
|
||||||
|
missing_trigger
|
||||||
yaml_description = (
|
)
|
||||||
domain_yaml.get(missing_trigger) or {} # type: ignore[union-attr]
|
) is None:
|
||||||
)
|
_LOGGER.debug(
|
||||||
|
"No trigger descriptions found for trigger %s, skipping",
|
||||||
|
missing_trigger,
|
||||||
|
)
|
||||||
|
new_descriptions_cache[missing_trigger] = None
|
||||||
|
continue
|
||||||
|
|
||||||
description = {"fields": yaml_description.get("fields", {})}
|
description = {"fields": yaml_description.get("fields", {})}
|
||||||
|
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
|
import io
|
||||||
import logging
|
import logging
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from unittest.mock import ANY, AsyncMock, Mock, patch
|
from unittest.mock import ANY, AsyncMock, Mock, patch
|
||||||
@@ -28,9 +29,10 @@ from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
|
|||||||
from homeassistant.helpers import device_registry as dr
|
from homeassistant.helpers import device_registry as dr
|
||||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||||
from homeassistant.helpers.event import async_track_state_change_event
|
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.setup import async_set_domains_to_be_loaded, async_setup_component
|
||||||
from homeassistant.util.json import json_loads
|
from homeassistant.util.json import json_loads
|
||||||
|
from homeassistant.util.yaml.loader import parse_yaml
|
||||||
|
|
||||||
from tests.common import (
|
from tests.common import (
|
||||||
MockConfigEntry,
|
MockConfigEntry,
|
||||||
@@ -680,10 +682,34 @@ async def test_get_services(
|
|||||||
assert msg["result"].keys() == hass.services.async_services().keys()
|
assert msg["result"].keys() == hass.services.async_services().keys()
|
||||||
|
|
||||||
|
|
||||||
|
@patch("annotatedyaml.loader.load_yaml")
|
||||||
|
@patch.object(Integration, "has_triggers", return_value=True)
|
||||||
async def test_subscribe_triggers(
|
async def test_subscribe_triggers(
|
||||||
hass: HomeAssistant, websocket_client: MockHAClientWebSocket
|
mock_has_triggers: Mock,
|
||||||
|
mock_load_yaml: Mock,
|
||||||
|
hass: HomeAssistant,
|
||||||
|
websocket_client: MockHAClientWebSocket,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test get_triggers command."""
|
"""Test get_triggers command."""
|
||||||
|
sun_service_descriptions = """
|
||||||
|
sun: {}
|
||||||
|
"""
|
||||||
|
tag_service_descriptions = """
|
||||||
|
tag: {}
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _load_yaml(fname, secrets=None):
|
||||||
|
if fname.endswith("sun/triggers.yaml"):
|
||||||
|
service_descriptions = sun_service_descriptions
|
||||||
|
elif fname.endswith("tag/triggers.yaml"):
|
||||||
|
service_descriptions = tag_service_descriptions
|
||||||
|
else:
|
||||||
|
raise FileNotFoundError
|
||||||
|
with io.StringIO(service_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, "sun", {})
|
||||||
assert await async_setup_component(hass, "system_health", {})
|
assert await async_setup_component(hass, "system_health", {})
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
@@ -700,8 +726,10 @@ async def test_subscribe_triggers(
|
|||||||
|
|
||||||
old_cache = hass.data[ALL_TRIGGER_DESCRIPTIONS_JSON_CACHE]
|
old_cache = hass.data[ALL_TRIGGER_DESCRIPTIONS_JSON_CACHE]
|
||||||
|
|
||||||
# Test we receive an event when a new platform is loaded
|
# 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", {})
|
assert await async_setup_component(hass, "tag", {})
|
||||||
|
await hass.async_block_till_done()
|
||||||
msg = await websocket_client.receive_json()
|
msg = await websocket_client.receive_json()
|
||||||
assert msg == {
|
assert msg == {
|
||||||
"event": {"tag": {"fields": {}}},
|
"event": {"tag": {"fields": {}}},
|
||||||
|
@@ -478,8 +478,6 @@ async def test_async_get_all_descriptions(
|
|||||||
hass: HomeAssistant, sun_service_descriptions: str
|
hass: HomeAssistant, sun_service_descriptions: str
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test async_get_all_descriptions."""
|
"""Test async_get_all_descriptions."""
|
||||||
await trigger.async_setup(hass) # Move to hass fixture
|
|
||||||
|
|
||||||
assert await async_setup_component(hass, DOMAIN_SUN, {})
|
assert await async_setup_component(hass, DOMAIN_SUN, {})
|
||||||
assert await async_setup_component(hass, DOMAIN_SYSTEM_HEALTH, {})
|
assert await async_setup_component(hass, DOMAIN_SYSTEM_HEALTH, {})
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
@@ -546,8 +544,6 @@ async def test_async_get_all_descriptions_with_yaml_error(
|
|||||||
expected_message: str,
|
expected_message: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test async_get_all_descriptions."""
|
"""Test async_get_all_descriptions."""
|
||||||
await trigger.async_setup(hass) # Move to hass fixture
|
|
||||||
|
|
||||||
assert await async_setup_component(hass, DOMAIN_SUN, {})
|
assert await async_setup_component(hass, DOMAIN_SUN, {})
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
@@ -563,7 +559,7 @@ async def test_async_get_all_descriptions_with_yaml_error(
|
|||||||
):
|
):
|
||||||
descriptions = await trigger.async_get_all_descriptions(hass)
|
descriptions = await trigger.async_get_all_descriptions(hass)
|
||||||
|
|
||||||
assert descriptions == {DOMAIN_SUN: {"fields": {}}}
|
assert descriptions == {DOMAIN_SUN: None}
|
||||||
|
|
||||||
assert expected_message in caplog.text
|
assert expected_message in caplog.text
|
||||||
|
|
||||||
@@ -578,8 +574,6 @@ async def test_async_get_all_descriptions_with_bad_description(
|
|||||||
fields: not_a_dict
|
fields: not_a_dict
|
||||||
"""
|
"""
|
||||||
|
|
||||||
await trigger.async_setup(hass) # Move to hass fixture
|
|
||||||
|
|
||||||
assert await async_setup_component(hass, DOMAIN_SUN, {})
|
assert await async_setup_component(hass, DOMAIN_SUN, {})
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
@@ -596,7 +590,7 @@ async def test_async_get_all_descriptions_with_bad_description(
|
|||||||
):
|
):
|
||||||
descriptions = await trigger.async_get_all_descriptions(hass)
|
descriptions = await trigger.async_get_all_descriptions(hass)
|
||||||
|
|
||||||
assert descriptions == {DOMAIN_SUN: {"fields": {}}}
|
assert descriptions == {DOMAIN_SUN: None}
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
"Unable to parse triggers.yaml for the sun integration: "
|
"Unable to parse triggers.yaml for the sun integration: "
|
||||||
|
Reference in New Issue
Block a user