From 886c2635ad34fa20a088b9adc955145a4c7c880a Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Thu, 16 Mar 2023 14:02:26 +0100 Subject: [PATCH] Add support for constant selector (#89573) * Add support for constant selector * Adapt to frontend PR changes --- homeassistant/helpers/selector.py | 32 ++++++++++++++++++ tests/helpers/test_selector.py | 54 +++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/homeassistant/helpers/selector.py b/homeassistant/helpers/selector.py index fe4709a3021..865ea6374e1 100644 --- a/homeassistant/helpers/selector.py +++ b/homeassistant/helpers/selector.py @@ -358,6 +358,38 @@ class ConfigEntrySelector(Selector[ConfigEntrySelectorConfig]): return config +class ConstantSelectorConfig(TypedDict, total=False): + """Class to represent a constant selector config.""" + + label: str + translation_key: str + value: str | int | bool + + +@SELECTORS.register("constant") +class ConstantSelector(Selector[ConstantSelectorConfig]): + """Constant selector.""" + + selector_type = "constant" + + CONFIG_SCHEMA = vol.Schema( + { + vol.Optional("label"): str, + vol.Optional("translation_key"): cv.string, + vol.Required("value"): vol.Any(str, int, bool), + } + ) + + def __init__(self, config: ConstantSelectorConfig | None = None) -> None: + """Instantiate a selector.""" + super().__init__(config) + + def __call__(self, data: Any) -> Any: + """Validate the passed selection.""" + vol.Schema(self.config["value"])(data) + return self.config["value"] + + class DateSelectorConfig(TypedDict): """Class to represent a date selector config.""" diff --git a/tests/helpers/test_selector.py b/tests/helpers/test_selector.py index a5fa5c7a50d..6f1cb2baef7 100644 --- a/tests/helpers/test_selector.py +++ b/tests/helpers/test_selector.py @@ -836,3 +836,57 @@ def test_file_selector_schema(schema, valid_selections, invalid_selections) -> N """Test file selector.""" _test_selector("file", schema, valid_selections, invalid_selections) + + +@pytest.mark.parametrize( + ("schema", "valid_selections", "invalid_selections"), + ( + ( + {"value": True, "label": "Blah"}, + (True, 1), + (None, False, 0, "abc", "def"), + ), + ( + {"value": False}, + (False, 0), + (None, True, 1, "abc", "def"), + ), + ( + {"value": 0}, + (0, False), + (None, True, 1, "abc", "def"), + ), + ( + {"value": 1}, + (1, True), + (None, False, 0, "abc", "def"), + ), + ( + {"value": 4}, + (4,), + (None, False, True, 0, 1, "abc", "def"), + ), + ( + {"value": "dog"}, + ("dog",), + (None, False, True, 0, 1, "abc", "def"), + ), + ), +) +def test_constant_selector_schema(schema, valid_selections, invalid_selections) -> None: + """Test constant selector.""" + _test_selector("constant", schema, valid_selections, invalid_selections) + + +@pytest.mark.parametrize( + "schema", + ( + {}, # Value is mandatory + {"value": []}, # Value must be str, int or bool + {"value": 123, "label": 123}, # Label must be str + ), +) +def test_constant_selector_schema_error(schema) -> None: + """Test constant selector.""" + with pytest.raises(vol.Invalid): + selector.validate_selector({"constant": schema})