Fix variables in icon, picture, and name for state based template entities (#154994)

This commit is contained in:
Petro31
2025-10-23 20:02:18 +01:00
committed by GitHub
parent e0d404456b
commit 312812dd8b
4 changed files with 180 additions and 1 deletions
@@ -200,7 +200,13 @@ class TemplateEntity(AbstractTemplateEntity):
"""Name of this state."""
return "<None>"
variables = {"this": DummyState()}
# Render the current variables and add a dummy this variable to them.
variables = (
self._run_variables
if isinstance(self._run_variables, dict)
else self._run_variables.async_render(self.hass, {})
)
variables = {"this": DummyState(), **variables}
# Try to render the name as it can influence the entity ID
self._attr_name = None
@@ -228,6 +228,90 @@ async def test_reload_template_when_blueprint_changes(hass: HomeAssistant) -> No
assert not_inverted.state == "on"
async def test_init_attribute_variables_from_blueprint(hass: HomeAssistant) -> None:
"""Test a state based blueprint initializes icon, name, and picture with variables."""
blueprint = "test_init_attribute_variables.yaml"
source = "switch.foo"
entity_id = "sensor.foo"
hass.states.async_set(source, "on", {"friendly_name": "Foo"})
config = {
DOMAIN: [
{
"use_blueprint": {
"path": blueprint,
"input": {"switch": source},
},
}
],
}
assert await async_setup_component(
hass,
DOMAIN,
config,
)
await hass.async_block_till_done()
# Check initial state
sensor = hass.states.get(entity_id)
assert sensor
assert sensor.state == "True"
assert sensor.attributes["icon"] == "mdi:lightbulb"
assert sensor.attributes["entity_picture"] == "on.png"
assert sensor.attributes["friendly_name"] == "Foo"
assert sensor.attributes["extra"] == "ab"
hass.states.async_set(source, "off", {"friendly_name": "Foo"})
await hass.async_block_till_done()
# Check to see that the template light works
sensor = hass.states.get(entity_id)
assert sensor
assert sensor.state == "False"
assert sensor.attributes["icon"] == "mdi:lightbulb-off"
assert sensor.attributes["entity_picture"] == "off.png"
assert sensor.attributes["friendly_name"] == "Foo"
assert sensor.attributes["extra"] == "ab"
# Reload the templates without any change, but with updated blueprint
blueprint_config = yaml_util.load_yaml(
pathlib.Path("tests/testing_config/blueprints/template/") / blueprint
)
blueprint_config["variables"]["extraa"] = "c"
blueprint_config["sensor"]["variables"]["extrab"] = "d"
with (
patch(
"homeassistant.config.load_yaml_config_file",
autospec=True,
return_value=config,
),
patch(
"homeassistant.components.blueprint.models.yaml_util.load_yaml_dict",
autospec=True,
return_value=blueprint_config,
),
):
await hass.services.async_call(DOMAIN, SERVICE_RELOAD, blocking=True)
sensor = hass.states.get(entity_id)
assert sensor
assert sensor.state == "False"
assert sensor.attributes["icon"] == "mdi:lightbulb-off"
assert sensor.attributes["entity_picture"] == "off.png"
assert sensor.attributes["friendly_name"] == "Foo"
assert sensor.attributes["extra"] == "cd"
hass.states.async_set(source, "on", {"friendly_name": "Foo"})
await hass.async_block_till_done()
sensor = hass.states.get(entity_id)
assert sensor
assert sensor.state == "True"
assert sensor.attributes["icon"] == "mdi:lightbulb"
assert sensor.attributes["entity_picture"] == "on.png"
assert sensor.attributes["friendly_name"] == "Foo"
assert sensor.attributes["extra"] == "cd"
@pytest.mark.parametrize(
("blueprint"),
["test_event_sensor.yaml", "test_event_sensor_legacy_schema.yaml"],
+58
View File
@@ -5,6 +5,7 @@ from __future__ import annotations
import pytest
import voluptuous as vol
from homeassistant.components.template import DOMAIN
from homeassistant.components.template.config import (
CONFIG_SECTION_SCHEMA,
async_validate_config_section,
@@ -12,6 +13,7 @@ from homeassistant.components.template.config import (
from homeassistant.core import HomeAssistant
from homeassistant.helpers.script_variables import ScriptVariables
from homeassistant.helpers.template import Template
from homeassistant.setup import async_setup_component
@pytest.mark.parametrize(
@@ -256,3 +258,59 @@ async def test_combined_trigger_variables(
assert root_variables.as_dict() == expected_root
variables: ScriptVariables = validated["binary_sensor"][0].get("variables", empty)
assert variables.as_dict() == expected_entity
async def test_state_init_attribute_variables(
hass: HomeAssistant,
) -> None:
"""Test a state based template entity initializes icon, name, and picture with variables."""
source = "switch.foo"
entity_id = "sensor.foo"
hass.states.async_set(source, "on", {"friendly_name": "Foo"})
config = {
"template": [
{
"variables": {
"switch": "switch.foo",
"on_icon": "mdi:lightbulb",
"on_picture": "on.png",
},
"sensor": {
"variables": {
"off_icon": "mdi:lightbulb-off",
"off_picture": "off.png",
},
"name": "{{ state_attr(switch, 'friendly_name') }}",
"icon": "{{ on_icon if is_state(switch, 'on') else off_icon }}",
"picture": "{{ on_picture if is_state(switch, 'on') else off_picture }}",
"state": "{{ is_state(switch, 'on') }}",
},
}
],
}
assert await async_setup_component(
hass,
DOMAIN,
config,
)
await hass.async_block_till_done()
# Check initial state
sensor = hass.states.get(entity_id)
assert sensor
assert sensor.state == "True"
assert sensor.attributes["icon"] == "mdi:lightbulb"
assert sensor.attributes["entity_picture"] == "on.png"
assert sensor.attributes["friendly_name"] == "Foo"
hass.states.async_set(source, "off", {"friendly_name": "Foo"})
await hass.async_block_till_done()
# Check to see that the template light works
sensor = hass.states.get(entity_id)
assert sensor
assert sensor.state == "False"
assert sensor.attributes["icon"] == "mdi:lightbulb-off"
assert sensor.attributes["entity_picture"] == "off.png"
assert sensor.attributes["friendly_name"] == "Foo"
@@ -0,0 +1,31 @@
blueprint:
name: Switch to light
domain: template
input:
switch:
name: Switch
description: The switch which should be converted
selector:
entity:
multiple: false
filter:
- domain: switch
default: null
variables:
switch: !input switch
on_icon: mdi:lightbulb
on_picture: "on.png"
extraa: "a"
sensor:
variables:
off_icon: mdi:lightbulb-off
off_picture: "off.png"
extrab: "b"
name: "{{ state_attr(switch, 'friendly_name') }}"
icon: "{{ on_icon if is_state(switch, 'on') else off_icon }}"
picture: "{{ on_picture if is_state(switch, 'on') else off_picture }}"
state: "{{ is_state(switch, 'on') }}"
attributes:
extra: "{{ extraa ~ extrab }}"