Use voluptuous for input_slider, input_boolean, input_select (#3256)
* Use voluptuous for input slider * floats * _setup_component * Imperative mood * CONFIG_SCHEMA * None returns empty ensure_list * allow_extra * bool * restore ensure_list behaviourpull/3492/head
parent
de51cfbc07
commit
9631179126
|
@ -145,7 +145,7 @@ def prepare_setup_component(hass: core.HomeAssistant, config: dict,
|
||||||
if hasattr(component, 'CONFIG_SCHEMA'):
|
if hasattr(component, 'CONFIG_SCHEMA'):
|
||||||
try:
|
try:
|
||||||
config = component.CONFIG_SCHEMA(config)
|
config = component.CONFIG_SCHEMA(config)
|
||||||
except vol.MultipleInvalid as ex:
|
except vol.Invalid as ex:
|
||||||
log_exception(ex, domain, config)
|
log_exception(ex, domain, config)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -155,8 +155,8 @@ def prepare_setup_component(hass: core.HomeAssistant, config: dict,
|
||||||
# Validate component specific platform schema
|
# Validate component specific platform schema
|
||||||
try:
|
try:
|
||||||
p_validated = component.PLATFORM_SCHEMA(p_config)
|
p_validated = component.PLATFORM_SCHEMA(p_config)
|
||||||
except vol.MultipleInvalid as ex:
|
except vol.Invalid as ex:
|
||||||
log_exception(ex, domain, p_config)
|
log_exception(ex, domain, config)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Not all platform components follow same pattern for platforms
|
# Not all platform components follow same pattern for platforms
|
||||||
|
@ -176,7 +176,7 @@ def prepare_setup_component(hass: core.HomeAssistant, config: dict,
|
||||||
if hasattr(platform, 'PLATFORM_SCHEMA'):
|
if hasattr(platform, 'PLATFORM_SCHEMA'):
|
||||||
try:
|
try:
|
||||||
p_validated = platform.PLATFORM_SCHEMA(p_validated)
|
p_validated = platform.PLATFORM_SCHEMA(p_validated)
|
||||||
except vol.MultipleInvalid as ex:
|
except vol.Invalid as ex:
|
||||||
log_exception(ex, '{}.{}'.format(domain, p_name),
|
log_exception(ex, '{}.{}'.format(domain, p_name),
|
||||||
p_validated)
|
p_validated)
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -9,12 +9,11 @@ import logging
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_ENTITY_ID, SERVICE_TURN_OFF, SERVICE_TURN_ON, SERVICE_TOGGLE,
|
ATTR_ENTITY_ID, CONF_ICON, CONF_NAME, SERVICE_TURN_OFF, SERVICE_TURN_ON,
|
||||||
STATE_ON)
|
SERVICE_TOGGLE, STATE_ON)
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.entity import ToggleEntity
|
from homeassistant.helpers.entity import ToggleEntity
|
||||||
from homeassistant.helpers.entity_component import EntityComponent
|
from homeassistant.helpers.entity_component import EntityComponent
|
||||||
from homeassistant.util import slugify
|
|
||||||
|
|
||||||
DOMAIN = 'input_boolean'
|
DOMAIN = 'input_boolean'
|
||||||
|
|
||||||
|
@ -22,14 +21,19 @@ ENTITY_ID_FORMAT = DOMAIN + '.{}'
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
CONF_NAME = "name"
|
CONF_INITIAL = 'initial'
|
||||||
CONF_INITIAL = "initial"
|
|
||||||
CONF_ICON = "icon"
|
|
||||||
|
|
||||||
SERVICE_SCHEMA = vol.Schema({
|
SERVICE_SCHEMA = vol.Schema({
|
||||||
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = vol.Schema({
|
||||||
|
cv.slug: {
|
||||||
|
vol.Optional(CONF_NAME): cv.string,
|
||||||
|
vol.Optional(CONF_INITIAL): cv.boolean,
|
||||||
|
vol.Optional(CONF_ICON): cv.icon,
|
||||||
|
}}, extra=vol.ALLOW_EXTRA)
|
||||||
|
|
||||||
|
|
||||||
def is_on(hass, entity_id):
|
def is_on(hass, entity_id):
|
||||||
"""Test if input_boolean is True."""
|
"""Test if input_boolean is True."""
|
||||||
|
@ -53,19 +57,11 @@ def toggle(hass, entity_id):
|
||||||
|
|
||||||
def setup(hass, config):
|
def setup(hass, config):
|
||||||
"""Set up input boolean."""
|
"""Set up input boolean."""
|
||||||
if not isinstance(config.get(DOMAIN), dict):
|
|
||||||
_LOGGER.error('Expected %s config to be a dictionary', DOMAIN)
|
|
||||||
return False
|
|
||||||
|
|
||||||
component = EntityComponent(_LOGGER, DOMAIN, hass)
|
component = EntityComponent(_LOGGER, DOMAIN, hass)
|
||||||
|
|
||||||
entities = []
|
entities = []
|
||||||
|
|
||||||
for object_id, cfg in config[DOMAIN].items():
|
for object_id, cfg in config[DOMAIN].items():
|
||||||
if object_id != slugify(object_id):
|
|
||||||
_LOGGER.warning("Found invalid key for boolean input: %s. "
|
|
||||||
"Use %s instead", object_id, slugify(object_id))
|
|
||||||
continue
|
|
||||||
if not cfg:
|
if not cfg:
|
||||||
cfg = {}
|
cfg = {}
|
||||||
|
|
||||||
|
|
|
@ -8,19 +8,17 @@ import logging
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.const import ATTR_ENTITY_ID
|
from homeassistant.const import ATTR_ENTITY_ID, CONF_ICON, CONF_NAME
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
from homeassistant.helpers.entity_component import EntityComponent
|
from homeassistant.helpers.entity_component import EntityComponent
|
||||||
from homeassistant.util import slugify
|
|
||||||
|
|
||||||
DOMAIN = 'input_select'
|
DOMAIN = 'input_select'
|
||||||
ENTITY_ID_FORMAT = DOMAIN + '.{}'
|
ENTITY_ID_FORMAT = DOMAIN + '.{}'
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
CONF_NAME = 'name'
|
|
||||||
CONF_INITIAL = 'initial'
|
CONF_INITIAL = 'initial'
|
||||||
CONF_ICON = 'icon'
|
|
||||||
CONF_OPTIONS = 'options'
|
CONF_OPTIONS = 'options'
|
||||||
|
|
||||||
ATTR_OPTION = 'option'
|
ATTR_OPTION = 'option'
|
||||||
|
@ -34,6 +32,26 @@ SERVICE_SELECT_OPTION_SCHEMA = vol.Schema({
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def _cv_input_select(cfg):
|
||||||
|
"""Config validation helper for input select (Voluptuous)."""
|
||||||
|
options = cfg[CONF_OPTIONS]
|
||||||
|
state = cfg.get(CONF_INITIAL, options[0])
|
||||||
|
if state not in options:
|
||||||
|
raise vol.Invalid('initial state "{}" is not part of the options: {}'
|
||||||
|
.format(state, ','.join(options)))
|
||||||
|
return cfg
|
||||||
|
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = vol.Schema({DOMAIN: {
|
||||||
|
cv.slug: vol.All({
|
||||||
|
vol.Optional(CONF_NAME): cv.string,
|
||||||
|
vol.Required(CONF_OPTIONS): vol.All(cv.ensure_list, vol.Length(min=1),
|
||||||
|
[cv.string]),
|
||||||
|
vol.Optional(CONF_INITIAL): cv.string,
|
||||||
|
vol.Optional(CONF_ICON): cv.icon,
|
||||||
|
}, _cv_input_select)}}, required=True, extra=vol.ALLOW_EXTRA)
|
||||||
|
|
||||||
|
|
||||||
def select_option(hass, entity_id, option):
|
def select_option(hass, entity_id, option):
|
||||||
"""Set input_select to False."""
|
"""Set input_select to False."""
|
||||||
hass.services.call(DOMAIN, SERVICE_SELECT_OPTION, {
|
hass.services.call(DOMAIN, SERVICE_SELECT_OPTION, {
|
||||||
|
@ -44,39 +62,15 @@ def select_option(hass, entity_id, option):
|
||||||
|
|
||||||
def setup(hass, config):
|
def setup(hass, config):
|
||||||
"""Setup input select."""
|
"""Setup input select."""
|
||||||
if not isinstance(config.get(DOMAIN), dict):
|
|
||||||
_LOGGER.error('Expected %s config to be a dictionary', DOMAIN)
|
|
||||||
return False
|
|
||||||
|
|
||||||
component = EntityComponent(_LOGGER, DOMAIN, hass)
|
component = EntityComponent(_LOGGER, DOMAIN, hass)
|
||||||
|
|
||||||
entities = []
|
entities = []
|
||||||
|
|
||||||
for object_id, cfg in config[DOMAIN].items():
|
for object_id, cfg in config[DOMAIN].items():
|
||||||
if object_id != slugify(object_id):
|
|
||||||
_LOGGER.warning("Found invalid key for boolean input: %s. "
|
|
||||||
"Use %s instead", object_id, slugify(object_id))
|
|
||||||
continue
|
|
||||||
if not cfg:
|
|
||||||
_LOGGER.warning("No configuration specified for %s", object_id)
|
|
||||||
continue
|
|
||||||
|
|
||||||
name = cfg.get(CONF_NAME)
|
name = cfg.get(CONF_NAME)
|
||||||
options = cfg.get(CONF_OPTIONS)
|
options = cfg.get(CONF_OPTIONS)
|
||||||
|
state = cfg.get(CONF_INITIAL, options[0])
|
||||||
if not isinstance(options, list) or len(options) == 0:
|
|
||||||
_LOGGER.warning('Key %s should be a list of options', CONF_OPTIONS)
|
|
||||||
continue
|
|
||||||
|
|
||||||
options = [str(val) for val in options]
|
|
||||||
|
|
||||||
state = cfg.get(CONF_INITIAL)
|
|
||||||
|
|
||||||
if state not in options:
|
|
||||||
state = options[0]
|
|
||||||
|
|
||||||
icon = cfg.get(CONF_ICON)
|
icon = cfg.get(CONF_ICON)
|
||||||
|
|
||||||
entities.append(InputSelect(object_id, name, state, options, icon))
|
entities.append(InputSelect(object_id, name, state, options, icon))
|
||||||
|
|
||||||
if not entities:
|
if not entities:
|
||||||
|
|
|
@ -8,21 +8,19 @@ import logging
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.const import ATTR_ENTITY_ID, ATTR_UNIT_OF_MEASUREMENT
|
from homeassistant.const import (
|
||||||
|
ATTR_ENTITY_ID, ATTR_UNIT_OF_MEASUREMENT, CONF_ICON, CONF_NAME)
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
from homeassistant.helpers.entity_component import EntityComponent
|
from homeassistant.helpers.entity_component import EntityComponent
|
||||||
from homeassistant.util import slugify
|
|
||||||
|
|
||||||
DOMAIN = 'input_slider'
|
DOMAIN = 'input_slider'
|
||||||
ENTITY_ID_FORMAT = DOMAIN + '.{}'
|
ENTITY_ID_FORMAT = DOMAIN + '.{}'
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
CONF_NAME = 'name'
|
|
||||||
CONF_INITIAL = 'initial'
|
CONF_INITIAL = 'initial'
|
||||||
CONF_MIN = 'min'
|
CONF_MIN = 'min'
|
||||||
CONF_MAX = 'max'
|
CONF_MAX = 'max'
|
||||||
CONF_ICON = 'icon'
|
|
||||||
CONF_STEP = 'step'
|
CONF_STEP = 'step'
|
||||||
|
|
||||||
ATTR_VALUE = 'value'
|
ATTR_VALUE = 'value'
|
||||||
|
@ -38,6 +36,33 @@ SERVICE_SELECT_VALUE_SCHEMA = vol.Schema({
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def _cv_input_slider(cfg):
|
||||||
|
"""Config validation helper for input slider (Voluptuous)."""
|
||||||
|
minimum = cfg.get(CONF_MIN)
|
||||||
|
maximum = cfg.get(CONF_MAX)
|
||||||
|
if minimum >= maximum:
|
||||||
|
raise vol.Invalid('Maximum ({}) is not greater than minimum ({})'
|
||||||
|
.format(minimum, maximum))
|
||||||
|
state = cfg.get(CONF_INITIAL, minimum)
|
||||||
|
if state < minimum or state > maximum:
|
||||||
|
raise vol.Invalid('Initial value {} not in range {}-{}'
|
||||||
|
.format(state, minimum, maximum))
|
||||||
|
cfg[CONF_INITIAL] = state
|
||||||
|
return cfg
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = vol.Schema({DOMAIN: {
|
||||||
|
cv.slug: vol.All({
|
||||||
|
vol.Optional(CONF_NAME): cv.string,
|
||||||
|
vol.Required(CONF_MIN): vol.Coerce(float),
|
||||||
|
vol.Required(CONF_MAX): vol.Coerce(float),
|
||||||
|
vol.Optional(CONF_INITIAL): vol.Coerce(float),
|
||||||
|
vol.Optional(CONF_STEP, default=1): vol.All(vol.Coerce(float),
|
||||||
|
vol.Range(min=1e-3)),
|
||||||
|
vol.Optional(CONF_ICON): cv.icon,
|
||||||
|
vol.Optional(ATTR_UNIT_OF_MEASUREMENT): cv.string
|
||||||
|
}, _cv_input_slider)}}, required=True, extra=vol.ALLOW_EXTRA)
|
||||||
|
|
||||||
|
|
||||||
def select_value(hass, entity_id, value):
|
def select_value(hass, entity_id, value):
|
||||||
"""Set input_slider to value."""
|
"""Set input_slider to value."""
|
||||||
hass.services.call(DOMAIN, SERVICE_SELECT_VALUE, {
|
hass.services.call(DOMAIN, SERVICE_SELECT_VALUE, {
|
||||||
|
@ -48,36 +73,19 @@ def select_value(hass, entity_id, value):
|
||||||
|
|
||||||
def setup(hass, config):
|
def setup(hass, config):
|
||||||
"""Set up input slider."""
|
"""Set up input slider."""
|
||||||
if not isinstance(config.get(DOMAIN), dict):
|
|
||||||
_LOGGER.error('Expected %s config to be a dictionary', DOMAIN)
|
|
||||||
return False
|
|
||||||
|
|
||||||
component = EntityComponent(_LOGGER, DOMAIN, hass)
|
component = EntityComponent(_LOGGER, DOMAIN, hass)
|
||||||
|
|
||||||
entities = []
|
entities = []
|
||||||
|
|
||||||
for object_id, cfg in config[DOMAIN].items():
|
for object_id, cfg in config[DOMAIN].items():
|
||||||
if object_id != slugify(object_id):
|
|
||||||
_LOGGER.warning("Found invalid key for boolean input: %s. "
|
|
||||||
"Use %s instead", object_id, slugify(object_id))
|
|
||||||
continue
|
|
||||||
if not cfg:
|
|
||||||
_LOGGER.warning("No configuration specified for %s", object_id)
|
|
||||||
continue
|
|
||||||
|
|
||||||
name = cfg.get(CONF_NAME)
|
name = cfg.get(CONF_NAME)
|
||||||
minimum = cfg.get(CONF_MIN)
|
minimum = cfg.get(CONF_MIN)
|
||||||
maximum = cfg.get(CONF_MAX)
|
maximum = cfg.get(CONF_MAX)
|
||||||
state = cfg.get(CONF_INITIAL, minimum)
|
state = cfg.get(CONF_INITIAL, minimum)
|
||||||
step = cfg.get(CONF_STEP, 1)
|
step = cfg.get(CONF_STEP)
|
||||||
icon = cfg.get(CONF_ICON)
|
icon = cfg.get(CONF_ICON)
|
||||||
unit = cfg.get(ATTR_UNIT_OF_MEASUREMENT)
|
unit = cfg.get(ATTR_UNIT_OF_MEASUREMENT)
|
||||||
|
|
||||||
if state < minimum:
|
|
||||||
state = minimum
|
|
||||||
if state > maximum:
|
|
||||||
state = maximum
|
|
||||||
|
|
||||||
entities.append(InputSlider(object_id, name, state, minimum, maximum,
|
entities.append(InputSlider(object_id, name, state, minimum, maximum,
|
||||||
step, icon, unit))
|
step, icon, unit))
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
"""Helper methods for components within Home Assistant."""
|
"""Helper methods for components within Home Assistant."""
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from typing import Any, Iterable, Tuple, List, Dict
|
from typing import Any, Iterable, Tuple, Sequence, Dict
|
||||||
|
|
||||||
from homeassistant.const import CONF_PLATFORM
|
from homeassistant.const import CONF_PLATFORM
|
||||||
|
|
||||||
# Typing Imports and TypeAlias
|
# Typing Imports and TypeAlias
|
||||||
# pylint: disable=using-constant-test,unused-import
|
# pylint: disable=using-constant-test,unused-import,wrong-import-order
|
||||||
if False:
|
if False:
|
||||||
from logging import Logger # NOQA
|
from logging import Logger # NOQA
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ def config_per_platform(config: ConfigType,
|
||||||
yield platform, item
|
yield platform, item
|
||||||
|
|
||||||
|
|
||||||
def extract_domain_configs(config: ConfigType, domain: str) -> List[str]:
|
def extract_domain_configs(config: ConfigType, domain: str) -> Sequence[str]:
|
||||||
"""Extract keys from config for given domain name."""
|
"""Extract keys from config for given domain name."""
|
||||||
pattern = re.compile(r'^{}(| .+)$'.format(domain))
|
pattern = re.compile(r'^{}(| .+)$'.format(domain))
|
||||||
return [key for key in config.keys() if pattern.match(key)]
|
return [key for key in config.keys() if pattern.match(key)]
|
||||||
|
|
|
@ -4,7 +4,7 @@ from datetime import timedelta
|
||||||
import os
|
import os
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
from typing import Any, Union, TypeVar, Callable, Sequence, List, Dict
|
from typing import Any, Union, TypeVar, Callable, Sequence, Dict
|
||||||
|
|
||||||
import jinja2
|
import jinja2
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
@ -80,7 +80,7 @@ def isfile(value: Any) -> str:
|
||||||
return file_in
|
return file_in
|
||||||
|
|
||||||
|
|
||||||
def ensure_list(value: Union[T, Sequence[T]]) -> List[T]:
|
def ensure_list(value: Union[T, Sequence[T]]) -> Sequence[T]:
|
||||||
"""Wrap value in list if it is not one."""
|
"""Wrap value in list if it is not one."""
|
||||||
return value if isinstance(value, list) else [value]
|
return value if isinstance(value, list) else [value]
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ def entity_id(value: Any) -> str:
|
||||||
raise vol.Invalid('Entity ID {} is an invalid entity id'.format(value))
|
raise vol.Invalid('Entity ID {} is an invalid entity id'.format(value))
|
||||||
|
|
||||||
|
|
||||||
def entity_ids(value: Union[str, Sequence]) -> List[str]:
|
def entity_ids(value: Union[str, Sequence]) -> Sequence[str]:
|
||||||
"""Validate Entity IDs."""
|
"""Validate Entity IDs."""
|
||||||
if value is None:
|
if value is None:
|
||||||
raise vol.Invalid('Entity IDs can not be None')
|
raise vol.Invalid('Entity IDs can not be None')
|
||||||
|
|
|
@ -1,12 +1,17 @@
|
||||||
"""The tests for the input_boolean component."""
|
"""The tests for the input_boolean component."""
|
||||||
# pylint: disable=too-many-public-methods,protected-access
|
# pylint: disable=too-many-public-methods,protected-access
|
||||||
import unittest
|
import unittest
|
||||||
|
import logging
|
||||||
|
|
||||||
from homeassistant.components import input_boolean
|
from tests.common import get_test_home_assistant
|
||||||
|
|
||||||
|
from homeassistant.bootstrap import setup_component
|
||||||
|
from homeassistant.components.input_boolean import (
|
||||||
|
DOMAIN, is_on, toggle, turn_off, turn_on)
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
STATE_ON, STATE_OFF, ATTR_ICON, ATTR_FRIENDLY_NAME)
|
STATE_ON, STATE_OFF, ATTR_ICON, ATTR_FRIENDLY_NAME)
|
||||||
|
|
||||||
from tests.common import get_test_home_assistant
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class TestInputBoolean(unittest.TestCase):
|
class TestInputBoolean(unittest.TestCase):
|
||||||
|
@ -22,68 +27,63 @@ class TestInputBoolean(unittest.TestCase):
|
||||||
|
|
||||||
def test_config(self):
|
def test_config(self):
|
||||||
"""Test config."""
|
"""Test config."""
|
||||||
self.assertFalse(input_boolean.setup(self.hass, {
|
invalid_configs = [
|
||||||
'input_boolean': None
|
None,
|
||||||
}))
|
1,
|
||||||
|
{},
|
||||||
|
{'name with space': None},
|
||||||
|
]
|
||||||
|
|
||||||
self.assertFalse(input_boolean.setup(self.hass, {
|
for cfg in invalid_configs:
|
||||||
'input_boolean': {
|
self.assertFalse(
|
||||||
}
|
setup_component(self.hass, DOMAIN, {DOMAIN: cfg}))
|
||||||
}))
|
|
||||||
|
|
||||||
self.assertFalse(input_boolean.setup(self.hass, {
|
|
||||||
'input_boolean': {
|
|
||||||
'name with space': None
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
|
|
||||||
def test_methods(self):
|
def test_methods(self):
|
||||||
"""Test is_on, turn_on, turn_off methods."""
|
"""Test is_on, turn_on, turn_off methods."""
|
||||||
self.assertTrue(input_boolean.setup(self.hass, {
|
self.assertTrue(setup_component(self.hass, DOMAIN, {DOMAIN: {
|
||||||
'input_boolean': {
|
'test_1': None,
|
||||||
'test_1': None,
|
}}))
|
||||||
}
|
|
||||||
}))
|
|
||||||
entity_id = 'input_boolean.test_1'
|
entity_id = 'input_boolean.test_1'
|
||||||
|
|
||||||
self.assertFalse(
|
self.assertFalse(
|
||||||
input_boolean.is_on(self.hass, entity_id))
|
is_on(self.hass, entity_id))
|
||||||
|
|
||||||
input_boolean.turn_on(self.hass, entity_id)
|
turn_on(self.hass, entity_id)
|
||||||
|
|
||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
|
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
input_boolean.is_on(self.hass, entity_id))
|
is_on(self.hass, entity_id))
|
||||||
|
|
||||||
input_boolean.turn_off(self.hass, entity_id)
|
turn_off(self.hass, entity_id)
|
||||||
|
|
||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
|
|
||||||
self.assertFalse(
|
self.assertFalse(
|
||||||
input_boolean.is_on(self.hass, entity_id))
|
is_on(self.hass, entity_id))
|
||||||
|
|
||||||
input_boolean.toggle(self.hass, entity_id)
|
toggle(self.hass, entity_id)
|
||||||
|
|
||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
|
|
||||||
self.assertTrue(
|
self.assertTrue(is_on(self.hass, entity_id))
|
||||||
input_boolean.is_on(self.hass, entity_id))
|
|
||||||
|
|
||||||
def test_config_options(self):
|
def test_config_options(self):
|
||||||
"""Test configuration options."""
|
"""Test configuration options."""
|
||||||
count_start = len(self.hass.states.entity_ids())
|
count_start = len(self.hass.states.entity_ids())
|
||||||
|
|
||||||
self.assertTrue(input_boolean.setup(self.hass, {
|
_LOGGER.debug('ENTITIES @ start: %s', self.hass.states.entity_ids())
|
||||||
'input_boolean': {
|
|
||||||
'test_1': None,
|
self.assertTrue(setup_component(self.hass, DOMAIN, {DOMAIN: {
|
||||||
'test_2': {
|
'test_1': None,
|
||||||
'name': 'Hello World',
|
'test_2': {
|
||||||
'icon': 'work',
|
'name': 'Hello World',
|
||||||
'initial': True,
|
'icon': 'mdi:work',
|
||||||
},
|
'initial': True,
|
||||||
},
|
},
|
||||||
}))
|
}}))
|
||||||
|
|
||||||
|
_LOGGER.debug('ENTITIES: %s', self.hass.states.entity_ids())
|
||||||
|
|
||||||
self.assertEqual(count_start + 2, len(self.hass.states.entity_ids()))
|
self.assertEqual(count_start + 2, len(self.hass.states.entity_ids()))
|
||||||
|
|
||||||
|
@ -100,4 +100,4 @@ class TestInputBoolean(unittest.TestCase):
|
||||||
self.assertEqual(STATE_ON, state_2.state)
|
self.assertEqual(STATE_ON, state_2.state)
|
||||||
self.assertEqual('Hello World',
|
self.assertEqual('Hello World',
|
||||||
state_2.attributes.get(ATTR_FRIENDLY_NAME))
|
state_2.attributes.get(ATTR_FRIENDLY_NAME))
|
||||||
self.assertEqual('work', state_2.attributes.get(ATTR_ICON))
|
self.assertEqual('mdi:work', state_2.attributes.get(ATTR_ICON))
|
||||||
|
|
|
@ -2,12 +2,14 @@
|
||||||
# pylint: disable=too-many-public-methods,protected-access
|
# pylint: disable=too-many-public-methods,protected-access
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from homeassistant.components import input_select
|
from tests.common import get_test_home_assistant
|
||||||
|
|
||||||
|
from homeassistant.bootstrap import setup_component
|
||||||
|
from homeassistant.components.input_select import (
|
||||||
|
ATTR_OPTIONS, DOMAIN, select_option)
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_ICON, ATTR_FRIENDLY_NAME)
|
ATTR_ICON, ATTR_FRIENDLY_NAME)
|
||||||
|
|
||||||
from tests.common import get_test_home_assistant
|
|
||||||
|
|
||||||
|
|
||||||
class TestInputSelect(unittest.TestCase):
|
class TestInputSelect(unittest.TestCase):
|
||||||
"""Test the input select component."""
|
"""Test the input select component."""
|
||||||
|
@ -22,59 +24,44 @@ class TestInputSelect(unittest.TestCase):
|
||||||
|
|
||||||
def test_config(self):
|
def test_config(self):
|
||||||
"""Test config."""
|
"""Test config."""
|
||||||
self.assertFalse(input_select.setup(self.hass, {
|
invalid_configs = [
|
||||||
'input_select': None
|
None,
|
||||||
}))
|
{},
|
||||||
|
{'name with space': None},
|
||||||
|
# {'bad_options': {'options': None}},
|
||||||
|
{'bad_initial': {
|
||||||
|
'options': [1, 2],
|
||||||
|
'initial': 3,
|
||||||
|
}},
|
||||||
|
]
|
||||||
|
|
||||||
self.assertFalse(input_select.setup(self.hass, {
|
for cfg in invalid_configs:
|
||||||
'input_select': {
|
self.assertFalse(
|
||||||
}
|
setup_component(self.hass, DOMAIN, {DOMAIN: cfg}))
|
||||||
}))
|
|
||||||
|
|
||||||
self.assertFalse(input_select.setup(self.hass, {
|
|
||||||
'input_select': {
|
|
||||||
'name with space': None
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
|
|
||||||
self.assertFalse(input_select.setup(self.hass, {
|
|
||||||
'input_select': {
|
|
||||||
'hello': {
|
|
||||||
'options': None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
|
|
||||||
self.assertFalse(input_select.setup(self.hass, {
|
|
||||||
'input_select': {
|
|
||||||
'hello': None
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
|
|
||||||
def test_select_option(self):
|
def test_select_option(self):
|
||||||
"""Test select_option methods."""
|
"""Test select_option methods."""
|
||||||
self.assertTrue(input_select.setup(self.hass, {
|
self.assertTrue(
|
||||||
'input_select': {
|
setup_component(self.hass, DOMAIN, {DOMAIN: {
|
||||||
'test_1': {
|
'test_1': {
|
||||||
'options': [
|
'options': [
|
||||||
'some option',
|
'some option',
|
||||||
'another option',
|
'another option',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
}
|
}}))
|
||||||
}))
|
|
||||||
entity_id = 'input_select.test_1'
|
entity_id = 'input_select.test_1'
|
||||||
|
|
||||||
state = self.hass.states.get(entity_id)
|
state = self.hass.states.get(entity_id)
|
||||||
self.assertEqual('some option', state.state)
|
self.assertEqual('some option', state.state)
|
||||||
|
|
||||||
input_select.select_option(self.hass, entity_id, 'another option')
|
select_option(self.hass, entity_id, 'another option')
|
||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
|
|
||||||
state = self.hass.states.get(entity_id)
|
state = self.hass.states.get(entity_id)
|
||||||
self.assertEqual('another option', state.state)
|
self.assertEqual('another option', state.state)
|
||||||
|
|
||||||
input_select.select_option(self.hass, entity_id, 'non existing option')
|
select_option(self.hass, entity_id, 'non existing option')
|
||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
|
|
||||||
state = self.hass.states.get(entity_id)
|
state = self.hass.states.get(entity_id)
|
||||||
|
@ -90,8 +77,8 @@ class TestInputSelect(unittest.TestCase):
|
||||||
'Best Option',
|
'Best Option',
|
||||||
]
|
]
|
||||||
|
|
||||||
self.assertTrue(input_select.setup(self.hass, {
|
self.assertTrue(setup_component(self.hass, DOMAIN, {
|
||||||
'input_select': {
|
DOMAIN: {
|
||||||
'test_1': {
|
'test_1': {
|
||||||
'options': [
|
'options': [
|
||||||
1,
|
1,
|
||||||
|
@ -100,11 +87,11 @@ class TestInputSelect(unittest.TestCase):
|
||||||
},
|
},
|
||||||
'test_2': {
|
'test_2': {
|
||||||
'name': 'Hello World',
|
'name': 'Hello World',
|
||||||
'icon': 'work',
|
'icon': 'mdi:work',
|
||||||
'options': test_2_options,
|
'options': test_2_options,
|
||||||
'initial': 'Better Option',
|
'initial': 'Better Option',
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
self.assertEqual(count_start + 2, len(self.hass.states.entity_ids()))
|
self.assertEqual(count_start + 2, len(self.hass.states.entity_ids()))
|
||||||
|
@ -117,13 +104,12 @@ class TestInputSelect(unittest.TestCase):
|
||||||
|
|
||||||
self.assertEqual('1', state_1.state)
|
self.assertEqual('1', state_1.state)
|
||||||
self.assertEqual(['1', '2'],
|
self.assertEqual(['1', '2'],
|
||||||
state_1.attributes.get(input_select.ATTR_OPTIONS))
|
state_1.attributes.get(ATTR_OPTIONS))
|
||||||
self.assertNotIn(ATTR_ICON, state_1.attributes)
|
self.assertNotIn(ATTR_ICON, state_1.attributes)
|
||||||
self.assertNotIn(ATTR_FRIENDLY_NAME, state_1.attributes)
|
|
||||||
|
|
||||||
self.assertEqual('Better Option', state_2.state)
|
self.assertEqual('Better Option', state_2.state)
|
||||||
self.assertEqual(test_2_options,
|
self.assertEqual(test_2_options,
|
||||||
state_2.attributes.get(input_select.ATTR_OPTIONS))
|
state_2.attributes.get(ATTR_OPTIONS))
|
||||||
self.assertEqual('Hello World',
|
self.assertEqual('Hello World',
|
||||||
state_2.attributes.get(ATTR_FRIENDLY_NAME))
|
state_2.attributes.get(ATTR_FRIENDLY_NAME))
|
||||||
self.assertEqual('work', state_2.attributes.get(ATTR_ICON))
|
self.assertEqual('mdi:work', state_2.attributes.get(ATTR_ICON))
|
||||||
|
|
|
@ -2,10 +2,11 @@
|
||||||
# pylint: disable=too-many-public-methods,protected-access
|
# pylint: disable=too-many-public-methods,protected-access
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from homeassistant.components import input_slider
|
|
||||||
|
|
||||||
from tests.common import get_test_home_assistant
|
from tests.common import get_test_home_assistant
|
||||||
|
|
||||||
|
from homeassistant.bootstrap import setup_component
|
||||||
|
from homeassistant.components.input_slider import (DOMAIN, select_value)
|
||||||
|
|
||||||
|
|
||||||
class TestInputSlider(unittest.TestCase):
|
class TestInputSlider(unittest.TestCase):
|
||||||
"""Test the input slider component."""
|
"""Test the input slider component."""
|
||||||
|
@ -20,50 +21,46 @@ class TestInputSlider(unittest.TestCase):
|
||||||
|
|
||||||
def test_config(self):
|
def test_config(self):
|
||||||
"""Test config."""
|
"""Test config."""
|
||||||
self.assertFalse(input_slider.setup(self.hass, {
|
invalid_configs = [
|
||||||
'input_slider': None
|
None,
|
||||||
}))
|
{},
|
||||||
|
{'name with space': None},
|
||||||
self.assertFalse(input_slider.setup(self.hass, {
|
{'test_1': {
|
||||||
'input_slider': {
|
'min': 50,
|
||||||
}
|
'max': 50,
|
||||||
}))
|
}},
|
||||||
|
]
|
||||||
self.assertFalse(input_slider.setup(self.hass, {
|
for cfg in invalid_configs:
|
||||||
'input_slider': {
|
self.assertFalse(
|
||||||
'name with space': None
|
setup_component(self.hass, DOMAIN, {DOMAIN: cfg}))
|
||||||
}
|
|
||||||
}))
|
|
||||||
|
|
||||||
def test_select_value(self):
|
def test_select_value(self):
|
||||||
"""Test select_value method."""
|
"""Test select_value method."""
|
||||||
self.assertTrue(input_slider.setup(self.hass, {
|
self.assertTrue(setup_component(self.hass, DOMAIN, {DOMAIN: {
|
||||||
'input_slider': {
|
'test_1': {
|
||||||
'test_1': {
|
'initial': 50,
|
||||||
'initial': 50,
|
'min': 0,
|
||||||
'min': 0,
|
'max': 100,
|
||||||
'max': 100,
|
},
|
||||||
},
|
}}))
|
||||||
}
|
|
||||||
}))
|
|
||||||
entity_id = 'input_slider.test_1'
|
entity_id = 'input_slider.test_1'
|
||||||
|
|
||||||
state = self.hass.states.get(entity_id)
|
state = self.hass.states.get(entity_id)
|
||||||
self.assertEqual(50, float(state.state))
|
self.assertEqual(50, float(state.state))
|
||||||
|
|
||||||
input_slider.select_value(self.hass, entity_id, '30.4')
|
select_value(self.hass, entity_id, '30.4')
|
||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
|
|
||||||
state = self.hass.states.get(entity_id)
|
state = self.hass.states.get(entity_id)
|
||||||
self.assertEqual(30.4, float(state.state))
|
self.assertEqual(30.4, float(state.state))
|
||||||
|
|
||||||
input_slider.select_value(self.hass, entity_id, '70')
|
select_value(self.hass, entity_id, '70')
|
||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
|
|
||||||
state = self.hass.states.get(entity_id)
|
state = self.hass.states.get(entity_id)
|
||||||
self.assertEqual(70, float(state.state))
|
self.assertEqual(70, float(state.state))
|
||||||
|
|
||||||
input_slider.select_value(self.hass, entity_id, '110')
|
select_value(self.hass, entity_id, '110')
|
||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
|
|
||||||
state = self.hass.states.get(entity_id)
|
state = self.hass.states.get(entity_id)
|
||||||
|
|
Loading…
Reference in New Issue