mirror of
https://github.com/home-assistant/core.git
synced 2025-07-17 10:17:09 +00:00
Fix ESPHome entities not being removed when the ESPHome config removes an entire platform (#141708)
* Fix old ESPHome entities not being removed when configuration changes fixes #140756 * make sure all callbacks fire * make sure all callbacks fire * make sure all callbacks fire * make sure all callbacks fire * revert * cover
This commit is contained in:
parent
bcd296822d
commit
ea8392a4a1
@ -312,17 +312,18 @@ class RuntimeEntryData:
|
|||||||
|
|
||||||
# Make a dict of the EntityInfo by type and send
|
# Make a dict of the EntityInfo by type and send
|
||||||
# them to the listeners for each specific EntityInfo type
|
# them to the listeners for each specific EntityInfo type
|
||||||
infos_by_type: dict[type[EntityInfo], list[EntityInfo]] = {}
|
infos_by_type: defaultdict[type[EntityInfo], list[EntityInfo]] = defaultdict(
|
||||||
|
list
|
||||||
|
)
|
||||||
for info in infos:
|
for info in infos:
|
||||||
info_type = type(info)
|
infos_by_type[type(info)].append(info)
|
||||||
if info_type not in infos_by_type:
|
|
||||||
infos_by_type[info_type] = []
|
|
||||||
infos_by_type[info_type].append(info)
|
|
||||||
|
|
||||||
callbacks_by_type = self.entity_info_callbacks
|
for type_, callbacks in self.entity_info_callbacks.items():
|
||||||
for type_, entity_infos in infos_by_type.items():
|
# If all entities for a type are removed, we
|
||||||
if callbacks_ := callbacks_by_type.get(type_):
|
# still need to call the callbacks with an empty list
|
||||||
for callback_ in callbacks_:
|
# to make sure the entities are removed.
|
||||||
|
entity_infos = infos_by_type.get(type_, [])
|
||||||
|
for callback_ in callbacks:
|
||||||
callback_(entity_infos)
|
callback_(entity_infos)
|
||||||
|
|
||||||
# Finally update static info subscriptions
|
# Finally update static info subscriptions
|
||||||
|
@ -260,6 +260,76 @@ async def test_entities_removed_after_reload(
|
|||||||
assert len(hass_storage[storage_key]["data"]["binary_sensor"]) == 1
|
assert len(hass_storage[storage_key]["data"]["binary_sensor"]) == 1
|
||||||
|
|
||||||
|
|
||||||
|
async def test_entities_for_entire_platform_removed(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
mock_client: APIClient,
|
||||||
|
hass_storage: dict[str, Any],
|
||||||
|
mock_esphome_device: Callable[
|
||||||
|
[APIClient, list[EntityInfo], list[UserService], list[EntityState]],
|
||||||
|
Awaitable[MockESPHomeDevice],
|
||||||
|
],
|
||||||
|
) -> None:
|
||||||
|
"""Test removing all entities for a specific platform when static info changes."""
|
||||||
|
entity_info = [
|
||||||
|
BinarySensorInfo(
|
||||||
|
object_id="mybinary_sensor_to_be_removed",
|
||||||
|
key=1,
|
||||||
|
name="my binary_sensor to be removed",
|
||||||
|
unique_id="mybinary_sensor_to_be_removed",
|
||||||
|
),
|
||||||
|
]
|
||||||
|
states = [
|
||||||
|
BinarySensorState(key=1, state=True, missing_state=False),
|
||||||
|
]
|
||||||
|
user_service = []
|
||||||
|
mock_device = await mock_esphome_device(
|
||||||
|
mock_client=mock_client,
|
||||||
|
entity_info=entity_info,
|
||||||
|
user_service=user_service,
|
||||||
|
states=states,
|
||||||
|
)
|
||||||
|
entry = mock_device.entry
|
||||||
|
entry_id = entry.entry_id
|
||||||
|
storage_key = f"esphome.{entry_id}"
|
||||||
|
state = hass.states.get("binary_sensor.test_mybinary_sensor_to_be_removed")
|
||||||
|
assert state is not None
|
||||||
|
assert state.state == STATE_ON
|
||||||
|
|
||||||
|
await hass.config_entries.async_unload(entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert len(hass_storage[storage_key]["data"]["binary_sensor"]) == 1
|
||||||
|
|
||||||
|
state = hass.states.get("binary_sensor.test_mybinary_sensor_to_be_removed")
|
||||||
|
assert state is not None
|
||||||
|
reg_entry = entity_registry.async_get(
|
||||||
|
"binary_sensor.test_mybinary_sensor_to_be_removed"
|
||||||
|
)
|
||||||
|
assert reg_entry is not None
|
||||||
|
assert state.attributes[ATTR_RESTORED] is True
|
||||||
|
|
||||||
|
entity_info = []
|
||||||
|
states = []
|
||||||
|
mock_device = await mock_esphome_device(
|
||||||
|
mock_client=mock_client,
|
||||||
|
entity_info=entity_info,
|
||||||
|
user_service=user_service,
|
||||||
|
states=states,
|
||||||
|
entry=entry,
|
||||||
|
)
|
||||||
|
assert mock_device.entry.entry_id == entry_id
|
||||||
|
state = hass.states.get("binary_sensor.test_mybinary_sensor_to_be_removed")
|
||||||
|
assert state is None
|
||||||
|
reg_entry = entity_registry.async_get(
|
||||||
|
"binary_sensor.test_mybinary_sensor_to_be_removed"
|
||||||
|
)
|
||||||
|
assert reg_entry is None
|
||||||
|
await hass.config_entries.async_unload(entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert len(hass_storage[storage_key]["data"]["binary_sensor"]) == 0
|
||||||
|
|
||||||
|
|
||||||
async def test_entity_info_object_ids(
|
async def test_entity_info_object_ids(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
mock_client: APIClient,
|
mock_client: APIClient,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user