1
0
mirror of https://github.com/home-assistant/core.git synced 2026-05-08 17:49:37 +01:00

Fix subentry ID is not updated when renaming the entity ID (#157498)

This commit is contained in:
Jan Bouwhuis
2025-12-01 07:55:13 +01:00
committed by GitHub
parent 4bb8590076
commit 34d6938171
3 changed files with 256 additions and 2 deletions
+3 -1
View File
@@ -1553,7 +1553,9 @@ class Entity(
# Clear the remove future to handle entity added again after entity id change
self.__remove_future = None
self._platform_state = EntityPlatformState.NOT_ADDED
await self.platform.async_add_entities([self])
await self.platform.async_add_entities(
[self], config_subentry_id=registry_entry.config_subentry_id
)
@callback
def _async_unsubscribe_device_updates(self) -> None:
+188
View File
@@ -1,4 +1,192 @@
# serializer version: 1
# name: test_change_entity_id_config_entry[None]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'test_domain',
'entity_category': None,
'entity_id': 'test_domain.test_5678',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': None,
'platform': 'test',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': '5678',
'unit_of_measurement': None,
})
# ---
# name: test_change_entity_id_config_entry[None].1
StateSnapshot({
'attributes': ReadOnlyDict({
}),
'context': <ANY>,
'entity_id': 'test_domain.test_5678',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'unknown',
})
# ---
# name: test_change_entity_id_config_entry[None].2
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'test_domain',
'entity_category': None,
'entity_id': 'test_domain.test2',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': None,
'platform': 'test',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': '5678',
'unit_of_measurement': None,
})
# ---
# name: test_change_entity_id_config_entry[None].3
StateSnapshot({
'attributes': ReadOnlyDict({
}),
'context': <ANY>,
'entity_id': 'test_domain.test2',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'unknown',
})
# ---
# name: test_change_entity_id_config_entry[mock-subentry-id-1]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'test_domain',
'entity_category': None,
'entity_id': 'test_domain.test_5678',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': None,
'platform': 'test',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': '5678',
'unit_of_measurement': None,
})
# ---
# name: test_change_entity_id_config_entry[mock-subentry-id-1].1
StateSnapshot({
'attributes': ReadOnlyDict({
}),
'context': <ANY>,
'entity_id': 'test_domain.test_5678',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'unknown',
})
# ---
# name: test_change_entity_id_config_entry[mock-subentry-id-1].2
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'test_domain',
'entity_category': None,
'entity_id': 'test_domain.test2',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': None,
'platform': 'test',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': '5678',
'unit_of_measurement': None,
})
# ---
# name: test_change_entity_id_config_entry[mock-subentry-id-1].3
StateSnapshot({
'attributes': ReadOnlyDict({
}),
'context': <ANY>,
'entity_id': 'test_domain.test2',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'unknown',
})
# ---
# name: test_entity_description_as_dataclass
dict({
'device_class': 'test',
+65 -1
View File
@@ -16,7 +16,7 @@ from pytest_unordered import unordered
from syrupy.assertion import SnapshotAssertion
import voluptuous as vol
from homeassistant.config_entries import ConfigEntry
from homeassistant.config_entries import ConfigEntry, ConfigSubentryData
from homeassistant.const import (
ATTR_ATTRIBUTION,
ATTR_DEVICE_CLASS,
@@ -1911,6 +1911,70 @@ async def test_change_entity_id(
assert ent._platform_state == entity.EntityPlatformState.ADDED
@pytest.mark.parametrize("config_subentry_id", [None, "mock-subentry-id-1"])
async def test_change_entity_id_config_entry(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
snapshot: SnapshotAssertion,
config_subentry_id: str | None,
) -> None:
"""Test changing entity id does not effect the config entry."""
class MockEntity(entity.Entity):
_attr_unique_id = "5678"
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Mock setup entry method."""
async_add_entities([MockEntity()], config_subentry_id=config_subentry_id)
platform = MockPlatform(async_setup_entry=async_setup_entry)
config_entry = MockConfigEntry(
entry_id="super-mock-id",
subentries_data=[
ConfigSubentryData(
data={},
subentry_id="mock-subentry-id-1",
subentry_type="test",
title="Mock title",
unique_id="test",
),
],
)
config_entry.add_to_hass(hass)
entity_platform = MockEntityPlatform(
hass, platform_name=config_entry.domain, platform=platform
)
assert await entity_platform.async_setup_entry(config_entry)
await hass.async_block_till_done()
ent = entity_registry.async_get(next(iter(hass.states.async_entity_ids())))
assert ent == snapshot
# The snapshot check asserts on any (sub)entry ID
assert ent.config_entry_id == config_entry.entry_id
assert ent.config_subentry_id == config_subentry_id
state = hass.states.async_all()[0]
assert state == snapshot
entity_registry.async_update_entity(
ent.entity_id, new_entity_id="test_domain.test2"
)
await hass.async_block_till_done(wait_background_tasks=True)
new_ent = entity_registry.async_get("test_domain.test2")
assert new_ent == snapshot
# The snapshot check asserts on any (sub)entry ID
assert new_ent.config_entry_id == config_entry.entry_id
assert new_ent.config_subentry_id == config_subentry_id
new_state = hass.states.get("test_domain.test2")
assert new_state == snapshot
def test_entity_description_as_dataclass(snapshot: SnapshotAssertion) -> None:
"""Test EntityDescription behaves like a dataclass."""