mirror of
				https://github.com/home-assistant/core.git
				synced 2025-11-04 00:19:31 +00:00 
			
		
		
		
	Compare commits
	
		
			18 Commits
		
	
	
		
			2025.11.0b
			...
			manual_tri
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					635669278c | ||
| 
						 | 
					1c5eb92c9c | ||
| 
						 | 
					3337dd4ed7 | ||
| 
						 | 
					f1d21685e6 | ||
| 
						 | 
					73f27549e4 | ||
| 
						 | 
					1882b914dc | ||
| 
						 | 
					06f99dc9ba | ||
| 
						 | 
					2e2c718d94 | ||
| 
						 | 
					b8f56a6ed6 | ||
| 
						 | 
					db37dbec03 | ||
| 
						 | 
					579f44468e | ||
| 
						 | 
					d452e957c9 | ||
| 
						 | 
					5f9bcd583b | ||
| 
						 | 
					c0c508c7a2 | ||
| 
						 | 
					13f5adfa84 | ||
| 
						 | 
					a07a3a61bf | ||
| 
						 | 
					848162debd | ||
| 
						 | 
					07cd669bc1 | 
@@ -121,6 +121,7 @@ class TriggerBaseEntity(Entity):
 | 
			
		||||
        self._rendered = dict(self._static_rendered)
 | 
			
		||||
        self._parse_result = {CONF_AVAILABILITY}
 | 
			
		||||
        self._attr_device_class = config.get(CONF_DEVICE_CLASS)
 | 
			
		||||
        self._render_error = False
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def name(self) -> str | None:
 | 
			
		||||
@@ -146,7 +147,7 @@ class TriggerBaseEntity(Entity):
 | 
			
		||||
    def available(self) -> bool:
 | 
			
		||||
        """Return availability of the entity."""
 | 
			
		||||
        return (
 | 
			
		||||
            self._rendered is not self._static_rendered
 | 
			
		||||
            self._render_error is False
 | 
			
		||||
            and
 | 
			
		||||
            # Check against False so `None` is ok
 | 
			
		||||
            self._rendered.get(CONF_AVAILABILITY) is not False
 | 
			
		||||
@@ -176,12 +177,34 @@ class TriggerBaseEntity(Entity):
 | 
			
		||||
                extra_state_attributes[attr] = last_state.attributes[attr]
 | 
			
		||||
            self._rendered[CONF_ATTRIBUTES] = extra_state_attributes
 | 
			
		||||
 | 
			
		||||
    def _render_availability_template(self, variables: dict[str, Any]) -> None:
 | 
			
		||||
        """Render availability template."""
 | 
			
		||||
        self._render_error = False
 | 
			
		||||
        rendered = {**self._static_rendered, **self._rendered}
 | 
			
		||||
        key = CONF_AVAILABILITY
 | 
			
		||||
        try:
 | 
			
		||||
            if key in self._to_render_simple:
 | 
			
		||||
                rendered[key] = self._config[key].async_render(
 | 
			
		||||
                    variables,
 | 
			
		||||
                    parse_result=key in self._parse_result,
 | 
			
		||||
                )
 | 
			
		||||
        except TemplateError as err:
 | 
			
		||||
            logging.getLogger(f"{__package__}.{self.entity_id.split('.')[0]}").error(
 | 
			
		||||
                "Error rendering %s template for %s: %s", key, self.entity_id, err
 | 
			
		||||
            )
 | 
			
		||||
            self._render_error = True
 | 
			
		||||
        self._rendered = rendered
 | 
			
		||||
 | 
			
		||||
    def _render_templates(self, variables: dict[str, Any]) -> None:
 | 
			
		||||
        """Render templates."""
 | 
			
		||||
        self._render_availability_template(variables)
 | 
			
		||||
        rendered = dict(self._rendered)
 | 
			
		||||
        if CONF_AVAILABILITY in rendered and rendered[CONF_AVAILABILITY] is False:
 | 
			
		||||
            return
 | 
			
		||||
        try:
 | 
			
		||||
            rendered = dict(self._static_rendered)
 | 
			
		||||
 | 
			
		||||
            for key in self._to_render_simple:
 | 
			
		||||
                if key == CONF_AVAILABILITY:
 | 
			
		||||
                    continue
 | 
			
		||||
                rendered[key] = self._config[key].async_render(
 | 
			
		||||
                    variables,
 | 
			
		||||
                    parse_result=key in self._parse_result,
 | 
			
		||||
@@ -198,13 +221,13 @@ class TriggerBaseEntity(Entity):
 | 
			
		||||
                    self._config[CONF_ATTRIBUTES],
 | 
			
		||||
                    variables,
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
            self._rendered = rendered
 | 
			
		||||
        except TemplateError as err:
 | 
			
		||||
            logging.getLogger(f"{__package__}.{self.entity_id.split('.')[0]}").error(
 | 
			
		||||
                "Error rendering %s template for %s: %s", key, self.entity_id, err
 | 
			
		||||
            )
 | 
			
		||||
            self._rendered = self._static_rendered
 | 
			
		||||
            self._render_error = True
 | 
			
		||||
            return
 | 
			
		||||
        self._rendered = rendered
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ManualTriggerEntity(TriggerBaseEntity):
 | 
			
		||||
@@ -230,16 +253,15 @@ class ManualTriggerEntity(TriggerBaseEntity):
 | 
			
		||||
        Implementing class should call this last in update method to render templates.
 | 
			
		||||
        Ex: self._process_manual_data(payload)
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        run_variables: dict[str, Any] = {"value": value}
 | 
			
		||||
        # Silently try if variable is a json and store result in `value_json` if it is.
 | 
			
		||||
        with contextlib.suppress(*JSON_DECODE_EXCEPTIONS):
 | 
			
		||||
            run_variables["value_json"] = json_loads(run_variables["value"])
 | 
			
		||||
 | 
			
		||||
        variables = {
 | 
			
		||||
            "this": TemplateStateFromEntityId(self.hass, self.entity_id),
 | 
			
		||||
            **(run_variables or {}),
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        self._render_templates(variables)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -808,3 +808,52 @@ async def test_availability(
 | 
			
		||||
    entity_state = hass.states.get("sensor.test")
 | 
			
		||||
    assert entity_state
 | 
			
		||||
    assert entity_state.state == STATE_UNAVAILABLE
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize(
 | 
			
		||||
    "get_config",
 | 
			
		||||
    [
 | 
			
		||||
        {
 | 
			
		||||
            "command_line": [
 | 
			
		||||
                {
 | 
			
		||||
                    "sensor": {
 | 
			
		||||
                        "name": "Test",
 | 
			
		||||
                        "command": "echo {{ states.sensor.input_sensor.state }}",
 | 
			
		||||
                        "availability": "{{ value|is_number}}",
 | 
			
		||||
                        "unit_of_measurement": " ",
 | 
			
		||||
                        "state_class": "measurement",
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            ]
 | 
			
		||||
        }
 | 
			
		||||
    ],
 | 
			
		||||
)
 | 
			
		||||
async def test_template_render_not_break_for_availability(
 | 
			
		||||
    hass: HomeAssistant, load_yaml_integration: None
 | 
			
		||||
) -> None:
 | 
			
		||||
    """Ensure command with templates get rendered properly."""
 | 
			
		||||
    hass.states.async_set("sensor.input_sensor", "sensor_value")
 | 
			
		||||
 | 
			
		||||
    # Give time for template to load
 | 
			
		||||
    async_fire_time_changed(
 | 
			
		||||
        hass,
 | 
			
		||||
        dt_util.utcnow() + timedelta(minutes=1),
 | 
			
		||||
    )
 | 
			
		||||
    await hass.async_block_till_done(wait_background_tasks=True)
 | 
			
		||||
 | 
			
		||||
    entity_state = hass.states.get("sensor.test")
 | 
			
		||||
    assert entity_state
 | 
			
		||||
    assert entity_state.state == STATE_UNAVAILABLE
 | 
			
		||||
 | 
			
		||||
    hass.states.async_set("sensor.input_sensor", "1")
 | 
			
		||||
 | 
			
		||||
    # Give time for template to load
 | 
			
		||||
    async_fire_time_changed(
 | 
			
		||||
        hass,
 | 
			
		||||
        dt_util.utcnow() + timedelta(minutes=1),
 | 
			
		||||
    )
 | 
			
		||||
    await hass.async_block_till_done(wait_background_tasks=True)
 | 
			
		||||
 | 
			
		||||
    entity_state = hass.states.get("sensor.test")
 | 
			
		||||
    assert entity_state
 | 
			
		||||
    assert entity_state.state == "1"
 | 
			
		||||
 
 | 
			
		||||
@@ -1054,3 +1054,54 @@ async def test_availability_in_config(hass: HomeAssistant) -> None:
 | 
			
		||||
 | 
			
		||||
    state = hass.states.get("sensor.rest_sensor")
 | 
			
		||||
    assert state.state == STATE_UNAVAILABLE
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@respx.mock
 | 
			
		||||
async def test_json_response_with_availability(hass: HomeAssistant) -> None:
 | 
			
		||||
    """Test availability with complex json."""
 | 
			
		||||
 | 
			
		||||
    respx.get("http://localhost").respond(
 | 
			
		||||
        status_code=HTTPStatus.OK,
 | 
			
		||||
        json={"heartbeatList": {"1": [{"status": 1, "ping": 21.4}]}},
 | 
			
		||||
    )
 | 
			
		||||
    assert await async_setup_component(
 | 
			
		||||
        hass,
 | 
			
		||||
        DOMAIN,
 | 
			
		||||
        {
 | 
			
		||||
            DOMAIN: [
 | 
			
		||||
                {
 | 
			
		||||
                    "resource": "http://localhost",
 | 
			
		||||
                    "sensor": [
 | 
			
		||||
                        {
 | 
			
		||||
                            "unique_id": "complex_json",
 | 
			
		||||
                            "name": "complex_json",
 | 
			
		||||
                            "value_template": '{% set v = value_json.heartbeatList["1"][-1] %}{{ v.ping }}',
 | 
			
		||||
                            "availability": '{% set v = value_json.heartbeatList["1"][-1] %}{{ v.status == 1 and is_number(v.ping) }}',
 | 
			
		||||
                            "unit_of_measurement": "ms",
 | 
			
		||||
                            "state_class": "measurement",
 | 
			
		||||
                        }
 | 
			
		||||
                    ],
 | 
			
		||||
                }
 | 
			
		||||
            ]
 | 
			
		||||
        },
 | 
			
		||||
    )
 | 
			
		||||
    await async_setup_component(hass, "homeassistant", {})
 | 
			
		||||
    await hass.async_block_till_done()
 | 
			
		||||
    assert len(hass.states.async_all(SENSOR_DOMAIN)) == 1
 | 
			
		||||
 | 
			
		||||
    state = hass.states.get("sensor.complex_json")
 | 
			
		||||
    assert state.state == "21.4"
 | 
			
		||||
 | 
			
		||||
    respx.get("http://localhost").respond(
 | 
			
		||||
        status_code=HTTPStatus.OK,
 | 
			
		||||
        json={"heartbeatList": {"1": [{"status": 0, "ping": None}]}},
 | 
			
		||||
    )
 | 
			
		||||
    await hass.services.async_call(
 | 
			
		||||
        "homeassistant",
 | 
			
		||||
        "update_entity",
 | 
			
		||||
        {ATTR_ENTITY_ID: ["sensor.complex_json"]},
 | 
			
		||||
        blocking=True,
 | 
			
		||||
    )
 | 
			
		||||
    await hass.async_block_till_done()
 | 
			
		||||
    state = hass.states.get("sensor.complex_json")
 | 
			
		||||
    assert state.state == STATE_UNAVAILABLE
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,9 @@
 | 
			
		||||
 | 
			
		||||
import pytest
 | 
			
		||||
 | 
			
		||||
from homeassistant.components import sensor
 | 
			
		||||
from homeassistant.components.template import template_entity
 | 
			
		||||
from homeassistant.const import STATE_OFF, STATE_ON, STATE_UNAVAILABLE
 | 
			
		||||
from homeassistant.core import HomeAssistant
 | 
			
		||||
from homeassistant.helpers import template
 | 
			
		||||
 | 
			
		||||
@@ -22,3 +24,46 @@ async def test_template_entity_requires_hass_set(hass: HomeAssistant) -> None:
 | 
			
		||||
    entity.add_template_attribute("_hello", tpl_with_hass)
 | 
			
		||||
 | 
			
		||||
    assert len(entity._template_attrs.get(tpl_with_hass, [])) == 1
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize(("count", "domain"), [(1, sensor.DOMAIN)])
 | 
			
		||||
@pytest.mark.parametrize(
 | 
			
		||||
    "config",
 | 
			
		||||
    [
 | 
			
		||||
        {
 | 
			
		||||
            "sensor": {
 | 
			
		||||
                "platform": "template",
 | 
			
		||||
                "sensors": {
 | 
			
		||||
                    "test_template_sensor": {
 | 
			
		||||
                        "value_template": "{{ states.sensor.test_sensor.state }}",
 | 
			
		||||
                        "availability_template": "{{ is_state('sensor.test_sensor', 'on') }}",
 | 
			
		||||
                        "icon_template": "{% if states.sensor.test_sensor.state == 'on' %}mdi:on{% else %}mdi:off{% endif %}",
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
            },
 | 
			
		||||
        },
 | 
			
		||||
    ],
 | 
			
		||||
)
 | 
			
		||||
@pytest.mark.usefixtures("start_ha")
 | 
			
		||||
async def test_unavailable_does_not_render_other_state_attributes(
 | 
			
		||||
    hass: HomeAssistant,
 | 
			
		||||
) -> None:
 | 
			
		||||
    """Test when entity goes unavailable, other state attributes are not rendered."""
 | 
			
		||||
    hass.states.async_set("sensor.test_sensor", STATE_OFF)
 | 
			
		||||
 | 
			
		||||
    # When template returns true..
 | 
			
		||||
    hass.states.async_set("sensor.test_sensor", STATE_ON)
 | 
			
		||||
    await hass.async_block_till_done()
 | 
			
		||||
 | 
			
		||||
    # Device State should not be unavailable
 | 
			
		||||
    assert hass.states.get("sensor.test_template_sensor").state != STATE_UNAVAILABLE
 | 
			
		||||
    assert hass.states.get("sensor.test_template_sensor").attributes["icon"] == "mdi:on"
 | 
			
		||||
 | 
			
		||||
    # When Availability template returns false
 | 
			
		||||
    hass.states.async_set("sensor.test_sensor", STATE_OFF)
 | 
			
		||||
    await hass.async_block_till_done()
 | 
			
		||||
 | 
			
		||||
    # device state should be unavailable
 | 
			
		||||
    assert hass.states.get("sensor.test_template_sensor").state == STATE_UNAVAILABLE
 | 
			
		||||
    # Icon should be mdi:on as going unavailable does not render state attributes
 | 
			
		||||
    assert hass.states.get("sensor.test_template_sensor").attributes["icon"] == "mdi:on"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,18 +1,27 @@
 | 
			
		||||
"""Test template trigger entity."""
 | 
			
		||||
 | 
			
		||||
from typing import Any
 | 
			
		||||
 | 
			
		||||
import pytest
 | 
			
		||||
 | 
			
		||||
from homeassistant.const import CONF_ICON, CONF_NAME, STATE_OFF, STATE_ON, STATE_UNKNOWN
 | 
			
		||||
from homeassistant.core import HomeAssistant
 | 
			
		||||
from homeassistant.helpers import template
 | 
			
		||||
from homeassistant.helpers.trigger_template_entity import ManualTriggerEntity
 | 
			
		||||
from homeassistant.helpers.trigger_template_entity import (
 | 
			
		||||
    CONF_AVAILABILITY,
 | 
			
		||||
    CONF_PICTURE,
 | 
			
		||||
    ManualTriggerEntity,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
async def test_template_entity_requires_hass_set(hass: HomeAssistant) -> None:
 | 
			
		||||
    """Test manual trigger template entity."""
 | 
			
		||||
    config = {
 | 
			
		||||
        "name": template.Template("test_entity", hass),
 | 
			
		||||
        "icon": template.Template(
 | 
			
		||||
        CONF_NAME: template.Template("test_entity", hass),
 | 
			
		||||
        CONF_ICON: template.Template(
 | 
			
		||||
            '{% if value=="on" %} mdi:on {% else %} mdi:off {% endif %}', hass
 | 
			
		||||
        ),
 | 
			
		||||
        "picture": template.Template(
 | 
			
		||||
        CONF_PICTURE: template.Template(
 | 
			
		||||
            '{% if value=="on" %} /local/picture_on {% else %} /local/picture_off {% endif %}',
 | 
			
		||||
            hass,
 | 
			
		||||
        ),
 | 
			
		||||
@@ -20,21 +29,137 @@ async def test_template_entity_requires_hass_set(hass: HomeAssistant) -> None:
 | 
			
		||||
 | 
			
		||||
    entity = ManualTriggerEntity(hass, config)
 | 
			
		||||
    entity.entity_id = "test.entity"
 | 
			
		||||
    hass.states.async_set("test.entity", "on")
 | 
			
		||||
    hass.states.async_set("test.entity", STATE_ON)
 | 
			
		||||
    await entity.async_added_to_hass()
 | 
			
		||||
 | 
			
		||||
    entity._process_manual_data("on")
 | 
			
		||||
    entity._process_manual_data(STATE_ON)
 | 
			
		||||
    await hass.async_block_till_done()
 | 
			
		||||
 | 
			
		||||
    assert entity.name == "test_entity"
 | 
			
		||||
    assert entity.icon == "mdi:on"
 | 
			
		||||
    assert entity.entity_picture == "/local/picture_on"
 | 
			
		||||
 | 
			
		||||
    hass.states.async_set("test.entity", "off")
 | 
			
		||||
    hass.states.async_set("test.entity", STATE_OFF)
 | 
			
		||||
    await entity.async_added_to_hass()
 | 
			
		||||
    entity._process_manual_data("off")
 | 
			
		||||
    entity._process_manual_data(STATE_OFF)
 | 
			
		||||
    await hass.async_block_till_done()
 | 
			
		||||
 | 
			
		||||
    assert entity.name == "test_entity"
 | 
			
		||||
    assert entity.icon == "mdi:off"
 | 
			
		||||
    assert entity.entity_picture == "/local/picture_off"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
async def test_trigger_template_availability(hass: HomeAssistant) -> None:
 | 
			
		||||
    """Test manual trigger template entity availability template."""
 | 
			
		||||
    config = {
 | 
			
		||||
        CONF_NAME: template.Template("test_entity", hass),
 | 
			
		||||
        CONF_ICON: template.Template(
 | 
			
		||||
            '{% if value=="on" %} mdi:on {% else %} mdi:off {% endif %}', hass
 | 
			
		||||
        ),
 | 
			
		||||
        CONF_PICTURE: template.Template(
 | 
			
		||||
            '{% if value=="on" %} /local/picture_on {% else %} /local/picture_off {% endif %}',
 | 
			
		||||
            hass,
 | 
			
		||||
        ),
 | 
			
		||||
        CONF_AVAILABILITY: template.Template('{{ has_value("test.entity") }}', hass),
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    entity = ManualTriggerEntity(hass, config)
 | 
			
		||||
    entity.entity_id = "test.entity"
 | 
			
		||||
    hass.states.async_set("test.entity", STATE_ON)
 | 
			
		||||
    await entity.async_added_to_hass()
 | 
			
		||||
 | 
			
		||||
    entity._process_manual_data(STATE_ON)
 | 
			
		||||
    await hass.async_block_till_done()
 | 
			
		||||
 | 
			
		||||
    assert entity.name == "test_entity"
 | 
			
		||||
    assert entity.icon == "mdi:on"
 | 
			
		||||
    assert entity.entity_picture == "/local/picture_on"
 | 
			
		||||
    assert entity.available is True
 | 
			
		||||
 | 
			
		||||
    hass.states.async_set("test.entity", STATE_OFF)
 | 
			
		||||
    await entity.async_added_to_hass()
 | 
			
		||||
    entity._process_manual_data(STATE_OFF)
 | 
			
		||||
    await hass.async_block_till_done()
 | 
			
		||||
 | 
			
		||||
    assert entity.name == "test_entity"
 | 
			
		||||
    assert entity.icon == "mdi:off"
 | 
			
		||||
    assert entity.entity_picture == "/local/picture_off"
 | 
			
		||||
    assert entity.available is True
 | 
			
		||||
 | 
			
		||||
    hass.states.async_set("test.entity", STATE_UNKNOWN)
 | 
			
		||||
    await entity.async_added_to_hass()
 | 
			
		||||
    entity._process_manual_data(STATE_UNKNOWN)
 | 
			
		||||
    await hass.async_block_till_done()
 | 
			
		||||
 | 
			
		||||
    assert entity.name == "test_entity"
 | 
			
		||||
    assert entity.icon == "mdi:off"
 | 
			
		||||
    assert entity.entity_picture == "/local/picture_off"
 | 
			
		||||
    assert entity.available is False
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
async def test_trigger_template_availability_fails(
 | 
			
		||||
    hass: HomeAssistant, caplog: pytest.LogCaptureFixture
 | 
			
		||||
) -> None:
 | 
			
		||||
    """Test manual trigger template entity when availability render fails."""
 | 
			
		||||
    config = {
 | 
			
		||||
        CONF_NAME: template.Template("test_entity", hass),
 | 
			
		||||
        CONF_ICON: template.Template(
 | 
			
		||||
            '{% if value=="on" %} mdi:on {% else %} mdi:off {% endif %}', hass
 | 
			
		||||
        ),
 | 
			
		||||
        CONF_PICTURE: template.Template(
 | 
			
		||||
            '{% if value=="on" %} /local/picture_on {% else %} /local/picture_off {% endif %}',
 | 
			
		||||
            hass,
 | 
			
		||||
        ),
 | 
			
		||||
        CONF_AVAILABILITY: template.Template("{{ incorrect ", hass),
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    entity = ManualTriggerEntity(hass, config)
 | 
			
		||||
    entity.entity_id = "test.entity"
 | 
			
		||||
    hass.states.async_set("test.entity", STATE_ON)
 | 
			
		||||
    await entity.async_added_to_hass()
 | 
			
		||||
 | 
			
		||||
    entity._process_manual_data(STATE_ON)
 | 
			
		||||
    await hass.async_block_till_done()
 | 
			
		||||
 | 
			
		||||
    assert "Error rendering availability template for test.entity" in caplog.text
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
async def test_trigger_template_complex(hass: HomeAssistant) -> None:
 | 
			
		||||
    """Test manual trigger template entity complex template."""
 | 
			
		||||
    complex_template = """
 | 
			
		||||
    {% set d = {'test_key':'test_data'} %}
 | 
			
		||||
    {{ dict(d) }}
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
    config = {
 | 
			
		||||
        CONF_NAME: template.Template("test_entity", hass),
 | 
			
		||||
        CONF_ICON: template.Template(
 | 
			
		||||
            '{% if value=="on" %} mdi:on {% else %} mdi:off {% endif %}', hass
 | 
			
		||||
        ),
 | 
			
		||||
        CONF_PICTURE: template.Template(
 | 
			
		||||
            '{% if value=="on" %} /local/picture_on {% else %} /local/picture_off {% endif %}',
 | 
			
		||||
            hass,
 | 
			
		||||
        ),
 | 
			
		||||
        CONF_AVAILABILITY: template.Template('{{ has_value("test.entity") }}', hass),
 | 
			
		||||
        "other_key": template.Template(complex_template, hass),
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    class TestEntity(ManualTriggerEntity):
 | 
			
		||||
        """Test entity class."""
 | 
			
		||||
 | 
			
		||||
        extra_template_keys_complex = ("other_key",)
 | 
			
		||||
 | 
			
		||||
        @property
 | 
			
		||||
        def some_other_key(self) -> dict[str, Any] | None:
 | 
			
		||||
            """Return extra attributes."""
 | 
			
		||||
            return self._rendered.get("other_key")
 | 
			
		||||
 | 
			
		||||
    entity = TestEntity(hass, config)
 | 
			
		||||
    entity.entity_id = "test.entity"
 | 
			
		||||
    hass.states.async_set("test.entity", STATE_ON)
 | 
			
		||||
    await entity.async_added_to_hass()
 | 
			
		||||
 | 
			
		||||
    entity._process_manual_data(STATE_ON)
 | 
			
		||||
    await hass.async_block_till_done()
 | 
			
		||||
 | 
			
		||||
    assert entity.some_other_key == {"test_key": "test_data"}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user