diff --git a/homeassistant/components/timer/__init__.py b/homeassistant/components/timer/__init__.py index a2ac7bdf6dd7..5da160a2a820 100644 --- a/homeassistant/components/timer/__init__.py +++ b/homeassistant/components/timer/__init__.py @@ -449,6 +449,13 @@ class Timer(collection.CollectionEntity, RestoreEntity): EVENT_TIMER_FINISHED, extra_attrs={ATTR_FINISHED_AT: end.isoformat()} ) + @override + async def async_will_remove_from_hass(self) -> None: + """Cancel the running timer when the entity is removed.""" + if self._listener: + self._listener() + self._listener = None + @override async def async_update_config(self, config: ConfigType) -> None: """Handle when the config is updated.""" diff --git a/tests/components/timer/test_init.py b/tests/components/timer/test_init.py index 353a5afd4d31..3af439440f68 100644 --- a/tests/components/timer/test_init.py +++ b/tests/components/timer/test_init.py @@ -1098,6 +1098,36 @@ async def test_ws_delete( assert entity_registry.async_get_entity_id(DOMAIN, DOMAIN, timer_id) is None +async def test_ws_delete_running_timer( + hass: HomeAssistant, + hass_ws_client: WebSocketGenerator, + storage_setup, +) -> None: + """Test deleting a running timer does not fire the finished event.""" + assert await storage_setup() + timer_entity_id = f"{DOMAIN}.{DOMAIN}_from_storage" + events = async_capture_events(hass, EVENT_TIMER_FINISHED) + + await hass.services.async_call( + DOMAIN, + SERVICE_START, + {CONF_ENTITY_ID: timer_entity_id, CONF_DURATION: 10}, + blocking=True, + ) + + client = await hass_ws_client(hass) + await client.send_json( + {"id": 6, "type": f"{DOMAIN}/delete", f"{DOMAIN}_id": "from_storage"} + ) + resp = await client.receive_json() + assert resp["success"] + + async_fire_time_changed(hass, utcnow() + timedelta(seconds=20)) + await hass.async_block_till_done() + + assert not events + + async def test_update( hass: HomeAssistant, entity_registry: er.EntityRegistry,