Improve editing of device automation referring non added select entity (#52047)

* Improve editing of device automation referring non added select entity

* Update tests
This commit is contained in:
Erik Montnemery 2021-06-21 14:49:51 +02:00 committed by GitHub
parent f29bcf7ff7
commit b916247e8e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 79 additions and 31 deletions

View File

@ -112,6 +112,8 @@ async def async_get_action_capabilities(
hass: HomeAssistant, config: ConfigType hass: HomeAssistant, config: ConfigType
) -> dict[str, vol.Schema]: ) -> dict[str, vol.Schema]:
"""List action capabilities.""" """List action capabilities."""
# We need to refer to the state directly because ATTR_CODE_ARM_REQUIRED is not a
# capability attribute
state = hass.states.get(config[CONF_ENTITY_ID]) state = hass.states.get(config[CONF_ENTITY_ID])
code_required = state.attributes.get(ATTR_CODE_ARM_REQUIRED) if state else False code_required = state.attributes.get(ATTR_CODE_ARM_REQUIRED) if state else False

View File

@ -12,9 +12,10 @@ from homeassistant.const import (
CONF_ENTITY_ID, CONF_ENTITY_ID,
CONF_TYPE, CONF_TYPE,
) )
from homeassistant.core import Context, HomeAssistant from homeassistant.core import Context, HomeAssistant, HomeAssistantError
from homeassistant.helpers import entity_registry from homeassistant.helpers import entity_registry
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import get_capability
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType
from .const import ATTR_OPTION, ATTR_OPTIONS, CONF_OPTION, DOMAIN, SERVICE_SELECT_OPTION from .const import ATTR_OPTION, ATTR_OPTIONS, CONF_OPTION, DOMAIN, SERVICE_SELECT_OPTION
@ -65,16 +66,9 @@ async def async_get_action_capabilities(
hass: HomeAssistant, config: ConfigType hass: HomeAssistant, config: ConfigType
) -> dict[str, Any]: ) -> dict[str, Any]:
"""List action capabilities.""" """List action capabilities."""
state = hass.states.get(config[CONF_ENTITY_ID]) try:
if state is None: options = get_capability(hass, config[CONF_ENTITY_ID], ATTR_OPTIONS) or []
return {} except HomeAssistantError:
options = []
return { return {"extra_fields": vol.Schema({vol.Required(CONF_OPTION): vol.In(options)})}
"extra_fields": vol.Schema(
{
vol.Required(CONF_OPTION): vol.In(
state.attributes.get(ATTR_OPTIONS, [])
),
}
)
}

View File

@ -13,9 +13,10 @@ from homeassistant.const import (
CONF_FOR, CONF_FOR,
CONF_TYPE, CONF_TYPE,
) )
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, HomeAssistantError, callback
from homeassistant.helpers import condition, config_validation as cv, entity_registry from homeassistant.helpers import condition, config_validation as cv, entity_registry
from homeassistant.helpers.config_validation import DEVICE_CONDITION_BASE_SCHEMA from homeassistant.helpers.config_validation import DEVICE_CONDITION_BASE_SCHEMA
from homeassistant.helpers.entity import get_capability
from homeassistant.helpers.typing import ConfigType, TemplateVarsType from homeassistant.helpers.typing import ConfigType, TemplateVarsType
from .const import ATTR_OPTIONS, CONF_OPTION, DOMAIN from .const import ATTR_OPTIONS, CONF_OPTION, DOMAIN
@ -72,16 +73,15 @@ async def async_get_condition_capabilities(
hass: HomeAssistant, config: ConfigType hass: HomeAssistant, config: ConfigType
) -> dict[str, Any]: ) -> dict[str, Any]:
"""List condition capabilities.""" """List condition capabilities."""
state = hass.states.get(config[CONF_ENTITY_ID]) try:
if state is None: options = get_capability(hass, config[CONF_ENTITY_ID], ATTR_OPTIONS) or []
return {} except HomeAssistantError:
options = []
return { return {
"extra_fields": vol.Schema( "extra_fields": vol.Schema(
{ {
vol.Required(CONF_OPTION): vol.In( vol.Required(CONF_OPTION): vol.In(options),
state.attributes.get(ATTR_OPTIONS, [])
),
vol.Optional(CONF_FOR): cv.positive_time_period_dict, vol.Optional(CONF_FOR): cv.positive_time_period_dict,
} }
) )

View File

@ -22,8 +22,9 @@ from homeassistant.const import (
CONF_PLATFORM, CONF_PLATFORM,
CONF_TYPE, CONF_TYPE,
) )
from homeassistant.core import CALLBACK_TYPE, HomeAssistant from homeassistant.core import CALLBACK_TYPE, HomeAssistant, HomeAssistantError
from homeassistant.helpers import config_validation as cv, entity_registry from homeassistant.helpers import config_validation as cv, entity_registry
from homeassistant.helpers.entity import get_capability
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType
from . import DOMAIN from . import DOMAIN
@ -88,15 +89,16 @@ async def async_get_trigger_capabilities(
hass: HomeAssistant, config: ConfigType hass: HomeAssistant, config: ConfigType
) -> dict[str, Any]: ) -> dict[str, Any]:
"""List trigger capabilities.""" """List trigger capabilities."""
state = hass.states.get(config[CONF_ENTITY_ID]) try:
if state is None: options = get_capability(hass, config[CONF_ENTITY_ID], ATTR_OPTIONS) or []
return {} except HomeAssistantError:
options = []
return { return {
"extra_fields": vol.Schema( "extra_fields": vol.Schema(
{ {
vol.Optional(CONF_FROM): vol.In(state.attributes.get(ATTR_OPTIONS, [])), vol.Optional(CONF_FROM): vol.In(options),
vol.Optional(CONF_TO): vol.In(state.attributes.get(ATTR_OPTIONS, [])), vol.Optional(CONF_TO): vol.In(options),
vol.Optional(CONF_FOR): cv.positive_time_period_dict, vol.Optional(CONF_FOR): cv.positive_time_period_dict,
} }
) )

View File

@ -93,7 +93,7 @@ def async_generate_entity_id(
return test_string return test_string
def get_capability(hass: HomeAssistant, entity_id: str, capability: str) -> str | None: def get_capability(hass: HomeAssistant, entity_id: str, capability: str) -> Any | None:
"""Get a capability attribute of an entity. """Get a capability attribute of an entity.
First try the statemachine, then entity registry. First try the statemachine, then entity registry.

View File

@ -94,7 +94,7 @@ async def test_action(hass: HomeAssistant) -> None:
assert select_calls[0].data == {"entity_id": "select.entity", "option": "option1"} assert select_calls[0].data == {"entity_id": "select.entity", "option": "option1"}
async def test_get_trigger_capabilities(hass: HomeAssistant) -> None: async def test_get_action_capabilities(hass: HomeAssistant) -> None:
"""Test we get the expected capabilities from a select action.""" """Test we get the expected capabilities from a select action."""
config = { config = {
"platform": "device", "platform": "device",
@ -106,7 +106,18 @@ async def test_get_trigger_capabilities(hass: HomeAssistant) -> None:
# Test when entity doesn't exists # Test when entity doesn't exists
capabilities = await async_get_action_capabilities(hass, config) capabilities = await async_get_action_capabilities(hass, config)
assert capabilities == {} assert capabilities
assert "extra_fields" in capabilities
assert voluptuous_serialize.convert(
capabilities["extra_fields"], custom_serializer=cv.custom_serializer
) == [
{
"name": "option",
"required": True,
"type": "select",
"options": [],
},
]
# Mock an entity # Mock an entity
hass.states.async_set("select.test", "option1", {"options": ["option1", "option2"]}) hass.states.async_set("select.test", "option1", {"options": ["option1", "option2"]})

View File

@ -159,7 +159,23 @@ async def test_get_condition_capabilities(hass: HomeAssistant) -> None:
# Test when entity doesn't exists # Test when entity doesn't exists
capabilities = await async_get_condition_capabilities(hass, config) capabilities = await async_get_condition_capabilities(hass, config)
assert capabilities == {} assert capabilities
assert "extra_fields" in capabilities
assert voluptuous_serialize.convert(
capabilities["extra_fields"], custom_serializer=cv.custom_serializer
) == [
{
"name": "option",
"required": True,
"type": "select",
"options": [],
},
{
"name": "for",
"optional": True,
"type": "positive_time_period_dict",
},
]
# Mock an entity # Mock an entity
hass.states.async_set("select.test", "option1", {"options": ["option1", "option2"]}) hass.states.async_set("select.test", "option1", {"options": ["option1", "option2"]})

View File

@ -184,7 +184,30 @@ async def test_get_trigger_capabilities(hass: HomeAssistant) -> None:
# Test when entity doesn't exists # Test when entity doesn't exists
capabilities = await async_get_trigger_capabilities(hass, config) capabilities = await async_get_trigger_capabilities(hass, config)
assert capabilities == {} assert capabilities
assert "extra_fields" in capabilities
assert voluptuous_serialize.convert(
capabilities["extra_fields"], custom_serializer=cv.custom_serializer
) == [
{
"name": "from",
"optional": True,
"type": "select",
"options": [],
},
{
"name": "to",
"optional": True,
"type": "select",
"options": [],
},
{
"name": "for",
"optional": True,
"type": "positive_time_period_dict",
"optional": True,
},
]
# Mock an entity # Mock an entity
hass.states.async_set("select.test", "option1", {"options": ["option1", "option2"]}) hass.states.async_set("select.test", "option1", {"options": ["option1", "option2"]})