From b381922a20d50284f77a37df9e07a79af5834e38 Mon Sep 17 00:00:00 2001 From: RoboMagus <68224306+RoboMagus@users.noreply.github.com> Date: Mon, 4 Mar 2024 14:22:14 +0100 Subject: [PATCH] Issues template function (#95206) * Add 'issues' template function for listing active issues. * Add issue template function test * Add 'issue' template function for getting specific issue by domain and issue_id * Remove comment * Fix function description * Remove reduntant function, Fix tests * remove pass_context * remove issues filter Co-authored-by: Erik Montnemery --------- Co-authored-by: Erik Montnemery --- homeassistant/helpers/template.py | 28 +++++++++++++- tests/helpers/test_template.py | 62 +++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 1 deletion(-) diff --git a/homeassistant/helpers/template.py b/homeassistant/helpers/template.py index f7f12c59710..426ff3bed6f 100644 --- a/homeassistant/helpers/template.py +++ b/homeassistant/helpers/template.py @@ -78,7 +78,13 @@ from homeassistant.util.json import JSON_DECODE_EXCEPTIONS, json_loads from homeassistant.util.read_only_dict import ReadOnlyDict from homeassistant.util.thread import ThreadWithException -from . import area_registry, device_registry, entity_registry, location as loc_helper +from . import ( + area_registry, + device_registry, + entity_registry, + issue_registry, + location as loc_helper, +) from .singleton import singleton from .translation import async_translate_state from .typing import TemplateVarsType @@ -1357,6 +1363,21 @@ def is_device_attr( return bool(device_attr(hass, device_or_entity_id, attr_name) == attr_value) +def issues(hass: HomeAssistant) -> dict[tuple[str, str], dict[str, Any]]: + """Return all open issues.""" + current_issues = issue_registry.async_get(hass).issues + # Use JSON for safe representation + return {k: v.to_json() for (k, v) in current_issues.items()} + + +def issue(hass: HomeAssistant, domain: str, issue_id: str) -> dict[str, Any] | None: + """Get issue by domain and issue_id.""" + result = issue_registry.async_get(hass).async_get_issue(domain, issue_id) + if result: + return result.to_json() + return None + + def areas(hass: HomeAssistant) -> Iterable[str | None]: """Return all areas.""" area_reg = area_registry.async_get(hass) @@ -2619,6 +2640,11 @@ class TemplateEnvironment(ImmutableSandboxedEnvironment): self.globals["device_id"] = hassfunction(device_id) self.filters["device_id"] = self.globals["device_id"] + self.globals["issues"] = hassfunction(issues) + + self.globals["issue"] = hassfunction(issue) + self.filters["issue"] = self.globals["issue"] + self.globals["areas"] = hassfunction(areas) self.globals["area_id"] = hassfunction(area_id) diff --git a/tests/helpers/test_template.py b/tests/helpers/test_template.py index ab6d61bfe6c..6279ea0089a 100644 --- a/tests/helpers/test_template.py +++ b/tests/helpers/test_template.py @@ -37,6 +37,7 @@ from homeassistant.helpers import ( device_registry as dr, entity, entity_registry as er, + issue_registry as ir, template, translation, ) @@ -3512,6 +3513,67 @@ async def test_device_attr( assert info.rate_limit is None +async def test_issues(hass: HomeAssistant, issue_registry: ir.IssueRegistry) -> None: + """Test issues function.""" + # Test no issues + info = render_to_info(hass, "{{ issues() }}") + assert_result_info(info, {}) + assert info.rate_limit is None + + # Test persistent issue + ir.async_create_issue( + hass, + "test", + "issue 1", + breaks_in_ha_version="2023.7", + is_fixable=True, + is_persistent=True, + learn_more_url="https://theuselessweb.com", + severity="error", + translation_key="abc_1234", + translation_placeholders={"abc": "123"}, + ) + await hass.async_block_till_done() + created_issue = issue_registry.async_get_issue("test", "issue 1") + info = render_to_info(hass, "{{ issues()['test', 'issue 1'] }}") + assert_result_info(info, created_issue.to_json()) + assert info.rate_limit is None + + # Test fixed issue + ir.async_delete_issue(hass, "test", "issue 1") + await hass.async_block_till_done() + info = render_to_info(hass, "{{ issues() }}") + assert_result_info(info, {}) + assert info.rate_limit is None + + +async def test_issue(hass: HomeAssistant, issue_registry: ir.IssueRegistry) -> None: + """Test issue function.""" + # Test non existent issue + info = render_to_info(hass, "{{ issue('non_existent', 'issue') }}") + assert_result_info(info, None) + assert info.rate_limit is None + + # Test existing issue + ir.async_create_issue( + hass, + "test", + "issue 1", + breaks_in_ha_version="2023.7", + is_fixable=True, + is_persistent=True, + learn_more_url="https://theuselessweb.com", + severity="error", + translation_key="abc_1234", + translation_placeholders={"abc": "123"}, + ) + await hass.async_block_till_done() + created_issue = issue_registry.async_get_issue("test", "issue 1") + info = render_to_info(hass, "{{ issue('test', 'issue 1') }}") + assert_result_info(info, created_issue.to_json()) + assert info.rate_limit is None + + async def test_areas(hass: HomeAssistant, area_registry: ar.AreaRegistry) -> None: """Test areas function.""" # Test no areas