Fix alert not respecting can_acknowledge setting (#139483)

* fix(alert): check can_ack prior to acking

* fix(alert): add test for when can_acknowledge=False

* fix(alert): warn on can_ack blocking an ack

* Raise error when trying to acknowledge alert with can_acknowledge set to False

* Rewrite can_ack check as guard

Co-authored-by: Franck Nijhof <frenck@frenck.nl>

* Make can_ack service error msg human readable because it will show up in the UI

* format with ruff

* Make pytest aware of service error when acking an unackable alert

---------

Co-authored-by: Franck Nijhof <frenck@frenck.nl>
pull/125870/merge
StaleLoafOfBread 2025-02-28 14:59:35 -05:00 committed by GitHub
parent c21234672d
commit ed06831e9d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 33 additions and 2 deletions

View File

@ -14,7 +14,7 @@ from homeassistant.components.notify import (
)
from homeassistant.const import STATE_IDLE, STATE_OFF, STATE_ON
from homeassistant.core import Event, EventStateChangedData, HassJob, HomeAssistant
from homeassistant.exceptions import ServiceNotFound
from homeassistant.exceptions import ServiceNotFound, ServiceValidationError
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.event import (
async_track_point_in_time,
@ -195,7 +195,8 @@ class AlertEntity(Entity):
async def async_turn_off(self, **kwargs: Any) -> None:
"""Async Acknowledge alert."""
LOGGER.debug("Acknowledged Alert: %s", self._attr_name)
if not self._can_ack:
raise ServiceValidationError("This alert cannot be acknowledged")
self._ack = True
self.async_write_ha_state()

View File

@ -28,6 +28,7 @@ from homeassistant.const import (
STATE_ON,
)
from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.exceptions import ServiceValidationError
from homeassistant.setup import async_setup_component
from tests.common import MockEntityPlatform, async_mock_service
@ -116,6 +117,35 @@ async def test_silence(hass: HomeAssistant, mock_notifier: list[ServiceCall]) ->
assert hass.states.get(ENTITY_ID).state == STATE_ON
async def test_silence_can_acknowledge_false(hass: HomeAssistant) -> None:
"""Test that attempting to silence an alert with can_acknowledge=False will not silence."""
# Create copy of config where can_acknowledge is False
config = deepcopy(TEST_CONFIG)
config[DOMAIN][NAME]["can_acknowledge"] = False
# Setup the alert component
assert await async_setup_component(hass, DOMAIN, config)
await hass.async_block_till_done()
# Ensure the alert is currently on
hass.states.async_set(ENTITY_ID, STATE_ON)
await hass.async_block_till_done()
assert hass.states.get(ENTITY_ID).state == STATE_ON
# Attempt to acknowledge
with pytest.raises(ServiceValidationError):
await hass.services.async_call(
DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: ENTITY_ID},
blocking=True,
)
await hass.async_block_till_done()
# The state should still be ON because can_acknowledge=False
assert hass.states.get(ENTITY_ID).state == STATE_ON
async def test_reset(hass: HomeAssistant, mock_notifier: list[ServiceCall]) -> None:
"""Test resetting the alert."""
assert await async_setup_component(hass, DOMAIN, TEST_CONFIG)