Mark device actions from hidden or auxiliary entities as secondary (#70278)

This commit is contained in:
Erik Montnemery 2022-04-20 19:48:46 +02:00 committed by GitHub
parent 2a99084911
commit 64381acbaf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 875 additions and 164 deletions

View file

@ -67,7 +67,7 @@ async def async_get_actions(
supported_features = get_supported_features(hass, entry.entity_id) supported_features = get_supported_features(hass, entry.entity_id)
base_action = { base_action: dict = {
CONF_DEVICE_ID: device_id, CONF_DEVICE_ID: device_id,
CONF_DOMAIN: DOMAIN, CONF_DOMAIN: DOMAIN,
CONF_ENTITY_ID: entry.entity_id, CONF_ENTITY_ID: entry.entity_id,

View file

@ -13,8 +13,13 @@ import voluptuous as vol
import voluptuous_serialize import voluptuous_serialize
from homeassistant.components import websocket_api from homeassistant.components import websocket_api
from homeassistant.const import CONF_DEVICE_ID, CONF_DOMAIN, CONF_PLATFORM from homeassistant.const import (
from homeassistant.core import HomeAssistant ATTR_ENTITY_ID,
CONF_DEVICE_ID,
CONF_DOMAIN,
CONF_PLATFORM,
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import ( from homeassistant.helpers import (
config_validation as cv, config_validation as cv,
device_registry as dr, device_registry as dr,
@ -166,6 +171,24 @@ async def async_get_device_automation_platform(
return platform return platform
@callback
def _async_set_entity_device_automation_metadata(
hass: HomeAssistant, automation: dict[str, Any]
) -> None:
"""Set device automation metadata based on entity registry entry data."""
if "metadata" not in automation:
automation["metadata"] = {}
if ATTR_ENTITY_ID not in automation or "secondary" in automation["metadata"]:
return
entity_registry = er.async_get(hass)
# Guard against the entry being removed before this is called
if not (entry := entity_registry.async_get(automation[ATTR_ENTITY_ID])):
return
automation["metadata"]["secondary"] = bool(entry.entity_category or entry.hidden_by)
async def _async_get_device_automations_from_domain( async def _async_get_device_automations_from_domain(
hass, domain, automation_type, device_ids, return_exceptions hass, domain, automation_type, device_ids, return_exceptions
): ):
@ -242,6 +265,8 @@ async def async_get_device_automations(
) )
continue continue
for automation in device_results: for automation in device_results:
if automation_type == DeviceAutomationType.ACTION:
_async_set_entity_device_automation_metadata(hass, automation)
combined_results[automation["device_id"]].append(automation) combined_results[automation["device_id"]].append(automation)
return combined_results return combined_results

View file

@ -1465,6 +1465,7 @@ DEVICE_ACTION_BASE_SCHEMA = vol.Schema(
**SCRIPT_ACTION_BASE_SCHEMA, **SCRIPT_ACTION_BASE_SCHEMA,
vol.Required(CONF_DEVICE_ID): string, vol.Required(CONF_DEVICE_ID): string,
vol.Required(CONF_DOMAIN): str, vol.Required(CONF_DOMAIN): str,
vol.Remove("metadata"): dict,
} }
) )

View file

@ -6,6 +6,7 @@ from homeassistant.components.NEW_DOMAIN import DOMAIN
from homeassistant.components.device_automation import DeviceAutomationType from homeassistant.components.device_automation import DeviceAutomationType
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry, entity_registry from homeassistant.helpers import device_registry, entity_registry
from homeassistant.helpers.entity import EntityCategory
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from tests.common import ( from tests.common import (
@ -46,16 +47,58 @@ async def test_get_actions(
expected_actions = [ expected_actions = [
{ {
"domain": DOMAIN, "domain": DOMAIN,
"type": "turn_on", "type": action,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": "NEW_DOMAIN.test_5678", "entity_id": f"{DOMAIN}.test_5678",
}, }
for action in ["turn_off", "turn_on"]
]
actions = await async_get_device_automations(
hass, DeviceAutomationType.ACTION, device_entry.id
)
assert_lists_same(actions, expected_actions)
@pytest.mark.parametrize(
"hidden_by,entity_category",
(
(entity_registry.RegistryEntryHider.INTEGRATION, None),
(entity_registry.RegistryEntryHider.USER, None),
(None, EntityCategory.CONFIG),
(None, EntityCategory.DIAGNOSTIC),
),
)
async def test_get_actions_hidden_auxiliary(
hass,
device_reg,
entity_reg,
hidden_by,
entity_category,
):
"""Test we get the expected actions from a hidden or auxiliary entity."""
config_entry = MockConfigEntry(domain="test", data={})
config_entry.add_to_hass(hass)
device_entry = device_reg.async_get_or_create(
config_entry_id=config_entry.entry_id,
connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
)
entity_reg.async_get_or_create(
DOMAIN,
"test",
"5678",
device_id=device_entry.id,
entity_category=entity_category,
hidden_by=hidden_by,
)
expected_actions = [
{ {
"domain": DOMAIN, "domain": DOMAIN,
"type": "turn_off", "type": action,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": "NEW_DOMAIN.test_5678", "entity_id": f"{DOMAIN}.test_5678",
}, "metadata": {"secondary": True},
}
for action in ["turn_off", "turn_on", "toggle"]
] ]
actions = await async_get_device_automations( actions = await async_get_device_automations(
hass, DeviceAutomationType.ACTION, device_entry.id hass, DeviceAutomationType.ACTION, device_entry.id

View file

@ -2,7 +2,6 @@
from __future__ import annotations from __future__ import annotations
import asyncio import asyncio
import collections
from collections import OrderedDict from collections import OrderedDict
from collections.abc import Awaitable, Collection from collections.abc import Awaitable, Collection
from contextlib import contextmanager from contextlib import contextmanager
@ -1226,72 +1225,17 @@ def async_mock_signal(hass, signal):
return calls return calls
class hashdict(dict):
"""
hashable dict implementation, suitable for use as a key into other dicts.
>>> h1 = hashdict({"apples": 1, "bananas":2})
>>> h2 = hashdict({"bananas": 3, "mangoes": 5})
>>> h1+h2
hashdict(apples=1, bananas=3, mangoes=5)
>>> d1 = {}
>>> d1[h1] = "salad"
>>> d1[h1]
'salad'
>>> d1[h2]
Traceback (most recent call last):
...
KeyError: hashdict(bananas=3, mangoes=5)
based on answers from
http://stackoverflow.com/questions/1151658/python-hashable-dicts
"""
def __key(self):
return tuple(sorted(self.items()))
def __repr__(self): # noqa: D105 no docstring
return ", ".join(f"{i[0]!s}={i[1]!r}" for i in self.__key())
def __hash__(self): # noqa: D105 no docstring
return hash(self.__key())
def __setitem__(self, key, value): # noqa: D105 no docstring
raise TypeError(f"{self.__class__.__name__} does not support item assignment")
def __delitem__(self, key): # noqa: D105 no docstring
raise TypeError(f"{self.__class__.__name__} does not support item assignment")
def clear(self): # noqa: D102 no docstring
raise TypeError(f"{self.__class__.__name__} does not support item assignment")
def pop(self, *args, **kwargs): # noqa: D102 no docstring
raise TypeError(f"{self.__class__.__name__} does not support item assignment")
def popitem(self, *args, **kwargs): # noqa: D102 no docstring
raise TypeError(f"{self.__class__.__name__} does not support item assignment")
def setdefault(self, *args, **kwargs): # noqa: D102 no docstring
raise TypeError(f"{self.__class__.__name__} does not support item assignment")
def update(self, *args, **kwargs): # noqa: D102 no docstring
raise TypeError(f"{self.__class__.__name__} does not support item assignment")
# update is not ok because it mutates the object
# __add__ is ok because it creates a new object
# while the new object is under construction, it's ok to mutate it
def __add__(self, right): # noqa: D105 no docstring
result = hashdict(self)
dict.update(result, right)
return result
def assert_lists_same(a, b): def assert_lists_same(a, b):
"""Compare two lists, ignoring order.""" """Compare two lists, ignoring order.
assert collections.Counter([hashdict(i) for i in a]) == collections.Counter(
[hashdict(i) for i in b] Check both that all items in a are in b and that all items in b are in a,
) otherwise assert_lists_same(["1", "1"], ["1", "2"]) could be True.
"""
assert len(a) == len(b)
for i in a:
assert i in b
for i in b:
assert i in a
def raise_contains_mocks(val): def raise_contains_mocks(val):

View file

@ -15,6 +15,8 @@ from homeassistant.const import (
STATE_UNKNOWN, STATE_UNKNOWN,
) )
from homeassistant.helpers import device_registry from homeassistant.helpers import device_registry
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_registry import RegistryEntryHider
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from tests.common import ( from tests.common import (
@ -125,6 +127,7 @@ async def test_get_actions(
"type": action, "type": action,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": f"{DOMAIN}.test_5678",
"metadata": {"secondary": False},
} }
for action in expected_action_types for action in expected_action_types
] ]
@ -134,6 +137,55 @@ async def test_get_actions(
assert_lists_same(actions, expected_actions) assert_lists_same(actions, expected_actions)
@pytest.mark.parametrize(
"hidden_by,entity_category",
(
(RegistryEntryHider.INTEGRATION, None),
(RegistryEntryHider.USER, None),
(None, EntityCategory.CONFIG),
(None, EntityCategory.DIAGNOSTIC),
),
)
async def test_get_actions_hidden_auxiliary(
hass,
device_reg,
entity_reg,
hidden_by,
entity_category,
):
"""Test we get the expected actions from a hidden or auxiliary entity."""
config_entry = MockConfigEntry(domain="test", data={})
config_entry.add_to_hass(hass)
device_entry = device_reg.async_get_or_create(
config_entry_id=config_entry.entry_id,
connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
)
entity_reg.async_get_or_create(
DOMAIN,
"test",
"5678",
device_id=device_entry.id,
entity_category=entity_category,
hidden_by=hidden_by,
supported_features=const.AlarmControlPanelEntityFeature.ARM_AWAY,
)
expected_actions = []
expected_actions += [
{
"domain": DOMAIN,
"type": action,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"metadata": {"secondary": True},
}
for action in ["disarm", "arm_away"]
]
actions = await async_get_device_automations(
hass, DeviceAutomationType.ACTION, device_entry.id
)
assert_lists_same(actions, expected_actions)
async def test_get_actions_arm_night_only(hass, device_reg, entity_reg): async def test_get_actions_arm_night_only(hass, device_reg, entity_reg):
"""Test we get the expected actions from a alarm_control_panel.""" """Test we get the expected actions from a alarm_control_panel."""
config_entry = MockConfigEntry(domain="test", data={}) config_entry = MockConfigEntry(domain="test", data={})
@ -152,12 +204,14 @@ async def test_get_actions_arm_night_only(hass, device_reg, entity_reg):
"type": "arm_night", "type": "arm_night",
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": "alarm_control_panel.test_5678", "entity_id": "alarm_control_panel.test_5678",
"metadata": {"secondary": False},
}, },
{ {
"domain": DOMAIN, "domain": DOMAIN,
"type": "disarm", "type": "disarm",
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": "alarm_control_panel.test_5678", "entity_id": "alarm_control_panel.test_5678",
"metadata": {"secondary": False},
}, },
] ]
actions = await async_get_device_automations( actions = await async_get_device_automations(

View file

@ -6,6 +6,7 @@ from homeassistant.components.button import DOMAIN
from homeassistant.components.device_automation import DeviceAutomationType from homeassistant.components.device_automation import DeviceAutomationType
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry, entity_registry from homeassistant.helpers import device_registry, entity_registry
from homeassistant.helpers.entity import EntityCategory
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from tests.common import ( from tests.common import (
@ -49,6 +50,7 @@ async def test_get_actions(
"type": "press", "type": "press",
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": "button.test_5678", "entity_id": "button.test_5678",
"metadata": {"secondary": False},
} }
] ]
actions = await async_get_device_automations( actions = await async_get_device_automations(
@ -57,6 +59,54 @@ async def test_get_actions(
assert_lists_same(actions, expected_actions) assert_lists_same(actions, expected_actions)
@pytest.mark.parametrize(
"hidden_by,entity_category",
(
(entity_registry.RegistryEntryHider.INTEGRATION, None),
(entity_registry.RegistryEntryHider.USER, None),
(None, EntityCategory.CONFIG),
(None, EntityCategory.DIAGNOSTIC),
),
)
async def test_get_actions_hidden_auxiliary(
hass,
device_reg,
entity_reg,
hidden_by,
entity_category,
):
"""Test we get the expected actions from a hidden or auxiliary entity."""
config_entry = MockConfigEntry(domain="test", data={})
config_entry.add_to_hass(hass)
device_entry = device_reg.async_get_or_create(
config_entry_id=config_entry.entry_id,
connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
)
entity_reg.async_get_or_create(
DOMAIN,
"test",
"5678",
device_id=device_entry.id,
entity_category=entity_category,
hidden_by=hidden_by,
)
expected_actions = []
expected_actions += [
{
"domain": DOMAIN,
"type": action,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"metadata": {"secondary": True},
}
for action in ["press"]
]
actions = await async_get_device_automations(
hass, DeviceAutomationType.ACTION, device_entry.id
)
assert_lists_same(actions, expected_actions)
async def test_action(hass: HomeAssistant) -> None: async def test_action(hass: HomeAssistant) -> None:
"""Test for press action.""" """Test for press action."""
assert await async_setup_component( assert await async_setup_component(

View file

@ -6,6 +6,8 @@ import homeassistant.components.automation as automation
from homeassistant.components.climate import DOMAIN, const, device_action from homeassistant.components.climate import DOMAIN, const, device_action
from homeassistant.components.device_automation import DeviceAutomationType from homeassistant.components.device_automation import DeviceAutomationType
from homeassistant.helpers import config_validation as cv, device_registry from homeassistant.helpers import config_validation as cv, device_registry
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_registry import RegistryEntryHider
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from tests.common import ( from tests.common import (
@ -86,6 +88,7 @@ async def test_get_actions(
"type": action, "type": action,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": f"{DOMAIN}.test_5678",
"metadata": {"secondary": False},
} }
for action in expected_action_types for action in expected_action_types
] ]
@ -96,6 +99,55 @@ async def test_get_actions(
assert_lists_same(actions, expected_actions) assert_lists_same(actions, expected_actions)
@pytest.mark.parametrize(
"hidden_by,entity_category",
(
(RegistryEntryHider.INTEGRATION, None),
(RegistryEntryHider.USER, None),
(None, EntityCategory.CONFIG),
(None, EntityCategory.DIAGNOSTIC),
),
)
async def test_get_actions_hidden_auxiliary(
hass,
device_reg,
entity_reg,
hidden_by,
entity_category,
):
"""Test we get the expected actions from a hidden or auxiliary entity."""
config_entry = MockConfigEntry(domain="test", data={})
config_entry.add_to_hass(hass)
device_entry = device_reg.async_get_or_create(
config_entry_id=config_entry.entry_id,
connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
)
entity_reg.async_get_or_create(
DOMAIN,
"test",
"5678",
device_id=device_entry.id,
entity_category=entity_category,
hidden_by=hidden_by,
supported_features=0,
)
expected_actions = []
expected_actions += [
{
"domain": DOMAIN,
"type": action,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"metadata": {"secondary": True},
}
for action in ["set_hvac_mode"]
]
actions = await async_get_device_automations(
hass, DeviceAutomationType.ACTION, device_entry.id
)
assert_lists_same(actions, expected_actions)
async def test_action(hass): async def test_action(hass):
"""Test for actions.""" """Test for actions."""
hass.states.async_set( hass.states.async_set(

View file

@ -16,6 +16,8 @@ from homeassistant.components.cover import (
from homeassistant.components.device_automation import DeviceAutomationType from homeassistant.components.device_automation import DeviceAutomationType
from homeassistant.const import CONF_PLATFORM from homeassistant.const import CONF_PLATFORM
from homeassistant.helpers import device_registry from homeassistant.helpers import device_registry
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_registry import RegistryEntryHider
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from tests.common import ( from tests.common import (
@ -99,6 +101,7 @@ async def test_get_actions(
"type": action, "type": action,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": f"{DOMAIN}.test_5678",
"metadata": {"secondary": False},
} }
for action in expected_action_types for action in expected_action_types
] ]
@ -108,6 +111,55 @@ async def test_get_actions(
assert_lists_same(actions, expected_actions) assert_lists_same(actions, expected_actions)
@pytest.mark.parametrize(
"hidden_by,entity_category",
(
(RegistryEntryHider.INTEGRATION, None),
(RegistryEntryHider.USER, None),
(None, EntityCategory.CONFIG),
(None, EntityCategory.DIAGNOSTIC),
),
)
async def test_get_actions_hidden_auxiliary(
hass,
device_reg,
entity_reg,
hidden_by,
entity_category,
):
"""Test we get the expected actions from a hidden or auxiliary entity."""
config_entry = MockConfigEntry(domain="test", data={})
config_entry.add_to_hass(hass)
device_entry = device_reg.async_get_or_create(
config_entry_id=config_entry.entry_id,
connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
)
entity_reg.async_get_or_create(
DOMAIN,
"test",
"5678",
device_id=device_entry.id,
entity_category=entity_category,
hidden_by=hidden_by,
supported_features=SUPPORT_CLOSE,
)
expected_actions = []
expected_actions += [
{
"domain": DOMAIN,
"type": action,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"metadata": {"secondary": True},
}
for action in ["close"]
]
actions = await async_get_device_automations(
hass, DeviceAutomationType.ACTION, device_entry.id
)
assert_lists_same(actions, expected_actions)
async def test_get_action_capabilities( async def test_get_action_capabilities(
hass, device_reg, entity_reg, enable_custom_integrations hass, device_reg, entity_reg, enable_custom_integrations
): ):

View file

@ -57,18 +57,21 @@ async def test_websocket_get_actions(hass, hass_ws_client, device_reg, entity_re
"type": "turn_off", "type": "turn_off",
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": "light.test_5678", "entity_id": "light.test_5678",
"metadata": {"secondary": False},
}, },
{ {
"domain": "light", "domain": "light",
"type": "turn_on", "type": "turn_on",
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": "light.test_5678", "entity_id": "light.test_5678",
"metadata": {"secondary": False},
}, },
{ {
"domain": "light", "domain": "light",
"type": "toggle", "type": "toggle",
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": "light.test_5678", "entity_id": "light.test_5678",
"metadata": {"secondary": False},
}, },
] ]

View file

@ -5,6 +5,8 @@ import homeassistant.components.automation as automation
from homeassistant.components.device_automation import DeviceAutomationType from homeassistant.components.device_automation import DeviceAutomationType
from homeassistant.components.fan import DOMAIN from homeassistant.components.fan import DOMAIN
from homeassistant.helpers import device_registry from homeassistant.helpers import device_registry
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_registry import RegistryEntryHider
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from tests.common import ( from tests.common import (
@ -39,19 +41,64 @@ async def test_get_actions(hass, device_reg, entity_reg):
connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_reg.async_get_or_create(DOMAIN, "test", "5678", device_id=device_entry.id) entity_reg.async_get_or_create(DOMAIN, "test", "5678", device_id=device_entry.id)
expected_actions = [ expected_actions = []
expected_actions += [
{ {
"domain": DOMAIN, "domain": DOMAIN,
"type": "turn_on", "type": action,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": "fan.test_5678", "entity_id": f"{DOMAIN}.test_5678",
}, "metadata": {"secondary": False},
}
for action in ["turn_on", "turn_off"]
]
actions = await async_get_device_automations(
hass, DeviceAutomationType.ACTION, device_entry.id
)
assert_lists_same(actions, expected_actions)
@pytest.mark.parametrize(
"hidden_by,entity_category",
(
(RegistryEntryHider.INTEGRATION, None),
(RegistryEntryHider.USER, None),
(None, EntityCategory.CONFIG),
(None, EntityCategory.DIAGNOSTIC),
),
)
async def test_get_actions_hidden_auxiliary(
hass,
device_reg,
entity_reg,
hidden_by,
entity_category,
):
"""Test we get the expected actions from a hidden or auxiliary entity."""
config_entry = MockConfigEntry(domain="test", data={})
config_entry.add_to_hass(hass)
device_entry = device_reg.async_get_or_create(
config_entry_id=config_entry.entry_id,
connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
)
entity_reg.async_get_or_create(
DOMAIN,
"test",
"5678",
device_id=device_entry.id,
entity_category=entity_category,
hidden_by=hidden_by,
)
expected_actions = []
expected_actions += [
{ {
"domain": DOMAIN, "domain": DOMAIN,
"type": "turn_off", "type": action,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": "fan.test_5678", "entity_id": f"{DOMAIN}.test_5678",
}, "metadata": {"secondary": True},
}
for action in ["turn_on", "turn_off"]
] ]
actions = await async_get_device_automations( actions = await async_get_device_automations(
hass, DeviceAutomationType.ACTION, device_entry.id hass, DeviceAutomationType.ACTION, device_entry.id

View file

@ -7,6 +7,8 @@ from homeassistant.components.device_automation import DeviceAutomationType
from homeassistant.components.humidifier import DOMAIN, const, device_action from homeassistant.components.humidifier import DOMAIN, const, device_action
from homeassistant.const import STATE_ON from homeassistant.const import STATE_ON
from homeassistant.helpers import config_validation as cv, device_registry from homeassistant.helpers import config_validation as cv, device_registry
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_registry import RegistryEntryHider
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from tests.common import ( from tests.common import (
@ -76,6 +78,7 @@ async def test_get_actions(
"type": action, "type": action,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": f"{DOMAIN}.test_5678",
"metadata": {"secondary": False},
} }
for action in basic_action_types for action in basic_action_types
] ]
@ -85,6 +88,7 @@ async def test_get_actions(
"type": action, "type": action,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": f"{DOMAIN}.test_5678",
"metadata": {"secondary": False},
} }
for action in expected_action_types for action in expected_action_types
] ]
@ -94,6 +98,55 @@ async def test_get_actions(
assert_lists_same(actions, expected_actions) assert_lists_same(actions, expected_actions)
@pytest.mark.parametrize(
"hidden_by,entity_category",
(
(RegistryEntryHider.INTEGRATION, None),
(RegistryEntryHider.USER, None),
(None, EntityCategory.CONFIG),
(None, EntityCategory.DIAGNOSTIC),
),
)
async def test_get_actions_hidden_auxiliary(
hass,
device_reg,
entity_reg,
hidden_by,
entity_category,
):
"""Test we get the expected actions from a hidden or auxiliary entity."""
config_entry = MockConfigEntry(domain="test", data={})
config_entry.add_to_hass(hass)
device_entry = device_reg.async_get_or_create(
config_entry_id=config_entry.entry_id,
connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
)
entity_reg.async_get_or_create(
DOMAIN,
"test",
"5678",
device_id=device_entry.id,
entity_category=entity_category,
hidden_by=hidden_by,
supported_features=0,
)
expected_actions = []
expected_actions += [
{
"domain": DOMAIN,
"type": action,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"metadata": {"secondary": True},
}
for action in ["turn_on", "turn_off", "toggle", "set_humidity"]
]
actions = await async_get_device_automations(
hass, DeviceAutomationType.ACTION, device_entry.id
)
assert_lists_same(actions, expected_actions)
async def test_action(hass): async def test_action(hass):
"""Test for actions.""" """Test for actions."""
hass.states.async_set( hass.states.async_set(

View file

@ -13,10 +13,13 @@ from homeassistant.components.light import (
) )
from homeassistant.const import CONF_PLATFORM, STATE_OFF, STATE_ON from homeassistant.const import CONF_PLATFORM, STATE_OFF, STATE_ON
from homeassistant.helpers import device_registry from homeassistant.helpers import device_registry
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_registry import RegistryEntryHider
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from tests.common import ( from tests.common import (
MockConfigEntry, MockConfigEntry,
assert_lists_same,
async_get_device_automation_capabilities, async_get_device_automation_capabilities,
async_get_device_automations, async_get_device_automations,
async_mock_service, async_mock_service,
@ -60,48 +63,78 @@ async def test_get_actions(hass, device_reg, entity_reg):
supported_features=LightEntityFeature.FLASH, supported_features=LightEntityFeature.FLASH,
capabilities={"supported_color_modes": ["brightness"]}, capabilities={"supported_color_modes": ["brightness"]},
) )
expected_actions = [ expected_actions = []
expected_actions += [
{ {
"domain": DOMAIN, "domain": DOMAIN,
"type": "turn_off", "type": action,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": f"{DOMAIN}.test_5678",
}, "metadata": {"secondary": False},
{ }
"domain": DOMAIN, for action in [
"type": "turn_on", "turn_off",
"device_id": device_entry.id, "turn_on",
"entity_id": f"{DOMAIN}.test_5678", "toggle",
}, "brightness_decrease",
{ "brightness_increase",
"domain": DOMAIN, "flash",
"type": "toggle", ]
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
},
{
"domain": DOMAIN,
"type": "brightness_increase",
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
},
{
"domain": DOMAIN,
"type": "brightness_decrease",
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
},
{
"domain": DOMAIN,
"type": "flash",
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
},
] ]
actions = await async_get_device_automations( actions = await async_get_device_automations(
hass, DeviceAutomationType.ACTION, device_entry.id hass, DeviceAutomationType.ACTION, device_entry.id
) )
assert actions == expected_actions assert_lists_same(actions, expected_actions)
@pytest.mark.parametrize(
"hidden_by,entity_category",
(
(RegistryEntryHider.INTEGRATION, None),
(RegistryEntryHider.USER, None),
(None, EntityCategory.CONFIG),
(None, EntityCategory.DIAGNOSTIC),
),
)
async def test_get_actions_hidden_auxiliary(
hass,
device_reg,
entity_reg,
hidden_by,
entity_category,
):
"""Test we get the expected actions from a hidden or auxiliary entity."""
config_entry = MockConfigEntry(domain="test", data={})
config_entry.add_to_hass(hass)
device_entry = device_reg.async_get_or_create(
config_entry_id=config_entry.entry_id,
connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
)
entity_reg.async_get_or_create(
DOMAIN,
"test",
"5678",
device_id=device_entry.id,
entity_category=entity_category,
hidden_by=hidden_by,
supported_features=0,
capabilities={"supported_color_modes": ["onoff"]},
)
expected_actions = []
expected_actions += [
{
"domain": DOMAIN,
"type": action,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"metadata": {"secondary": True},
}
for action in ["turn_on", "turn_off", "toggle"]
]
actions = await async_get_device_automations(
hass, DeviceAutomationType.ACTION, device_entry.id
)
assert_lists_same(actions, expected_actions)
async def test_get_action_capabilities(hass, device_reg, entity_reg): async def test_get_action_capabilities(hass, device_reg, entity_reg):

View file

@ -5,6 +5,8 @@ import homeassistant.components.automation as automation
from homeassistant.components.device_automation import DeviceAutomationType from homeassistant.components.device_automation import DeviceAutomationType
from homeassistant.components.lock import DOMAIN, LockEntityFeature from homeassistant.components.lock import DOMAIN, LockEntityFeature
from homeassistant.helpers import device_registry from homeassistant.helpers import device_registry
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_registry import RegistryEntryHider
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from tests.common import ( from tests.common import (
@ -74,6 +76,7 @@ async def test_get_actions(
"type": action, "type": action,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": f"{DOMAIN}.test_5678",
"metadata": {"secondary": False},
} }
for action in basic_action_types for action in basic_action_types
] ]
@ -83,6 +86,7 @@ async def test_get_actions(
"type": action, "type": action,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": f"{DOMAIN}.test_5678",
"metadata": {"secondary": False},
} }
for action in expected_action_types for action in expected_action_types
] ]
@ -92,6 +96,55 @@ async def test_get_actions(
assert_lists_same(actions, expected_actions) assert_lists_same(actions, expected_actions)
@pytest.mark.parametrize(
"hidden_by,entity_category",
(
(RegistryEntryHider.INTEGRATION, None),
(RegistryEntryHider.USER, None),
(None, EntityCategory.CONFIG),
(None, EntityCategory.DIAGNOSTIC),
),
)
async def test_get_actions_hidden_auxiliary(
hass,
device_reg,
entity_reg,
hidden_by,
entity_category,
):
"""Test we get the expected actions from a hidden or auxiliary entity."""
config_entry = MockConfigEntry(domain="test", data={})
config_entry.add_to_hass(hass)
device_entry = device_reg.async_get_or_create(
config_entry_id=config_entry.entry_id,
connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
)
entity_reg.async_get_or_create(
DOMAIN,
"test",
"5678",
device_id=device_entry.id,
entity_category=entity_category,
hidden_by=hidden_by,
supported_features=0,
)
expected_actions = []
expected_actions += [
{
"domain": DOMAIN,
"type": action,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"metadata": {"secondary": True},
}
for action in ["lock", "unlock"]
]
actions = await async_get_device_automations(
hass, DeviceAutomationType.ACTION, device_entry.id
)
assert_lists_same(actions, expected_actions)
async def test_action(hass): async def test_action(hass):
"""Test for lock actions.""" """Test for lock actions."""
assert await async_setup_component( assert await async_setup_component(

View file

@ -13,7 +13,7 @@ async def test_get_actions(hass, push_registration):
assert await async_get_device_automations( assert await async_get_device_automations(
hass, device_automation.DeviceAutomationType.ACTION, device_id hass, device_automation.DeviceAutomationType.ACTION, device_id
) == [{"domain": DOMAIN, "device_id": device_id, "type": "notify"}] ) == [{"domain": DOMAIN, "device_id": device_id, "metadata": {}, "type": "notify"}]
capabilitites = await device_automation._async_get_device_automation_capabilities( capabilitites = await device_automation._async_get_device_automation_capabilities(
hass, hass,

View file

@ -6,6 +6,8 @@ import homeassistant.components.automation as automation
from homeassistant.components.device_automation import DeviceAutomationType from homeassistant.components.device_automation import DeviceAutomationType
from homeassistant.components.number import DOMAIN, device_action from homeassistant.components.number import DOMAIN, device_action
from homeassistant.helpers import config_validation as cv, device_registry from homeassistant.helpers import config_validation as cv, device_registry
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_registry import RegistryEntryHider
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from tests.common import ( from tests.common import (
@ -47,6 +49,7 @@ async def test_get_actions(hass, device_reg, entity_reg):
"type": "set_value", "type": "set_value",
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": "number.test_5678", "entity_id": "number.test_5678",
"metadata": {"secondary": False},
}, },
] ]
actions = await async_get_device_automations( actions = await async_get_device_automations(
@ -55,6 +58,54 @@ async def test_get_actions(hass, device_reg, entity_reg):
assert_lists_same(actions, expected_actions) assert_lists_same(actions, expected_actions)
@pytest.mark.parametrize(
"hidden_by,entity_category",
(
(RegistryEntryHider.INTEGRATION, None),
(RegistryEntryHider.USER, None),
(None, EntityCategory.CONFIG),
(None, EntityCategory.DIAGNOSTIC),
),
)
async def test_get_actions_hidden_auxiliary(
hass,
device_reg,
entity_reg,
hidden_by,
entity_category,
):
"""Test we get the expected actions from a hidden or auxiliary entity."""
config_entry = MockConfigEntry(domain="test", data={})
config_entry.add_to_hass(hass)
device_entry = device_reg.async_get_or_create(
config_entry_id=config_entry.entry_id,
connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
)
entity_reg.async_get_or_create(
DOMAIN,
"test",
"5678",
device_id=device_entry.id,
entity_category=entity_category,
hidden_by=hidden_by,
)
expected_actions = []
expected_actions += [
{
"domain": DOMAIN,
"type": action,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"metadata": {"secondary": True},
}
for action in ["set_value"]
]
actions = await async_get_device_automations(
hass, DeviceAutomationType.ACTION, device_entry.id
)
assert_lists_same(actions, expected_actions)
async def test_get_action_no_state(hass, device_reg, entity_reg): async def test_get_action_no_state(hass, device_reg, entity_reg):
"""Test we get the expected actions for an entity.""" """Test we get the expected actions for an entity."""
config_entry = MockConfigEntry(domain="test", data={}) config_entry = MockConfigEntry(domain="test", data={})
@ -70,6 +121,7 @@ async def test_get_action_no_state(hass, device_reg, entity_reg):
"type": "set_value", "type": "set_value",
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": "number.test_5678", "entity_id": "number.test_5678",
"metadata": {"secondary": False},
}, },
] ]
actions = await async_get_device_automations( actions = await async_get_device_automations(

View file

@ -6,10 +6,13 @@ from homeassistant.components.device_automation import DeviceAutomationType
from homeassistant.components.remote import DOMAIN from homeassistant.components.remote import DOMAIN
from homeassistant.const import CONF_PLATFORM, STATE_OFF, STATE_ON from homeassistant.const import CONF_PLATFORM, STATE_OFF, STATE_ON
from homeassistant.helpers import device_registry from homeassistant.helpers import device_registry
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_registry import RegistryEntryHider
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from tests.common import ( from tests.common import (
MockConfigEntry, MockConfigEntry,
assert_lists_same,
async_get_device_automations, async_get_device_automations,
async_mock_service, async_mock_service,
mock_device_registry, mock_device_registry,
@ -48,27 +51,65 @@ async def test_get_actions(hass, device_reg, entity_reg):
expected_actions = [ expected_actions = [
{ {
"domain": DOMAIN, "domain": DOMAIN,
"type": "turn_off", "type": action,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": f"{DOMAIN}.test_5678",
}, "metadata": {"secondary": False},
{ }
"domain": DOMAIN, for action in ["turn_off", "turn_on", "toggle"]
"type": "turn_on",
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
},
{
"domain": DOMAIN,
"type": "toggle",
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
},
] ]
actions = await async_get_device_automations( actions = await async_get_device_automations(
hass, DeviceAutomationType.ACTION, device_entry.id hass, DeviceAutomationType.ACTION, device_entry.id
) )
assert actions == expected_actions assert_lists_same(actions, expected_actions)
@pytest.mark.parametrize(
"hidden_by,entity_category",
(
(RegistryEntryHider.INTEGRATION, None),
(RegistryEntryHider.USER, None),
(None, EntityCategory.CONFIG),
(None, EntityCategory.DIAGNOSTIC),
),
)
async def test_get_actions_hidden_auxiliary(
hass,
device_reg,
entity_reg,
hidden_by,
entity_category,
):
"""Test we get the expected actions from a hidden or auxiliary entity."""
config_entry = MockConfigEntry(domain="test", data={})
config_entry.add_to_hass(hass)
device_entry = device_reg.async_get_or_create(
config_entry_id=config_entry.entry_id,
connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
)
entity_reg.async_get_or_create(
DOMAIN,
"test",
"5678",
device_id=device_entry.id,
entity_category=entity_category,
hidden_by=hidden_by,
)
expected_actions = []
expected_actions += [
{
"domain": DOMAIN,
"type": action,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"metadata": {"secondary": True},
}
for action in ["turn_off", "turn_on", "toggle"]
]
actions = await async_get_device_automations(
hass, DeviceAutomationType.ACTION, device_entry.id
)
assert_lists_same(actions, expected_actions)
async def test_action(hass, calls, enable_custom_integrations): async def test_action(hass, calls, enable_custom_integrations):

View file

@ -105,7 +105,7 @@ async def test_get_actions(hass, device_reg: DeviceRegistry, device, expected):
actions = [action for action in actions if action["domain"] == DOMAIN] actions = [action for action in actions if action["domain"] == DOMAIN]
expected_actions = [ expected_actions = [
{"domain": DOMAIN, "device_id": device_entry.id, **action_type} {"domain": DOMAIN, "device_id": device_entry.id, "metadata": {}, **action_type}
for action_type in expected for action_type in expected
] ]

View file

@ -12,6 +12,7 @@ from homeassistant.helpers import (
device_registry, device_registry,
entity_registry, entity_registry,
) )
from homeassistant.helpers.entity import EntityCategory
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from tests.common import ( from tests.common import (
@ -55,6 +56,7 @@ async def test_get_actions(
"type": "select_option", "type": "select_option",
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": "select.test_5678", "entity_id": "select.test_5678",
"metadata": {"secondary": False},
} }
] ]
actions = await async_get_device_automations( actions = await async_get_device_automations(
@ -63,6 +65,54 @@ async def test_get_actions(
assert_lists_same(actions, expected_actions) assert_lists_same(actions, expected_actions)
@pytest.mark.parametrize(
"hidden_by,entity_category",
(
(entity_registry.RegistryEntryHider.INTEGRATION, None),
(entity_registry.RegistryEntryHider.USER, None),
(None, EntityCategory.CONFIG),
(None, EntityCategory.DIAGNOSTIC),
),
)
async def test_get_actions_hidden_auxiliary(
hass,
device_reg,
entity_reg,
hidden_by,
entity_category,
):
"""Test we get the expected actions from a hidden or auxiliary entity."""
config_entry = MockConfigEntry(domain="test", data={})
config_entry.add_to_hass(hass)
device_entry = device_reg.async_get_or_create(
config_entry_id=config_entry.entry_id,
connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
)
entity_reg.async_get_or_create(
DOMAIN,
"test",
"5678",
device_id=device_entry.id,
entity_category=entity_category,
hidden_by=hidden_by,
)
expected_actions = []
expected_actions += [
{
"domain": DOMAIN,
"type": action,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"metadata": {"secondary": True},
}
for action in ["select_option"]
]
actions = await async_get_device_automations(
hass, DeviceAutomationType.ACTION, device_entry.id
)
assert_lists_same(actions, expected_actions)
async def test_action(hass: HomeAssistant) -> None: async def test_action(hass: HomeAssistant) -> None:
"""Test for select_option action.""" """Test for select_option action."""
assert await async_setup_component( assert await async_setup_component(

View file

@ -6,10 +6,13 @@ from homeassistant.components.device_automation import DeviceAutomationType
from homeassistant.components.switch import DOMAIN from homeassistant.components.switch import DOMAIN
from homeassistant.const import CONF_PLATFORM, STATE_OFF, STATE_ON from homeassistant.const import CONF_PLATFORM, STATE_OFF, STATE_ON
from homeassistant.helpers import device_registry from homeassistant.helpers import device_registry
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_registry import RegistryEntryHider
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from tests.common import ( from tests.common import (
MockConfigEntry, MockConfigEntry,
assert_lists_same,
async_get_device_automations, async_get_device_automations,
async_mock_service, async_mock_service,
mock_device_registry, mock_device_registry,
@ -45,30 +48,69 @@ async def test_get_actions(hass, device_reg, entity_reg):
connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_reg.async_get_or_create(DOMAIN, "test", "5678", device_id=device_entry.id) entity_reg.async_get_or_create(DOMAIN, "test", "5678", device_id=device_entry.id)
expected_actions = [ expected_actions = []
expected_actions += [
{ {
"domain": DOMAIN, "domain": DOMAIN,
"type": "turn_off", "type": action,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678", "entity_id": f"{DOMAIN}.test_5678",
}, "metadata": {"secondary": False},
{ }
"domain": DOMAIN, for action in ["turn_off", "turn_on", "toggle"]
"type": "turn_on",
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
},
{
"domain": DOMAIN,
"type": "toggle",
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
},
] ]
actions = await async_get_device_automations( actions = await async_get_device_automations(
hass, DeviceAutomationType.ACTION, device_entry.id hass, DeviceAutomationType.ACTION, device_entry.id
) )
assert actions == expected_actions assert_lists_same(actions, expected_actions)
@pytest.mark.parametrize(
"hidden_by,entity_category",
(
(RegistryEntryHider.INTEGRATION, None),
(RegistryEntryHider.USER, None),
(None, EntityCategory.CONFIG),
(None, EntityCategory.DIAGNOSTIC),
),
)
async def test_get_actions_hidden_auxiliary(
hass,
device_reg,
entity_reg,
hidden_by,
entity_category,
):
"""Test we get the expected actions from a hidden or auxiliary entity."""
config_entry = MockConfigEntry(domain="test", data={})
config_entry.add_to_hass(hass)
device_entry = device_reg.async_get_or_create(
config_entry_id=config_entry.entry_id,
connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
)
entity_reg.async_get_or_create(
DOMAIN,
"test",
"5678",
device_id=device_entry.id,
entity_category=entity_category,
hidden_by=hidden_by,
)
expected_actions = []
expected_actions += [
{
"domain": DOMAIN,
"type": action,
"device_id": device_entry.id,
"entity_id": f"{DOMAIN}.test_5678",
"metadata": {"secondary": True},
}
for action in ["turn_off", "turn_on", "toggle"]
]
actions = await async_get_device_automations(
hass, DeviceAutomationType.ACTION, device_entry.id
)
assert_lists_same(actions, expected_actions)
async def test_action(hass, calls, enable_custom_integrations): async def test_action(hass, calls, enable_custom_integrations):

View file

@ -5,6 +5,8 @@ import homeassistant.components.automation as automation
from homeassistant.components.device_automation import DeviceAutomationType from homeassistant.components.device_automation import DeviceAutomationType
from homeassistant.components.vacuum import DOMAIN from homeassistant.components.vacuum import DOMAIN
from homeassistant.helpers import device_registry from homeassistant.helpers import device_registry
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_registry import RegistryEntryHider
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from tests.common import ( from tests.common import (
@ -39,19 +41,64 @@ async def test_get_actions(hass, device_reg, entity_reg):
connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_reg.async_get_or_create(DOMAIN, "test", "5678", device_id=device_entry.id) entity_reg.async_get_or_create(DOMAIN, "test", "5678", device_id=device_entry.id)
expected_actions = [ expected_actions = []
expected_actions += [
{ {
"domain": DOMAIN, "domain": DOMAIN,
"type": "clean", "type": action,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": "vacuum.test_5678", "entity_id": "vacuum.test_5678",
}, "metadata": {"secondary": False},
}
for action in ["clean", "dock"]
]
actions = await async_get_device_automations(
hass, DeviceAutomationType.ACTION, device_entry.id
)
assert_lists_same(actions, expected_actions)
@pytest.mark.parametrize(
"hidden_by,entity_category",
(
(RegistryEntryHider.INTEGRATION, None),
(RegistryEntryHider.USER, None),
(None, EntityCategory.CONFIG),
(None, EntityCategory.DIAGNOSTIC),
),
)
async def test_get_actions_hidden_auxiliary(
hass,
device_reg,
entity_reg,
hidden_by,
entity_category,
):
"""Test we get the expected actions from a hidden or auxiliary entity."""
config_entry = MockConfigEntry(domain="test", data={})
config_entry.add_to_hass(hass)
device_entry = device_reg.async_get_or_create(
config_entry_id=config_entry.entry_id,
connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
)
entity_reg.async_get_or_create(
DOMAIN,
"test",
"5678",
device_id=device_entry.id,
entity_category=entity_category,
hidden_by=hidden_by,
)
expected_actions = []
expected_actions += [
{ {
"domain": DOMAIN, "domain": DOMAIN,
"type": "dock", "type": action,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": "vacuum.test_5678", "entity_id": f"{DOMAIN}.test_5678",
}, "metadata": {"secondary": True},
}
for action in ["clean", "dock"]
] ]
actions = await async_get_device_automations( actions = await async_get_device_automations(
hass, DeviceAutomationType.ACTION, device_entry.id hass, DeviceAutomationType.ACTION, device_entry.id

View file

@ -5,6 +5,8 @@ import homeassistant.components.automation as automation
from homeassistant.components.device_automation import DeviceAutomationType from homeassistant.components.device_automation import DeviceAutomationType
from homeassistant.components.water_heater import DOMAIN from homeassistant.components.water_heater import DOMAIN
from homeassistant.helpers import device_registry from homeassistant.helpers import device_registry
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_registry import RegistryEntryHider
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from tests.common import ( from tests.common import (
@ -39,19 +41,64 @@ async def test_get_actions(hass, device_reg, entity_reg):
connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
) )
entity_reg.async_get_or_create(DOMAIN, "test", "5678", device_id=device_entry.id) entity_reg.async_get_or_create(DOMAIN, "test", "5678", device_id=device_entry.id)
expected_actions = [ expected_actions = []
expected_actions += [
{ {
"domain": DOMAIN, "domain": DOMAIN,
"type": "turn_on", "type": action,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": "water_heater.test_5678", "entity_id": f"{DOMAIN}.test_5678",
}, "metadata": {"secondary": False},
}
for action in ["turn_on", "turn_off"]
]
actions = await async_get_device_automations(
hass, DeviceAutomationType.ACTION, device_entry.id
)
assert_lists_same(actions, expected_actions)
@pytest.mark.parametrize(
"hidden_by,entity_category",
(
(RegistryEntryHider.INTEGRATION, None),
(RegistryEntryHider.USER, None),
(None, EntityCategory.CONFIG),
(None, EntityCategory.DIAGNOSTIC),
),
)
async def test_get_actions_hidden_auxiliary(
hass,
device_reg,
entity_reg,
hidden_by,
entity_category,
):
"""Test we get the expected actions from a hidden or auxiliary entity."""
config_entry = MockConfigEntry(domain="test", data={})
config_entry.add_to_hass(hass)
device_entry = device_reg.async_get_or_create(
config_entry_id=config_entry.entry_id,
connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
)
entity_reg.async_get_or_create(
DOMAIN,
"test",
"5678",
device_id=device_entry.id,
entity_category=entity_category,
hidden_by=hidden_by,
)
expected_actions = []
expected_actions += [
{ {
"domain": DOMAIN, "domain": DOMAIN,
"type": "turn_off", "type": action,
"device_id": device_entry.id, "device_id": device_entry.id,
"entity_id": "water_heater.test_5678", "entity_id": f"{DOMAIN}.test_5678",
}, "metadata": {"secondary": True},
}
for action in ["turn_on", "turn_off"]
] ]
actions = await async_get_device_automations( actions = await async_get_device_automations(
hass, DeviceAutomationType.ACTION, device_entry.id hass, DeviceAutomationType.ACTION, device_entry.id

View file

@ -58,31 +58,40 @@ async def test_get_actions(hass, device_ias):
) )
expected_actions = [ expected_actions = [
{"domain": DOMAIN, "type": "squawk", "device_id": reg_device.id}, {
{"domain": DOMAIN, "type": "warn", "device_id": reg_device.id}, "domain": DOMAIN,
"type": "squawk",
"device_id": reg_device.id,
"metadata": {},
},
{"domain": DOMAIN, "type": "warn", "device_id": reg_device.id, "metadata": {}},
{ {
"domain": Platform.SELECT, "domain": Platform.SELECT,
"type": "select_option", "type": "select_option",
"device_id": reg_device.id, "device_id": reg_device.id,
"entity_id": "select.fakemanufacturer_fakemodel_e769900a_ias_wd_warningmode", "entity_id": "select.fakemanufacturer_fakemodel_e769900a_ias_wd_warningmode",
"metadata": {"secondary": True},
}, },
{ {
"domain": Platform.SELECT, "domain": Platform.SELECT,
"type": "select_option", "type": "select_option",
"device_id": reg_device.id, "device_id": reg_device.id,
"entity_id": "select.fakemanufacturer_fakemodel_e769900a_ias_wd_sirenlevel", "entity_id": "select.fakemanufacturer_fakemodel_e769900a_ias_wd_sirenlevel",
"metadata": {"secondary": True},
}, },
{ {
"domain": Platform.SELECT, "domain": Platform.SELECT,
"type": "select_option", "type": "select_option",
"device_id": reg_device.id, "device_id": reg_device.id,
"entity_id": "select.fakemanufacturer_fakemodel_e769900a_ias_wd_strobelevel", "entity_id": "select.fakemanufacturer_fakemodel_e769900a_ias_wd_strobelevel",
"metadata": {"secondary": True},
}, },
{ {
"domain": Platform.SELECT, "domain": Platform.SELECT,
"type": "select_option", "type": "select_option",
"device_id": reg_device.id, "device_id": reg_device.id,
"entity_id": "select.fakemanufacturer_fakemodel_e769900a_ias_wd_strobe", "entity_id": "select.fakemanufacturer_fakemodel_e769900a_ias_wd_strobe",
"metadata": {"secondary": True},
}, },
] ]

View file

@ -38,28 +38,40 @@ async def test_get_actions(
"type": "clear_lock_usercode", "type": "clear_lock_usercode",
"device_id": device.id, "device_id": device.id,
"entity_id": "lock.touchscreen_deadbolt", "entity_id": "lock.touchscreen_deadbolt",
"metadata": {"secondary": False},
}, },
{ {
"domain": DOMAIN, "domain": DOMAIN,
"type": "set_lock_usercode", "type": "set_lock_usercode",
"device_id": device.id, "device_id": device.id,
"entity_id": "lock.touchscreen_deadbolt", "entity_id": "lock.touchscreen_deadbolt",
"metadata": {"secondary": False},
},
{
"domain": DOMAIN,
"type": "refresh_value",
"device_id": device.id,
"entity_id": "binary_sensor.touchscreen_deadbolt_low_battery_level",
"metadata": {"secondary": True},
}, },
{ {
"domain": DOMAIN, "domain": DOMAIN,
"type": "refresh_value", "type": "refresh_value",
"device_id": device.id, "device_id": device.id,
"entity_id": "lock.touchscreen_deadbolt", "entity_id": "lock.touchscreen_deadbolt",
"metadata": {"secondary": False},
}, },
{ {
"domain": DOMAIN, "domain": DOMAIN,
"type": "set_value", "type": "set_value",
"device_id": device.id, "device_id": device.id,
"metadata": {},
}, },
{ {
"domain": DOMAIN, "domain": DOMAIN,
"type": "ping", "type": "ping",
"device_id": device.id, "device_id": device.id,
"metadata": {},
}, },
{ {
"domain": DOMAIN, "domain": DOMAIN,
@ -68,6 +80,7 @@ async def test_get_actions(
"parameter": 3, "parameter": 3,
"bitmask": None, "bitmask": None,
"subtype": "3 (Beeper)", "subtype": "3 (Beeper)",
"metadata": {},
}, },
] ]
actions = await async_get_device_automations( actions = await async_get_device_automations(