mirror of
https://github.com/home-assistant/core.git
synced 2025-04-24 17:27:52 +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,18 +312,19 @@ class RuntimeEntryData:
|
||||
|
||||
# Make a dict of the EntityInfo by type and send
|
||||
# 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:
|
||||
info_type = type(info)
|
||||
if info_type not in infos_by_type:
|
||||
infos_by_type[info_type] = []
|
||||
infos_by_type[info_type].append(info)
|
||||
infos_by_type[type(info)].append(info)
|
||||
|
||||
callbacks_by_type = self.entity_info_callbacks
|
||||
for type_, entity_infos in infos_by_type.items():
|
||||
if callbacks_ := callbacks_by_type.get(type_):
|
||||
for callback_ in callbacks_:
|
||||
callback_(entity_infos)
|
||||
for type_, callbacks in self.entity_info_callbacks.items():
|
||||
# If all entities for a type are removed, we
|
||||
# still need to call the callbacks with an empty list
|
||||
# to make sure the entities are removed.
|
||||
entity_infos = infos_by_type.get(type_, [])
|
||||
for callback_ in callbacks:
|
||||
callback_(entity_infos)
|
||||
|
||||
# Finally update static info subscriptions
|
||||
for callback_ in self.static_info_update_subscriptions:
|
||||
|
@ -260,6 +260,76 @@ async def test_entities_removed_after_reload(
|
||||
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(
|
||||
hass: HomeAssistant,
|
||||
mock_client: APIClient,
|
||||
|
Loading…
x
Reference in New Issue
Block a user