Improve test coverage

This commit is contained in:
Erik
2025-06-19 12:07:02 +02:00
parent 0b38535f6a
commit eb9adb7e12

View File

@@ -1,5 +1,6 @@
"""The tests for the trigger helper.""" """The tests for the trigger helper."""
import io
from unittest.mock import ANY, AsyncMock, MagicMock, call, patch from unittest.mock import ANY, AsyncMock, MagicMock, call, patch
import pytest import pytest
@@ -9,6 +10,7 @@ import voluptuous as vol
from homeassistant.components.sun import DOMAIN as DOMAIN_SUN from homeassistant.components.sun import DOMAIN as DOMAIN_SUN
from homeassistant.components.system_health import DOMAIN as DOMAIN_SYSTEM_HEALTH from homeassistant.components.system_health import DOMAIN as DOMAIN_SYSTEM_HEALTH
from homeassistant.core import Context, HomeAssistant, ServiceCall, callback from homeassistant.core import Context, HomeAssistant, ServiceCall, callback
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import trigger from homeassistant.helpers import trigger
from homeassistant.helpers.trigger import ( from homeassistant.helpers.trigger import (
DATA_PLUGGABLE_ACTIONS, DATA_PLUGGABLE_ACTIONS,
@@ -19,7 +21,7 @@ from homeassistant.helpers.trigger import (
) )
from homeassistant.loader import Integration, async_get_integration from homeassistant.loader import Integration, async_get_integration
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from homeassistant.util.yaml.loader import JSON_TYPE from homeassistant.util.yaml.loader import parse_yaml
async def test_bad_trigger_platform(hass: HomeAssistant) -> None: async def test_bad_trigger_platform(hass: HomeAssistant) -> None:
@@ -436,27 +438,53 @@ async def test_pluggable_action(
assert not plug_2 assert not plug_2
async def test_async_get_all_descriptions(hass: HomeAssistant) -> None: @pytest.mark.parametrize(
"sun_service_descriptions",
[
"""
sun:
fields:
event:
example: sunrise
selector:
select:
options:
- sunrise
- sunset
offset:
selector:
time: null
""",
"""
.anchor: &anchor
- sunrise
- sunset
sun:
fields:
event:
example: sunrise
selector:
select:
options: *anchor
offset:
selector:
time: null
""",
],
)
async def test_async_get_all_descriptions(
hass: HomeAssistant, sun_service_descriptions: str
) -> None:
"""Test async_get_all_descriptions.""" """Test async_get_all_descriptions."""
await trigger.async_setup(hass) # Move to hass fixture await trigger.async_setup(hass) # Move to hass fixture
sun_config = {DOMAIN_SUN: {}} assert await async_setup_component(hass, DOMAIN_SUN, {})
assert await async_setup_component(hass, DOMAIN_SUN, sun_config)
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()
def _load_triggers_file(hass: HomeAssistant, integration: Integration) -> JSON_TYPE: def _load_yaml(fname, secrets=None):
return { with io.StringIO(sun_service_descriptions) as file:
"sun": { return parse_yaml(file)
"fields": {
"event": {
"example": "sunrise",
"selector": {"select": {"options": ["sunrise", "sunset"]}},
},
"offset": {"selector": {"time": None}},
}
}
}
with ( with (
patch( patch(
@@ -464,14 +492,14 @@ async def test_async_get_all_descriptions(hass: HomeAssistant) -> None:
side_effect=trigger._load_triggers_files, side_effect=trigger._load_triggers_files,
) as proxy_load_triggers_files, ) as proxy_load_triggers_files,
patch( patch(
"homeassistant.helpers.trigger._load_triggers_file", "annotatedyaml.loader.load_yaml",
side_effect=_load_triggers_file, side_effect=_load_yaml,
), ),
patch.object(Integration, "has_triggers", return_value=True), patch.object(Integration, "has_triggers", return_value=True),
): ):
descriptions = await trigger.async_get_all_descriptions(hass) descriptions = await trigger.async_get_all_descriptions(hass)
# Test we only load triggers.yaml for integrations with triggers.yaml, # Test we only load triggers.yaml for integrations with triggers,
# system_health has no triggers # system_health has no triggers
assert proxy_load_triggers_files.mock_calls[0][1][1] == unordered( assert proxy_load_triggers_files.mock_calls[0][1][1] == unordered(
[ [
@@ -494,3 +522,81 @@ async def test_async_get_all_descriptions(hass: HomeAssistant) -> None:
# Verify the cache returns the same object # Verify the cache returns the same object
assert await trigger.async_get_all_descriptions(hass) is descriptions assert await trigger.async_get_all_descriptions(hass) is descriptions
@pytest.mark.parametrize(
("yaml_error", "expected_message"),
[
(
FileNotFoundError("Blah"),
"Unable to find triggers.yaml for the sun integration",
),
(
HomeAssistantError("Test error"),
"Unable to parse triggers.yaml for the sun integration: Test error",
),
],
)
async def test_async_get_all_descriptions_with_yaml_error(
hass: HomeAssistant,
caplog: pytest.LogCaptureFixture,
yaml_error: Exception,
expected_message: str,
) -> None:
"""Test async_get_all_descriptions."""
await trigger.async_setup(hass) # Move to hass fixture
assert await async_setup_component(hass, DOMAIN_SUN, {})
await hass.async_block_till_done()
def _load_yaml_dict(fname, secrets=None):
raise yaml_error
with (
patch(
"homeassistant.helpers.trigger.load_yaml_dict",
side_effect=_load_yaml_dict,
),
patch.object(Integration, "has_triggers", return_value=True),
):
descriptions = await trigger.async_get_all_descriptions(hass)
assert descriptions == {DOMAIN_SUN: {"fields": {}}}
assert expected_message in caplog.text
async def test_async_get_all_descriptions_with_bad_description(
hass: HomeAssistant,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test async_get_all_descriptions."""
sun_service_descriptions = """
sun:
fields: not_a_dict
"""
await trigger.async_setup(hass) # Move to hass fixture
assert await async_setup_component(hass, DOMAIN_SUN, {})
await hass.async_block_till_done()
def _load_yaml(fname, secrets=None):
with io.StringIO(sun_service_descriptions) as file:
return parse_yaml(file)
with (
patch(
"annotatedyaml.loader.load_yaml",
side_effect=_load_yaml,
),
patch.object(Integration, "has_triggers", return_value=True),
):
descriptions = await trigger.async_get_all_descriptions(hass)
assert descriptions == {DOMAIN_SUN: {"fields": {}}}
assert (
"Unable to parse triggers.yaml for the sun integration: "
"expected a dictionary for dictionary value @ data['sun']['fields']"
) in caplog.text