mirror of
https://github.com/home-assistant/core.git
synced 2025-12-24 21:06:19 +00:00
Deprecate legacy and undocumented template entity configurations (#155355)
This commit is contained in:
@@ -18,7 +18,7 @@ from homeassistant.const import (
|
||||
)
|
||||
from homeassistant.core import Event, HomeAssistant, ServiceCall
|
||||
from homeassistant.exceptions import ConfigEntryError, HomeAssistantError
|
||||
from homeassistant.helpers import discovery
|
||||
from homeassistant.helpers import discovery, issue_registry as ir
|
||||
from homeassistant.helpers.device import (
|
||||
async_remove_stale_devices_links_keep_current_device,
|
||||
)
|
||||
@@ -30,12 +30,21 @@ from homeassistant.util.hass_dict import HassKey
|
||||
|
||||
from .const import CONF_MAX, CONF_MIN, CONF_STEP, DOMAIN, PLATFORMS
|
||||
from .coordinator import TriggerUpdateCoordinator
|
||||
from .helpers import async_get_blueprints
|
||||
from .helpers import DATA_DEPRECATION, async_get_blueprints
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
DATA_COORDINATORS: HassKey[list[TriggerUpdateCoordinator]] = HassKey(DOMAIN)
|
||||
|
||||
|
||||
def _clean_up_legacy_template_deprecations(hass: HomeAssistant) -> None:
|
||||
if (found_issues := hass.data.pop(DATA_DEPRECATION, None)) is not None:
|
||||
issue_registry = ir.async_get(hass)
|
||||
for domain, issue_id in set(issue_registry.issues):
|
||||
if domain != DOMAIN or issue_id in found_issues:
|
||||
continue
|
||||
ir.async_delete_issue(hass, DOMAIN, issue_id)
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
"""Set up the template integration."""
|
||||
|
||||
@@ -54,6 +63,8 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
|
||||
async def _reload_config(call: Event | ServiceCall) -> None:
|
||||
"""Reload top-level + platforms."""
|
||||
hass.data.pop(DATA_DEPRECATION, None)
|
||||
|
||||
await async_get_blueprints(hass).async_reset_cache()
|
||||
try:
|
||||
unprocessed_conf = await conf_util.async_hass_config_yaml(hass)
|
||||
@@ -74,6 +85,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
if DOMAIN in conf:
|
||||
await _process_config(hass, conf)
|
||||
|
||||
_clean_up_legacy_template_deprecations(hass)
|
||||
hass.bus.async_fire(f"event_{DOMAIN}_reloaded", context=call.context)
|
||||
|
||||
async_register_admin_service(hass, DOMAIN, SERVICE_RELOAD, _reload_config)
|
||||
|
||||
@@ -72,7 +72,11 @@ from . import (
|
||||
weather as weather_platform,
|
||||
)
|
||||
from .const import CONF_DEFAULT_ENTITY_ID, DOMAIN, PLATFORMS, TemplateConfig
|
||||
from .helpers import async_get_blueprints, rewrite_legacy_to_modern_configs
|
||||
from .helpers import (
|
||||
async_get_blueprints,
|
||||
create_legacy_template_issue,
|
||||
rewrite_legacy_to_modern_configs,
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@@ -386,11 +390,11 @@ async def async_validate_config(hass: HomeAssistant, config: ConfigType) -> Conf
|
||||
definitions = (
|
||||
list(template_config[new_key]) if new_key in template_config else []
|
||||
)
|
||||
definitions.extend(
|
||||
rewrite_legacy_to_modern_configs(
|
||||
hass, new_key, template_config[old_key], legacy_fields
|
||||
)
|
||||
)
|
||||
for definition in rewrite_legacy_to_modern_configs(
|
||||
hass, new_key, template_config[old_key], legacy_fields
|
||||
):
|
||||
create_legacy_template_issue(hass, definition, new_key)
|
||||
definitions.append(definition)
|
||||
template_config = TemplateConfig({**template_config, new_key: definitions})
|
||||
|
||||
config_sections.append(template_config)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
"""Helpers for template integration."""
|
||||
|
||||
from collections.abc import Callable
|
||||
from enum import Enum
|
||||
import hashlib
|
||||
import itertools
|
||||
import logging
|
||||
from typing import Any
|
||||
@@ -22,15 +24,18 @@ from homeassistant.const import (
|
||||
)
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import PlatformNotReady
|
||||
from homeassistant.helpers import template
|
||||
from homeassistant.helpers import issue_registry as ir, template
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.helpers.entity_platform import (
|
||||
AddConfigEntryEntitiesCallback,
|
||||
AddEntitiesCallback,
|
||||
async_get_platforms,
|
||||
)
|
||||
from homeassistant.helpers.issue_registry import IssueSeverity
|
||||
from homeassistant.helpers.singleton import singleton
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
from homeassistant.util import yaml as yaml_util
|
||||
from homeassistant.util.hass_dict import HassKey
|
||||
|
||||
from .const import (
|
||||
CONF_ADVANCED_OPTIONS,
|
||||
@@ -46,7 +51,10 @@ from .entity import AbstractTemplateEntity
|
||||
from .template_entity import TemplateEntity
|
||||
from .trigger_entity import TriggerEntity
|
||||
|
||||
LEGACY_TEMPLATE_DEPRECATION_KEY = "deprecate_legacy_templates"
|
||||
|
||||
DATA_BLUEPRINTS = "template_blueprints"
|
||||
DATA_DEPRECATION: HassKey[list[str]] = HassKey(LEGACY_TEMPLATE_DEPRECATION_KEY)
|
||||
|
||||
LEGACY_FIELDS = {
|
||||
CONF_ICON_TEMPLATE: CONF_ICON,
|
||||
@@ -180,6 +188,95 @@ def async_create_template_tracking_entities(
|
||||
async_add_entities(entities)
|
||||
|
||||
|
||||
def _format_template(value: Any) -> Any:
|
||||
if isinstance(value, template.Template):
|
||||
return value.template
|
||||
|
||||
if isinstance(value, Enum):
|
||||
return value.name
|
||||
|
||||
if isinstance(value, (int, float, str, bool)):
|
||||
return value
|
||||
|
||||
return str(value)
|
||||
|
||||
|
||||
def format_migration_config(
|
||||
config: ConfigType | list[ConfigType], depth: int = 0
|
||||
) -> ConfigType | list[ConfigType]:
|
||||
"""Recursive method to format templates as strings from ConfigType."""
|
||||
types = (dict, list)
|
||||
if depth > 9:
|
||||
raise RecursionError
|
||||
|
||||
if isinstance(config, list):
|
||||
items = []
|
||||
for item in config:
|
||||
if isinstance(item, types):
|
||||
if len(item) > 0:
|
||||
items.append(format_migration_config(item, depth + 1))
|
||||
else:
|
||||
items.append(_format_template(item))
|
||||
return items # type: ignore[return-value]
|
||||
|
||||
formatted_config = {}
|
||||
for field, value in config.items():
|
||||
if isinstance(value, types):
|
||||
if len(value) > 0:
|
||||
formatted_config[field] = format_migration_config(value, depth + 1)
|
||||
else:
|
||||
formatted_config[field] = _format_template(value)
|
||||
|
||||
return formatted_config
|
||||
|
||||
|
||||
def create_legacy_template_issue(
|
||||
hass: HomeAssistant, config: ConfigType, domain: str
|
||||
) -> None:
|
||||
"""Create a repair for legacy template entities."""
|
||||
|
||||
breadcrumb = "Template Entity"
|
||||
# Default entity id should be in most legacy configuration because
|
||||
# it's created from the legacy slug. Vacuum and Lock do not have a
|
||||
# slug, therefore we need to use the name or unique_id.
|
||||
if (default_entity_id := config.get(CONF_DEFAULT_ENTITY_ID)) is not None:
|
||||
breadcrumb = default_entity_id.split(".")[-1]
|
||||
elif (unique_id := config.get(CONF_UNIQUE_ID)) is not None:
|
||||
breadcrumb = f"unique_id: {unique_id}"
|
||||
elif (name := config.get(CONF_NAME)) and isinstance(name, template.Template):
|
||||
breadcrumb = name.template
|
||||
|
||||
issue_id = f"{LEGACY_TEMPLATE_DEPRECATION_KEY}_{domain}_{breadcrumb}_{hashlib.md5(','.join(config.keys()).encode()).hexdigest()}"
|
||||
|
||||
if (deprecation_list := hass.data.get(DATA_DEPRECATION)) is None:
|
||||
hass.data[DATA_DEPRECATION] = deprecation_list = []
|
||||
|
||||
deprecation_list.append(issue_id)
|
||||
|
||||
try:
|
||||
modified_yaml = format_migration_config(config)
|
||||
yaml_config = yaml_util.dump({DOMAIN: [{domain: [modified_yaml]}]})
|
||||
# Format to show up properly in a numbered bullet on the repair.
|
||||
yaml_config = " ```\n " + yaml_config.replace("\n", "\n ") + "```"
|
||||
except RecursionError:
|
||||
yaml_config = f"{DOMAIN}:\n - {domain}: - ..."
|
||||
|
||||
ir.async_create_issue(
|
||||
hass,
|
||||
DOMAIN,
|
||||
issue_id,
|
||||
breaks_in_ha_version="2026.6",
|
||||
is_fixable=False,
|
||||
severity=IssueSeverity.WARNING,
|
||||
translation_key="deprecated_legacy_templates",
|
||||
translation_placeholders={
|
||||
"domain": domain,
|
||||
"breadcrumb": breadcrumb,
|
||||
"config": yaml_config,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_template_platform(
|
||||
hass: HomeAssistant,
|
||||
domain: str,
|
||||
@@ -201,6 +298,10 @@ async def async_setup_template_platform(
|
||||
)
|
||||
else:
|
||||
configs = [rewrite_legacy_to_modern_config(hass, config, legacy_fields)]
|
||||
|
||||
for definition in configs:
|
||||
create_legacy_template_issue(hass, definition, domain)
|
||||
|
||||
async_create_template_tracking_entities(
|
||||
state_entity_cls,
|
||||
async_add_entities,
|
||||
|
||||
@@ -527,6 +527,10 @@
|
||||
"deprecated_battery_level": {
|
||||
"description": "The template vacuum options `battery_level` and `battery_level_template` are being removed in 2026.8.\n\nPlease remove the `battery_level` or `battery_level_template` option from the YAML configuration for {entity_id} ({entity_name}).",
|
||||
"title": "Deprecated battery level option in {entity_name}"
|
||||
},
|
||||
"deprecated_legacy_templates": {
|
||||
"description": "The legacy `platform: template` syntax for `{domain}` is being removed. Please migrate `{breadcrumb}` to the modern template syntax.\n\n1. Remove existing template definition.\n2. Add new template definition:\n{config}\n3. Restart Home Assistant or reload template entities.",
|
||||
"title": "Legacy {domain} template deprecation"
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
sensor:
|
||||
- platform: template
|
||||
sensors:
|
||||
state:
|
||||
value_template: "{{ states.sensor.test_sensor.state }}"
|
||||
template:
|
||||
- sensor:
|
||||
- default_entity_id: sensor.state2
|
||||
state: "{{ states.sensor.test_sensor.state }}"
|
||||
- default_entity_id: sensor.state3
|
||||
state: "{{ states.sensor.test_sensor.state }}"
|
||||
@@ -13,6 +13,7 @@ from homeassistant.components.template.cover import LEGACY_FIELDS as COVER_LEGAC
|
||||
from homeassistant.components.template.fan import LEGACY_FIELDS as FAN_LEGACY_FIELDS
|
||||
from homeassistant.components.template.helpers import (
|
||||
async_setup_template_platform,
|
||||
format_migration_config,
|
||||
rewrite_legacy_to_modern_config,
|
||||
rewrite_legacy_to_modern_configs,
|
||||
)
|
||||
@@ -29,7 +30,9 @@ from homeassistant.components.template.vacuum import (
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import PlatformNotReady
|
||||
from homeassistant.helpers import issue_registry as ir
|
||||
from homeassistant.helpers.template import Template
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -377,3 +380,260 @@ async def test_platform_not_ready(
|
||||
None,
|
||||
{"coordinator": None, "entities": []},
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("domain", "config", "breadcrumb"),
|
||||
[
|
||||
(
|
||||
"template",
|
||||
{
|
||||
"template": [
|
||||
{
|
||||
"sensors": {
|
||||
"undocumented_configuration": {
|
||||
"value_template": "{{ 'armed_away' }}",
|
||||
}
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
"undocumented_configuration",
|
||||
),
|
||||
(
|
||||
"template",
|
||||
{
|
||||
"template": [
|
||||
{
|
||||
"binary_sensors": {
|
||||
"undocumented_configuration": {
|
||||
"value_template": "{{ 'armed_away' }}",
|
||||
}
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
"undocumented_configuration",
|
||||
),
|
||||
(
|
||||
"alarm_control_panel",
|
||||
{
|
||||
"alarm_control_panel": {
|
||||
"platform": "template",
|
||||
"panels": {
|
||||
"safe_alarm_panel": {
|
||||
"value_template": "{{ 'armed_away' }}",
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"safe_alarm_panel",
|
||||
),
|
||||
(
|
||||
"binary_sensor",
|
||||
{
|
||||
"binary_sensor": {
|
||||
"platform": "template",
|
||||
"sensors": {
|
||||
"sun_up": {
|
||||
"value_template": "{{ state_attr('sun.sun', 'elevation') > 0 }}",
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"sun_up",
|
||||
),
|
||||
(
|
||||
"cover",
|
||||
{
|
||||
"cover": {
|
||||
"platform": "template",
|
||||
"covers": {
|
||||
"garage_door": {
|
||||
"value_template": "{{ states('sensor.garage_door')|float > 0 }}",
|
||||
"open_cover": {"action": "script.toggle"},
|
||||
"close_cover": {"action": "script.toggle"},
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"garage_door",
|
||||
),
|
||||
(
|
||||
"fan",
|
||||
{
|
||||
"fan": {
|
||||
"platform": "template",
|
||||
"fans": {
|
||||
"bedroom_fan": {
|
||||
"value_template": "{{ states('input_boolean.state') }}",
|
||||
"turn_on": {"action": "script.toggle"},
|
||||
"turn_off": {"action": "script.toggle"},
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"bedroom_fan",
|
||||
),
|
||||
(
|
||||
"light",
|
||||
{
|
||||
"light": {
|
||||
"platform": "template",
|
||||
"lights": {
|
||||
"theater_lights": {
|
||||
"value_template": "{{ states('input_boolean.state') }}",
|
||||
"turn_on": {"action": "script.toggle"},
|
||||
"turn_off": {"action": "script.toggle"},
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"theater_lights",
|
||||
),
|
||||
(
|
||||
"lock",
|
||||
{
|
||||
"lock": {
|
||||
"platform": "template",
|
||||
"value_template": "{{ states('input_boolean.state') }}",
|
||||
"lock": {"action": "script.toggle"},
|
||||
"unlock": {"action": "script.toggle"},
|
||||
},
|
||||
},
|
||||
"Template Entity",
|
||||
),
|
||||
(
|
||||
"sensor",
|
||||
{
|
||||
"sensor": {
|
||||
"platform": "template",
|
||||
"sensors": {
|
||||
"test_template_sensor": {
|
||||
"value_template": "It {{ states.sensor.test_state.state }}.",
|
||||
"attribute_templates": {"something": "{{ 'bar' }}"},
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"test_template_sensor",
|
||||
),
|
||||
(
|
||||
"switch",
|
||||
{
|
||||
"switch": {
|
||||
"platform": "template",
|
||||
"switches": {
|
||||
"skylight": {
|
||||
"value_template": "{{ is_state('sensor.skylight', 'on') }}",
|
||||
"turn_on": {"action": "script.toggle"},
|
||||
"turn_off": {"action": "script.toggle"},
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"skylight",
|
||||
),
|
||||
(
|
||||
"vacuum",
|
||||
{
|
||||
"vacuum": {
|
||||
"platform": "template",
|
||||
"vacuums": {
|
||||
"living_room_vacuum": {
|
||||
"start": {"action": "script.start"},
|
||||
"attribute_templates": {"something": "{{ 'bar' }}"},
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"living_room_vacuum",
|
||||
),
|
||||
(
|
||||
"weather",
|
||||
{
|
||||
"weather": {
|
||||
"platform": "template",
|
||||
"name": "My Weather Station",
|
||||
"unique_id": "Foobar",
|
||||
"condition_template": "{{ 'rainy' }}",
|
||||
"temperature_template": "{{ 20 }}",
|
||||
"humidity_template": "{{ 50 }}",
|
||||
},
|
||||
},
|
||||
"unique_id: Foobar",
|
||||
),
|
||||
(
|
||||
"weather",
|
||||
{
|
||||
"weather": {
|
||||
"platform": "template",
|
||||
"name": "My Weather Station",
|
||||
"condition_template": "{{ 'rainy' }}",
|
||||
"temperature_template": "{{ 20 }}",
|
||||
"humidity_template": "{{ 50 }}",
|
||||
},
|
||||
},
|
||||
"My Weather Station",
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_legacy_deprecation(
|
||||
hass: HomeAssistant,
|
||||
domain: str,
|
||||
config: dict,
|
||||
breadcrumb: str,
|
||||
issue_registry: ir.IssueRegistry,
|
||||
) -> None:
|
||||
"""Test legacy configuration raises issue."""
|
||||
|
||||
await async_setup_component(hass, domain, config)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(issue_registry.issues) == 1
|
||||
issue = next(iter(issue_registry.issues.values()))
|
||||
|
||||
assert issue.domain == "template"
|
||||
assert issue.severity == ir.IssueSeverity.WARNING
|
||||
assert issue.translation_placeholders["breadcrumb"] == breadcrumb
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("domain", "config"),
|
||||
[
|
||||
(
|
||||
"template",
|
||||
{"template": [{"sensor": {"name": "test_template_sensor", "state": "OK"}}]},
|
||||
),
|
||||
(
|
||||
"template",
|
||||
{
|
||||
"template": [
|
||||
{
|
||||
"triggers": {"trigger": "event", "event_type": "test"},
|
||||
"sensor": {"name": "test_template_sensor", "state": "OK"},
|
||||
}
|
||||
]
|
||||
},
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_modern_configuration_does_not_raise_issue(
|
||||
hass: HomeAssistant,
|
||||
domain: str,
|
||||
config: dict,
|
||||
issue_registry: ir.IssueRegistry,
|
||||
) -> None:
|
||||
"""Test modern configuration does not raise issue."""
|
||||
|
||||
await async_setup_component(hass, domain, config)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(issue_registry.issues) == 0
|
||||
|
||||
|
||||
async def test_yaml_config_recursion_depth(hass: HomeAssistant) -> None:
|
||||
"""Test recursion depth when formatting ConfigType."""
|
||||
|
||||
with pytest.raises(RecursionError):
|
||||
format_migration_config({1: {2: {3: {4: {5: {6: [{7: {8: {9: {10: {}}}}}]}}}}}})
|
||||
|
||||
@@ -9,7 +9,11 @@ from homeassistant import config
|
||||
from homeassistant.components.template import DOMAIN
|
||||
from homeassistant.const import SERVICE_RELOAD
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||
from homeassistant.helpers import (
|
||||
device_registry as dr,
|
||||
entity_registry as er,
|
||||
issue_registry as ir,
|
||||
)
|
||||
from homeassistant.setup import async_setup_component
|
||||
from homeassistant.util import dt as dt_util
|
||||
|
||||
@@ -260,6 +264,50 @@ async def test_reload_sensors_that_reference_other_template_sensors(
|
||||
assert hass.states.get("sensor.test3").state == "2"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("count", "domain"), [(1, "sensor")])
|
||||
@pytest.mark.parametrize(
|
||||
"config",
|
||||
[
|
||||
{
|
||||
"sensor": {
|
||||
"platform": DOMAIN,
|
||||
"sensors": {
|
||||
"state": {
|
||||
"value_template": "{{ states.sensor.test_sensor.state }}"
|
||||
},
|
||||
"state2": {
|
||||
"value_template": "{{ states.sensor.test_sensor.state }}"
|
||||
},
|
||||
"state3": {
|
||||
"value_template": "{{ states.sensor.test_sensor.state }}"
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("start_ha")
|
||||
async def test_reload_removes_legacy_deprecation(
|
||||
hass: HomeAssistant, issue_registry: ir.IssueRegistry
|
||||
) -> None:
|
||||
"""Test that we can reload and remove all template sensors."""
|
||||
hass.states.async_set("sensor.test_sensor", "old")
|
||||
await hass.async_block_till_done()
|
||||
assert len(hass.states.async_all()) == 4
|
||||
assert hass.states.get("sensor.state").state == "old"
|
||||
assert hass.states.get("sensor.state2").state == "old"
|
||||
assert hass.states.get("sensor.state3").state == "old"
|
||||
|
||||
assert len(issue_registry.issues) == 3
|
||||
|
||||
await async_yaml_patch_helper(hass, "legacy_template_deprecation.yaml")
|
||||
assert len(hass.states.async_all()) == 4
|
||||
assert hass.states.get("sensor.state").state == "old"
|
||||
assert hass.states.get("sensor.state2").state == "old"
|
||||
assert hass.states.get("sensor.state3").state == "old"
|
||||
assert len(issue_registry.issues) == 1
|
||||
|
||||
|
||||
async def async_yaml_patch_helper(hass: HomeAssistant, filename: str) -> None:
|
||||
"""Help update configuration.yaml."""
|
||||
yaml_path = get_fixture_path(filename, "template")
|
||||
|
||||
@@ -594,16 +594,17 @@ async def test_battery_level_template(
|
||||
[(1, "{{ states('sensor.test_state') }}", {}, "{{ 50 }}")],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
("style", "attribute"),
|
||||
("style", "attribute", "issue_count"),
|
||||
[
|
||||
(ConfigurationStyle.LEGACY, "battery_level_template"),
|
||||
(ConfigurationStyle.MODERN, "battery_level"),
|
||||
(ConfigurationStyle.TRIGGER, "battery_level"),
|
||||
(ConfigurationStyle.LEGACY, "battery_level_template", 2),
|
||||
(ConfigurationStyle.MODERN, "battery_level", 1),
|
||||
(ConfigurationStyle.TRIGGER, "battery_level", 1),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("setup_single_attribute_state_vacuum")
|
||||
async def test_battery_level_template_repair(
|
||||
hass: HomeAssistant,
|
||||
issue_count: int,
|
||||
issue_registry: ir.IssueRegistry,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
) -> None:
|
||||
@@ -612,7 +613,7 @@ async def test_battery_level_template_repair(
|
||||
hass.states.async_set(TEST_STATE_SENSOR, VacuumActivity.DOCKED)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(issue_registry.issues) == 1
|
||||
assert len(issue_registry.issues) == issue_count
|
||||
issue = issue_registry.async_get_issue(
|
||||
"template", f"deprecated_battery_level_{TEST_ENTITY_ID}"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user