core/tests/helpers/test_selector.py

322 lines
9.6 KiB
Python

"""Test selectors."""
import pytest
import voluptuous as vol
from homeassistant.helpers import config_validation as cv, selector
from homeassistant.util import dt as dt_util
FAKE_UUID = "a266a680b608c32770e6c45bfe6b8411"
@pytest.mark.parametrize(
"schema",
(
{"device": None},
{"entity": None},
),
)
def test_valid_base_schema(schema):
"""Test base schema validation."""
selector.validate_selector(schema)
@pytest.mark.parametrize(
"schema",
(
None,
"not_a_dict",
{},
{"non_existing": {}},
# Two keys
{"device": {}, "entity": {}},
),
)
def test_invalid_base_schema(schema):
"""Test base schema validation."""
with pytest.raises(vol.Invalid):
selector.validate_selector(schema)
def test_validate_selector():
"""Test return is the same as input."""
schema = {"device": {"manufacturer": "mock-manuf", "model": "mock-model"}}
assert schema == selector.validate_selector(schema)
def _test_selector(
selector_type, schema, valid_selections, invalid_selections, converter=None
):
"""Help test a selector."""
def default_converter(x):
return x
if converter is None:
converter = default_converter
# Validate selector configuration
selector.validate_selector({selector_type: schema})
# Use selector in schema and validate
vol_schema = vol.Schema({"selection": selector.selector({selector_type: schema})})
for selection in valid_selections:
assert vol_schema({"selection": selection}) == {
"selection": converter(selection)
}
for selection in invalid_selections:
with pytest.raises(vol.Invalid):
vol_schema({"selection": selection})
# Serialize selector
selector_instance = selector.selector({selector_type: schema})
assert cv.custom_serializer(selector_instance) == {
"selector": {selector_type: selector_instance.config}
}
@pytest.mark.parametrize(
"schema,valid_selections,invalid_selections",
(
(None, ("abc123",), (None,)),
({}, ("abc123",), (None,)),
({"integration": "zha"}, ("abc123",), (None,)),
({"manufacturer": "mock-manuf"}, ("abc123",), (None,)),
({"model": "mock-model"}, ("abc123",), (None,)),
({"manufacturer": "mock-manuf", "model": "mock-model"}, ("abc123",), (None,)),
(
{"integration": "zha", "manufacturer": "mock-manuf", "model": "mock-model"},
("abc123",),
(None,),
),
({"entity": {"device_class": "motion"}}, ("abc123",), (None,)),
(
{
"integration": "zha",
"manufacturer": "mock-manuf",
"model": "mock-model",
"entity": {"domain": "binary_sensor", "device_class": "motion"},
},
("abc123",),
(None,),
),
),
)
def test_device_selector_schema(schema, valid_selections, invalid_selections):
"""Test device selector."""
_test_selector("device", schema, valid_selections, invalid_selections)
@pytest.mark.parametrize(
"schema,valid_selections,invalid_selections",
(
({}, ("sensor.abc123", FAKE_UUID), (None, "abc123")),
({"integration": "zha"}, ("sensor.abc123", FAKE_UUID), (None, "abc123")),
({"domain": "light"}, ("light.abc123", FAKE_UUID), (None, "sensor.abc123")),
({"device_class": "motion"}, ("sensor.abc123", FAKE_UUID), (None, "abc123")),
(
{"integration": "zha", "domain": "light"},
("light.abc123", FAKE_UUID),
(None, "sensor.abc123"),
),
(
{"integration": "zha", "domain": "binary_sensor", "device_class": "motion"},
("binary_sensor.abc123", FAKE_UUID),
(None, "sensor.abc123"),
),
),
)
def test_entity_selector_schema(schema, valid_selections, invalid_selections):
"""Test entity selector."""
_test_selector("entity", schema, valid_selections, invalid_selections)
@pytest.mark.parametrize(
"schema,valid_selections,invalid_selections",
(
({}, ("abc123",), (None,)),
({"entity": {}}, ("abc123",), (None,)),
({"entity": {"domain": "light"}}, ("abc123",), (None,)),
(
{"entity": {"domain": "binary_sensor", "device_class": "motion"}},
("abc123",),
(None,),
),
(
{
"entity": {
"domain": "binary_sensor",
"device_class": "motion",
"integration": "demo",
}
},
("abc123",),
(None,),
),
(
{"device": {"integration": "demo", "model": "mock-model"}},
("abc123",),
(None,),
),
(
{
"entity": {"domain": "binary_sensor", "device_class": "motion"},
"device": {"integration": "demo", "model": "mock-model"},
},
("abc123",),
(None,),
),
),
)
def test_area_selector_schema(schema, valid_selections, invalid_selections):
"""Test area selector."""
_test_selector("area", schema, valid_selections, invalid_selections)
@pytest.mark.parametrize(
"schema,valid_selections,invalid_selections",
(
(
{"min": 10, "max": 50},
(
10,
50,
),
(9, 51),
),
({"min": -100, "max": 100, "step": 5}, (), ()),
({"min": -20, "max": -10, "mode": "box"}, (), ()),
(
{"min": 0, "max": 100, "unit_of_measurement": "seconds", "mode": "slider"},
(),
(),
),
({"min": 10, "max": 1000, "mode": "slider", "step": 0.5}, (), ()),
),
)
def test_number_selector_schema(schema, valid_selections, invalid_selections):
"""Test number selector."""
_test_selector("number", schema, valid_selections, invalid_selections)
@pytest.mark.parametrize(
"schema,valid_selections,invalid_selections",
(({}, ("abc123",), (None,)),),
)
def test_addon_selector_schema(schema, valid_selections, invalid_selections):
"""Test add-on selector."""
_test_selector("addon", schema, valid_selections, invalid_selections)
@pytest.mark.parametrize(
"schema,valid_selections,invalid_selections",
(({}, (1, "one", None), ()),), # Everything can be coarced to bool
)
def test_boolean_selector_schema(schema, valid_selections, invalid_selections):
"""Test boolean selector."""
_test_selector("boolean", schema, valid_selections, invalid_selections, bool)
@pytest.mark.parametrize(
"schema,valid_selections,invalid_selections",
(({}, ("00:00:00",), ("blah", None)),),
)
def test_time_selector_schema(schema, valid_selections, invalid_selections):
"""Test time selector."""
_test_selector(
"time", schema, valid_selections, invalid_selections, dt_util.parse_time
)
@pytest.mark.parametrize(
"schema,valid_selections,invalid_selections",
(
({}, ({"entity_id": ["sensor.abc123"]},), ("abc123", None)),
({"entity": {}}, (), ()),
({"entity": {"domain": "light"}}, (), ()),
({"entity": {"domain": "binary_sensor", "device_class": "motion"}}, (), ()),
(
{
"entity": {
"domain": "binary_sensor",
"device_class": "motion",
"integration": "demo",
}
},
(),
(),
),
({"device": {"integration": "demo", "model": "mock-model"}}, (), ()),
(
{
"entity": {"domain": "binary_sensor", "device_class": "motion"},
"device": {"integration": "demo", "model": "mock-model"},
},
(),
(),
),
),
)
def test_target_selector_schema(schema, valid_selections, invalid_selections):
"""Test target selector."""
_test_selector("target", schema, valid_selections, invalid_selections)
@pytest.mark.parametrize(
"schema,valid_selections,invalid_selections",
(({}, ("abc123",), ()),),
)
def test_action_selector_schema(schema, valid_selections, invalid_selections):
"""Test action sequence selector."""
_test_selector("action", schema, valid_selections, invalid_selections)
@pytest.mark.parametrize(
"schema,valid_selections,invalid_selections",
(({}, ("abc123",), ()),),
)
def test_object_selector_schema(schema, valid_selections, invalid_selections):
"""Test object selector."""
_test_selector("object", schema, valid_selections, invalid_selections)
@pytest.mark.parametrize(
"schema,valid_selections,invalid_selections",
(
({}, ("abc123",), (None,)),
({"multiline": True}, (), ()),
({"multiline": False}, (), ()),
),
)
def test_text_selector_schema(schema, valid_selections, invalid_selections):
"""Test text selector."""
_test_selector("text", schema, valid_selections, invalid_selections)
@pytest.mark.parametrize(
"schema,valid_selections,invalid_selections",
(
(
{"options": ["red", "green", "blue"]},
("red", "green", "blue"),
("cat", 0, None),
),
),
)
def test_select_selector_schema(schema, valid_selections, invalid_selections):
"""Test select selector."""
_test_selector("select", schema, valid_selections, invalid_selections)
@pytest.mark.parametrize(
"schema",
(
{},
{"options": {"hello": "World"}},
{"options": []},
),
)
def test_select_selector_schema_error(schema):
"""Test select selector."""
with pytest.raises(vol.Invalid):
selector.validate_selector({"select": schema})