From 433d6400719cd2fc7afb53891ff28509f1a33a70 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Mon, 26 Jun 2023 22:27:19 +0200 Subject: [PATCH] Use entity registry id in light device actions (#95271) --- .../components/light/device_action.py | 10 +- tests/components/light/test_device_action.py | 214 ++++++++++++++++-- tests/components/zha/test_device_action.py | 6 +- 3 files changed, 199 insertions(+), 31 deletions(-) diff --git a/homeassistant/components/light/device_action.py b/homeassistant/components/light/device_action.py index 2e3338e1253..2b49c963438 100644 --- a/homeassistant/components/light/device_action.py +++ b/homeassistant/components/light/device_action.py @@ -113,7 +113,7 @@ async def async_get_actions( base_action = { CONF_DEVICE_ID: device_id, CONF_DOMAIN: DOMAIN, - CONF_ENTITY_ID: entry.entity_id, + CONF_ENTITY_ID: entry.id, } if brightness_supported(supported_color_modes): @@ -137,16 +137,12 @@ async def async_get_action_capabilities( if config[CONF_TYPE] != toggle_entity.CONF_TURN_ON: return {} - entry = async_get_entity_registry_entry_or_raise(hass, config[CONF_ENTITY_ID]) - try: + entry = async_get_entity_registry_entry_or_raise(hass, config[CONF_ENTITY_ID]) supported_color_modes = get_supported_color_modes(hass, entry.entity_id) - except HomeAssistantError: - supported_color_modes = None - - try: supported_features = get_supported_features(hass, entry.entity_id) except HomeAssistantError: + supported_color_modes = None supported_features = 0 extra_fields = {} diff --git a/tests/components/light/test_device_action.py b/tests/components/light/test_device_action.py index 4f97eaec012..dcb52d68a79 100644 --- a/tests/components/light/test_device_action.py +++ b/tests/components/light/test_device_action.py @@ -60,8 +60,7 @@ async def test_get_actions( supported_features=LightEntityFeature.FLASH, capabilities={"supported_color_modes": ["brightness"]}, ) - expected_actions = [] - expected_actions += [ + expected_actions = [ { "domain": DOMAIN, "type": action, @@ -69,24 +68,13 @@ async def test_get_actions( "entity_id": entity_entry.id, "metadata": {"secondary": False}, } - for action in [ - "turn_off", - "turn_on", - "toggle", - ] - ] - expected_actions += [ - { - "domain": DOMAIN, - "type": action, - "device_id": device_entry.id, - "entity_id": entity_entry.entity_id, - "metadata": {"secondary": False}, - } for action in [ "brightness_decrease", "brightness_increase", "flash", + "turn_off", + "turn_on", + "toggle", ] ] actions = await async_get_device_automations( @@ -332,6 +320,154 @@ async def test_get_action_capabilities_features( assert capabilities == expected +@pytest.mark.parametrize( + ( + "set_state", + "expected_actions", + "supported_features_reg", + "supported_features_state", + "capabilities_reg", + "attributes_state", + "expected_capabilities", + ), + [ + ( + False, + { + "turn_on", + "toggle", + "turn_off", + "brightness_increase", + "brightness_decrease", + }, + 0, + 0, + {ATTR_SUPPORTED_COLOR_MODES: [ColorMode.BRIGHTNESS]}, + {}, + { + "turn_on": [ + { + "name": "brightness_pct", + "optional": True, + "type": "float", + "valueMax": 100, + "valueMin": 0, + } + ] + }, + ), + ( + True, + { + "turn_on", + "toggle", + "turn_off", + "brightness_increase", + "brightness_decrease", + }, + 0, + 0, + None, + {ATTR_SUPPORTED_COLOR_MODES: [ColorMode.BRIGHTNESS]}, + { + "turn_on": [ + { + "name": "brightness_pct", + "optional": True, + "type": "float", + "valueMax": 100, + "valueMin": 0, + } + ] + }, + ), + ( + False, + {"turn_on", "toggle", "turn_off", "flash"}, + LightEntityFeature.FLASH, + 0, + None, + {}, + { + "turn_on": [ + { + "name": "flash", + "optional": True, + "type": "select", + "options": [("short", "short"), ("long", "long")], + } + ] + }, + ), + ( + True, + {"turn_on", "toggle", "turn_off", "flash"}, + 0, + LightEntityFeature.FLASH, + None, + {}, + { + "turn_on": [ + { + "name": "flash", + "optional": True, + "type": "select", + "options": [("short", "short"), ("long", "long")], + } + ] + }, + ), + ], +) +async def test_get_action_capabilities_features_legacy( + hass: HomeAssistant, + device_registry: dr.DeviceRegistry, + entity_registry: er.EntityRegistry, + set_state, + expected_actions, + supported_features_reg, + supported_features_state, + capabilities_reg, + attributes_state, + expected_capabilities, +) -> None: + """Test we get the expected capabilities from a light action.""" + config_entry = MockConfigEntry(domain="test", data={}) + config_entry.add_to_hass(hass) + device_entry = device_registry.async_get_or_create( + config_entry_id=config_entry.entry_id, + connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, + ) + entity_id = entity_registry.async_get_or_create( + DOMAIN, + "test", + "5678", + device_id=device_entry.id, + supported_features=supported_features_reg, + capabilities=capabilities_reg, + ).entity_id + if set_state: + hass.states.async_set( + entity_id, + None, + {"supported_features": supported_features_state, **attributes_state}, + ) + + actions = await async_get_device_automations( + hass, DeviceAutomationType.ACTION, device_entry.id + ) + assert len(actions) == len(expected_actions) + action_types = {action["type"] for action in actions} + assert action_types == expected_actions + for action in actions: + action["entity_id"] = entity_registry.async_get(action["entity_id"]).entity_id + capabilities = await async_get_device_automation_capabilities( + hass, DeviceAutomationType.ACTION, action + ) + expected = {"extra_fields": expected_capabilities.get(action["type"], [])} + assert capabilities == expected + + async def test_action( hass: HomeAssistant, entity_registry: er.EntityRegistry, @@ -378,7 +514,7 @@ async def test_action( "action": { "domain": DOMAIN, "device_id": "", - "entity_id": entry.entity_id, + "entity_id": entry.id, "type": "flash", }, }, @@ -387,7 +523,7 @@ async def test_action( "action": { "domain": DOMAIN, "device_id": "", - "entity_id": entry.entity_id, + "entity_id": entry.id, "type": "flash", "flash": "long", }, @@ -400,7 +536,7 @@ async def test_action( "action": { "domain": DOMAIN, "device_id": "", - "entity_id": entry.entity_id, + "entity_id": entry.id, "type": "brightness_increase", }, }, @@ -412,7 +548,7 @@ async def test_action( "action": { "domain": DOMAIN, "device_id": "", - "entity_id": entry.entity_id, + "entity_id": entry.id, "type": "brightness_decrease", }, }, @@ -421,7 +557,7 @@ async def test_action( "action": { "domain": DOMAIN, "device_id": "", - "entity_id": entry.entity_id, + "entity_id": entry.id, "type": "turn_on", "brightness_pct": 75, }, @@ -486,3 +622,39 @@ async def test_action( await hass.async_block_till_done() assert len(turn_on_calls) == 6 assert turn_on_calls[-1].data == {"entity_id": entry.entity_id, "flash": FLASH_LONG} + + +async def test_action_legacy( + hass: HomeAssistant, + entity_registry: er.EntityRegistry, + calls, + enable_custom_integrations: None, +) -> None: + """Test for turn_on and turn_off actions.""" + entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678") + + assert await async_setup_component( + hass, + automation.DOMAIN, + { + automation.DOMAIN: [ + { + "trigger": {"platform": "event", "event_type": "test_off"}, + "action": { + "domain": DOMAIN, + "device_id": "", + "entity_id": entry.entity_id, + "type": "turn_off", + }, + }, + ] + }, + ) + await hass.async_block_till_done() + + turn_off_calls = async_mock_service(hass, DOMAIN, "turn_off") + + hass.bus.async_fire("test_off") + await hass.async_block_till_done() + assert len(turn_off_calls) == 1 + assert turn_off_calls[-1].data == {"entity_id": entry.entity_id} diff --git a/tests/components/zha/test_device_action.py b/tests/components/zha/test_device_action.py index d9357fb38fd..beb085408e0 100644 --- a/tests/components/zha/test_device_action.py +++ b/tests/components/zha/test_device_action.py @@ -216,21 +216,21 @@ async def test_get_inovelli_actions(hass: HomeAssistant, device_inovelli) -> Non { "device_id": inovelli_reg_device.id, "domain": Platform.LIGHT, - "entity_id": "light.inovelli_vzm31_sn_light", + "entity_id": inovelli_light.id, "metadata": {"secondary": False}, "type": "brightness_increase", }, { "device_id": inovelli_reg_device.id, "domain": Platform.LIGHT, - "entity_id": "light.inovelli_vzm31_sn_light", + "entity_id": inovelli_light.id, "metadata": {"secondary": False}, "type": "brightness_decrease", }, { "device_id": inovelli_reg_device.id, "domain": Platform.LIGHT, - "entity_id": "light.inovelli_vzm31_sn_light", + "entity_id": inovelli_light.id, "metadata": {"secondary": False}, "type": "flash", },