Do not add template config entry to source device (#148756)

This commit is contained in:
Erik Montnemery 2025-07-15 22:13:03 +02:00 committed by GitHub
parent f5b785acd5
commit 381bd489d8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 39 additions and 19 deletions

View File

@ -6,7 +6,7 @@ from typing import Any
from homeassistant.const import CONF_DEVICE_ID
from homeassistant.core import Context, HomeAssistant, callback
from homeassistant.helpers.device import async_device_info_to_link_from_device_id
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.entity import Entity, async_generate_entity_id
from homeassistant.helpers.script import Script, _VarsType
from homeassistant.helpers.template import TemplateStateFromEntityId
@ -31,10 +31,9 @@ class AbstractTemplateEntity(Entity):
self._entity_id_format, object_id, hass=self.hass
)
self._attr_device_info = async_device_info_to_link_from_device_id(
self.hass,
config.get(CONF_DEVICE_ID),
)
device_registry = dr.async_get(hass)
if (device_id := config.get(CONF_DEVICE_ID)) is not None:
self.device_entry = device_registry.async_get(device_id)
@property
@abstractmethod

View File

@ -9,7 +9,7 @@ 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
from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.setup import async_setup_component
from homeassistant.util import dt as dt_util
@ -369,6 +369,7 @@ async def async_yaml_patch_helper(hass: HomeAssistant, filename: str) -> None:
async def test_change_device(
hass: HomeAssistant,
device_registry: dr.DeviceRegistry,
entity_registry: er.EntityRegistry,
config_entry_options: dict[str, str],
config_user_input: dict[str, str],
) -> None:
@ -379,6 +380,19 @@ async def test_change_device(
changed in the integration options.
"""
def check_template_entities(
template_entity_id: str,
device_id: str | None = None,
) -> None:
"""Check that the template entity is linked to the correct device."""
template_entity_ids: list[str] = []
for template_entity in entity_registry.entities.get_entries_for_config_entry_id(
template_config_entry.entry_id
):
template_entity_ids.append(template_entity.entity_id)
assert template_entity.device_id == device_id
assert template_entity_ids == [template_entity_id]
# Configure devices registry
entry_device1 = MockConfigEntry()
entry_device1.add_to_hass(hass)
@ -413,9 +427,14 @@ async def test_change_device(
assert await hass.config_entries.async_setup(template_config_entry.entry_id)
await hass.async_block_till_done()
# Confirm that the config entry has been added to the device 1 registry (current)
current_device = device_registry.async_get(device_id=device_id1)
assert template_config_entry.entry_id in current_device.config_entries
template_entity_id = f"{config_entry_options['template_type']}.my_template"
# Confirm that the template config entry has not been added to either device
# and that the entities are linked to device 1
for device_id in (device_id1, device_id2):
device = device_registry.async_get(device_id=device_id)
assert template_config_entry.entry_id not in device.config_entries
check_template_entities(template_entity_id, device_id1)
# Change config options to use device 2 and reload the integration
result = await hass.config_entries.options.async_init(
@ -427,13 +446,12 @@ async def test_change_device(
)
await hass.async_block_till_done()
# Confirm that the config entry has been removed from the device 1 registry
previous_device = device_registry.async_get(device_id=device_id1)
assert template_config_entry.entry_id not in previous_device.config_entries
# Confirm that the config entry has been added to the device 2 registry (current)
current_device = device_registry.async_get(device_id=device_id2)
assert template_config_entry.entry_id in current_device.config_entries
# Confirm that the template config entry has not been added to either device
# and that the entities are linked to device 2
for device_id in (device_id1, device_id2):
device = device_registry.async_get(device_id=device_id)
assert template_config_entry.entry_id not in device.config_entries
check_template_entities(template_entity_id, device_id2)
# Change the config options to remove the device and reload the integration
result = await hass.config_entries.options.async_init(
@ -445,9 +463,12 @@ async def test_change_device(
)
await hass.async_block_till_done()
# Confirm that the config entry has been removed from the device 2 registry
previous_device = device_registry.async_get(device_id=device_id2)
assert template_config_entry.entry_id not in previous_device.config_entries
# Confirm that the template config entry has not been added to either device
# and that the entities are not linked to any device
for device_id in (device_id1, device_id2):
device = device_registry.async_get(device_id=device_id)
assert template_config_entry.entry_id not in device.config_entries
check_template_entities(template_entity_id, None)
# Confirm that there is no device with the helper config entry
assert (