From 228db1c063c3c3e678df83a0e15953ece952f9db Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Fri, 9 Aug 2024 17:18:42 +0200 Subject: [PATCH] Support action YAML syntax in old-style notify groups (#123457) --- homeassistant/components/group/notify.py | 33 ++++++++++++++++++-- tests/components/group/test_notify.py | 39 ++++++++++++++++++++++-- 2 files changed, 67 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/group/notify.py b/homeassistant/components/group/notify.py index 8294b55be5e..ecbfec0bdb8 100644 --- a/homeassistant/components/group/notify.py +++ b/homeassistant/components/group/notify.py @@ -22,8 +22,9 @@ from homeassistant.components.notify import ( from homeassistant.config_entries import ConfigEntry from homeassistant.const import ( ATTR_ENTITY_ID, - ATTR_SERVICE, + CONF_ACTION, CONF_ENTITIES, + CONF_SERVICE, STATE_UNAVAILABLE, ) from homeassistant.core import HomeAssistant, callback @@ -36,11 +37,37 @@ from .entity import GroupEntity CONF_SERVICES = "services" + +def _backward_compat_schema(value: Any | None) -> Any: + """Backward compatibility for notify service schemas.""" + + if not isinstance(value, dict): + return value + + # `service` has been renamed to `action` + if CONF_SERVICE in value: + if CONF_ACTION in value: + raise vol.Invalid( + "Cannot specify both 'service' and 'action'. Please use 'action' only." + ) + value[CONF_ACTION] = value.pop(CONF_SERVICE) + + return value + + PLATFORM_SCHEMA = NOTIFY_PLATFORM_SCHEMA.extend( { vol.Required(CONF_SERVICES): vol.All( cv.ensure_list, - [{vol.Required(ATTR_SERVICE): cv.slug, vol.Optional(ATTR_DATA): dict}], + [ + vol.All( + _backward_compat_schema, + { + vol.Required(CONF_ACTION): cv.slug, + vol.Optional(ATTR_DATA): dict, + }, + ) + ], ) } ) @@ -88,7 +115,7 @@ class GroupNotifyPlatform(BaseNotificationService): tasks.append( asyncio.create_task( self.hass.services.async_call( - DOMAIN, entity[ATTR_SERVICE], sending_payload, blocking=True + DOMAIN, entity[CONF_ACTION], sending_payload, blocking=True ) ) ) diff --git a/tests/components/group/test_notify.py b/tests/components/group/test_notify.py index 2595b211dae..bbf2d98b492 100644 --- a/tests/components/group/test_notify.py +++ b/tests/components/group/test_notify.py @@ -122,7 +122,7 @@ async def test_send_message_with_data(hass: HomeAssistant, tmp_path: Path) -> No "services": [ {"service": "test_service1"}, { - "service": "test_service2", + "action": "test_service2", "data": { "target": "unnamed device", "data": {"test": "message", "default": "default"}, @@ -202,6 +202,41 @@ async def test_send_message_with_data(hass: HomeAssistant, tmp_path: Path) -> No ) +async def test_invalid_configuration( + hass: HomeAssistant, tmp_path: Path, caplog: pytest.LogCaptureFixture +) -> None: + """Test failing to set up group with an invalid configuration.""" + assert await async_setup_component( + hass, + "group", + {}, + ) + await hass.async_block_till_done() + + group_setup = [ + { + "platform": "group", + "name": "My invalid notification group", + "services": [ + { + "service": "test_service1", + "action": "test_service2", + "data": { + "target": "unnamed device", + "data": {"test": "message", "default": "default"}, + }, + }, + ], + } + ] + await help_setup_notify(hass, tmp_path, {"service1": 1, "service2": 2}, group_setup) + assert not hass.services.has_service("notify", "my_invalid_notification_group") + assert ( + "Invalid config for 'notify' from integration 'group':" + " Cannot specify both 'service' and 'action'." in caplog.text + ) + + async def test_reload_notify(hass: HomeAssistant, tmp_path: Path) -> None: """Verify we can reload the notify service.""" assert await async_setup_component( @@ -219,7 +254,7 @@ async def test_reload_notify(hass: HomeAssistant, tmp_path: Path) -> None: { "name": "group_notify", "platform": "group", - "services": [{"service": "test_service1"}], + "services": [{"action": "test_service1"}], } ], )