diff --git a/homeassistant/components/humidifier/device_condition.py b/homeassistant/components/humidifier/device_condition.py index 05812e35a36..c2c0378a746 100644 --- a/homeassistant/components/humidifier/device_condition.py +++ b/homeassistant/components/humidifier/device_condition.py @@ -3,7 +3,10 @@ from __future__ import annotations import voluptuous as vol -from homeassistant.components.device_automation import toggle_entity +from homeassistant.components.device_automation import ( + async_get_entity_registry_entry_or_raise, + toggle_entity, +) from homeassistant.const import ( ATTR_ENTITY_ID, ATTR_MODE, @@ -32,7 +35,7 @@ TOGGLE_CONDITION = toggle_entity.CONDITION_SCHEMA.extend( MODE_CONDITION = DEVICE_CONDITION_BASE_SCHEMA.extend( { - vol.Required(CONF_ENTITY_ID): cv.entity_id, + vol.Required(CONF_ENTITY_ID): cv.entity_id_or_uuid, vol.Required(CONF_TYPE): "is_mode", vol.Required(ATTR_MODE): str, } @@ -61,7 +64,7 @@ async def async_get_conditions( CONF_CONDITION: "device", CONF_DEVICE_ID: device_id, CONF_DOMAIN: DOMAIN, - CONF_ENTITY_ID: entry.entity_id, + CONF_ENTITY_ID: entry.id, CONF_TYPE: "is_mode", } ) @@ -79,11 +82,15 @@ def async_condition_from_config( else: return toggle_entity.async_condition_from_config(hass, config) + registry = er.async_get(hass) + entity_id = er.async_resolve_entity_id(registry, config[ATTR_ENTITY_ID]) + def test_is_state(hass: HomeAssistant, variables: TemplateVarsType) -> bool: """Test if an entity is a certain state.""" - state = hass.states.get(config[ATTR_ENTITY_ID]) return ( - state is not None and state.attributes.get(attribute) == config[attribute] + entity_id is not None + and (state := hass.states.get(entity_id)) is not None + and state.attributes.get(attribute) == config[attribute] ) return test_is_state @@ -99,9 +106,11 @@ async def async_get_condition_capabilities( if condition_type == "is_mode": try: + entry = async_get_entity_registry_entry_or_raise( + hass, config[CONF_ENTITY_ID] + ) modes = ( - get_capability(hass, config[ATTR_ENTITY_ID], const.ATTR_AVAILABLE_MODES) - or [] + get_capability(hass, entry.entity_id, const.ATTR_AVAILABLE_MODES) or [] ) except HomeAssistantError: modes = [] diff --git a/tests/components/humidifier/test_device_condition.py b/tests/components/humidifier/test_device_condition.py index 22dfc5c31d5..bf8eb98f456 100644 --- a/tests/components/humidifier/test_device_condition.py +++ b/tests/components/humidifier/test_device_condition.py @@ -89,7 +89,7 @@ async def test_get_conditions( "domain": DOMAIN, "type": condition, "device_id": device_entry.id, - "entity_id": entity_entry.entity_id, + "entity_id": entity_entry.id, "metadata": {"secondary": False}, } for condition in expected_condition_types @@ -206,7 +206,7 @@ async def test_if_state( "condition": "device", "domain": DOMAIN, "device_id": "", - "entity_id": entry.entity_id, + "entity_id": entry.id, "type": "is_mode", "mode": "away", } @@ -253,6 +253,53 @@ async def test_if_state( assert len(calls) == 3 +async def test_if_state_legacy( + hass: HomeAssistant, entity_registry: er.EntityRegistry, calls +) -> None: + """Test for turn_on and turn_off conditions.""" + entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678") + + hass.states.async_set(entry.entity_id, STATE_ON, {ATTR_MODE: const.MODE_AWAY}) + + assert await async_setup_component( + hass, + automation.DOMAIN, + { + automation.DOMAIN: [ + { + "trigger": {"platform": "event", "event_type": "test_event1"}, + "condition": [ + { + "condition": "device", + "domain": DOMAIN, + "device_id": "", + "entity_id": entry.entity_id, + "type": "is_mode", + "mode": "away", + } + ], + "action": { + "service": "test.automation", + "data_template": { + "some": "is_mode - {{ trigger.platform }} - {{ trigger.event.event_type }}" + }, + }, + }, + ] + }, + ) + await hass.async_block_till_done() + assert len(calls) == 0 + + hass.states.async_set(entry.entity_id, STATE_ON, {ATTR_MODE: const.MODE_AWAY}) + + hass.bus.async_fire("test_event1") + await hass.async_block_till_done() + + assert len(calls) == 1 + assert calls[0].data["some"] == "is_mode - event - test_event1" + + @pytest.mark.parametrize( ( "set_state", @@ -403,6 +450,176 @@ async def test_capabilities( capabilities_state, ) + capabilities = await device_condition.async_get_condition_capabilities( + hass, + { + "domain": DOMAIN, + "device_id": "abcdefgh", + "entity_id": entity_entry.id, + "type": condition, + }, + ) + + assert capabilities and "extra_fields" in capabilities + + assert ( + voluptuous_serialize.convert( + capabilities["extra_fields"], custom_serializer=cv.custom_serializer + ) + == expected_capabilities + ) + + +@pytest.mark.parametrize( + ( + "set_state", + "capabilities_reg", + "capabilities_state", + "condition", + "expected_capabilities", + ), + [ + ( + False, + {}, + {}, + "is_mode", + [ + { + "name": "mode", + "options": [], + "required": True, + "type": "select", + } + ], + ), + ( + False, + {const.ATTR_AVAILABLE_MODES: [const.MODE_HOME, const.MODE_AWAY]}, + {}, + "is_mode", + [ + { + "name": "mode", + "options": [("home", "home"), ("away", "away")], + "required": True, + "type": "select", + } + ], + ), + ( + False, + {}, + {}, + "is_off", + [ + { + "name": "for", + "optional": True, + "type": "positive_time_period_dict", + } + ], + ), + ( + False, + {}, + {}, + "is_on", + [ + { + "name": "for", + "optional": True, + "type": "positive_time_period_dict", + } + ], + ), + ( + True, + {}, + {}, + "is_mode", + [ + { + "name": "mode", + "options": [], + "required": True, + "type": "select", + } + ], + ), + ( + True, + {}, + {const.ATTR_AVAILABLE_MODES: [const.MODE_HOME, const.MODE_AWAY]}, + "is_mode", + [ + { + "name": "mode", + "options": [("home", "home"), ("away", "away")], + "required": True, + "type": "select", + } + ], + ), + ( + True, + {}, + {}, + "is_off", + [ + { + "name": "for", + "optional": True, + "type": "positive_time_period_dict", + } + ], + ), + ( + True, + {}, + {}, + "is_on", + [ + { + "name": "for", + "optional": True, + "type": "positive_time_period_dict", + } + ], + ), + ], +) +async def test_capabilities_legacy( + hass: HomeAssistant, + device_registry: dr.DeviceRegistry, + entity_registry: er.EntityRegistry, + set_state, + capabilities_reg, + capabilities_state, + condition, + expected_capabilities, +) -> None: + """Test getting capabilities.""" + 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_entry = entity_registry.async_get_or_create( + DOMAIN, + "test", + "5678", + device_id=device_entry.id, + capabilities=capabilities_reg, + ) + if set_state: + hass.states.async_set( + entity_entry.entity_id, + STATE_ON, + capabilities_state, + ) + capabilities = await device_condition.async_get_condition_capabilities( hass, { @@ -441,7 +658,7 @@ async def test_capabilities_missing_entity( { "domain": DOMAIN, "device_id": "abcdefgh", - "entity_id": f"{DOMAIN}.test_5678", + "entity_id": "0123456789", "type": condition, }, )