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
parent
c21234672d
commit
ed06831e9d
|
@ -14,7 +14,7 @@ from homeassistant.components.notify import (
|
||||||
)
|
)
|
||||||
from homeassistant.const import STATE_IDLE, STATE_OFF, STATE_ON
|
from homeassistant.const import STATE_IDLE, STATE_OFF, STATE_ON
|
||||||
from homeassistant.core import Event, EventStateChangedData, HassJob, HomeAssistant
|
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.entity import Entity
|
||||||
from homeassistant.helpers.event import (
|
from homeassistant.helpers.event import (
|
||||||
async_track_point_in_time,
|
async_track_point_in_time,
|
||||||
|
@ -195,7 +195,8 @@ class AlertEntity(Entity):
|
||||||
|
|
||||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||||
"""Async Acknowledge alert."""
|
"""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._ack = True
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ from homeassistant.const import (
|
||||||
STATE_ON,
|
STATE_ON,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant, ServiceCall
|
from homeassistant.core import HomeAssistant, ServiceCall
|
||||||
|
from homeassistant.exceptions import ServiceValidationError
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
from tests.common import MockEntityPlatform, async_mock_service
|
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
|
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:
|
async def test_reset(hass: HomeAssistant, mock_notifier: list[ServiceCall]) -> None:
|
||||||
"""Test resetting the alert."""
|
"""Test resetting the alert."""
|
||||||
assert await async_setup_component(hass, DOMAIN, TEST_CONFIG)
|
assert await async_setup_component(hass, DOMAIN, TEST_CONFIG)
|
||||||
|
|
Loading…
Reference in New Issue