diff --git a/homeassistant/components/input_select/__init__.py b/homeassistant/components/input_select/__init__.py index 288c6d6e588bccd747d6520bfb7725613bb845d8..ae5fc9d251e7407e80e4a0171285d6d8fc74e91f 100644 --- a/homeassistant/components/input_select/__init__.py +++ b/homeassistant/components/input_select/__init__.py @@ -45,15 +45,27 @@ STORAGE_KEY = DOMAIN STORAGE_VERSION = 1 STORAGE_VERSION_MINOR = 2 + +def _unique(options: Any) -> Any: + try: + return vol.Unique()(options) + except vol.Invalid as exc: + raise HomeAssistantError("Duplicate options are not allowed") from exc + + CREATE_FIELDS = { vol.Required(CONF_NAME): vol.All(str, vol.Length(min=1)), - vol.Required(CONF_OPTIONS): vol.All(cv.ensure_list, vol.Length(min=1), [cv.string]), + vol.Required(CONF_OPTIONS): vol.All( + cv.ensure_list, vol.Length(min=1), _unique, [cv.string] + ), vol.Optional(CONF_INITIAL): cv.string, vol.Optional(CONF_ICON): cv.icon, } UPDATE_FIELDS = { vol.Optional(CONF_NAME): cv.string, - vol.Optional(CONF_OPTIONS): vol.All(cv.ensure_list, vol.Length(min=1), [cv.string]), + vol.Optional(CONF_OPTIONS): vol.All( + cv.ensure_list, vol.Length(min=1), _unique, [cv.string] + ), vol.Optional(CONF_INITIAL): cv.string, vol.Optional(CONF_ICON): cv.icon, } diff --git a/tests/components/input_select/test_init.py b/tests/components/input_select/test_init.py index 7a239bac45b003d3ed7127e36c1d695eb4c187e1..d65140dcbf9a94148ebbe8de8ba609e4d7c241eb 100644 --- a/tests/components/input_select/test_init.py +++ b/tests/components/input_select/test_init.py @@ -707,16 +707,12 @@ async def test_update_duplicates(hass, hass_ws_client, storage_setup, caplog): } ) resp = await client.receive_json() - assert resp["success"] - - assert ( - "Input select 'from storage' with options " - "['new option', 'newer option', 'newer option'] " - "had duplicated options, the duplicates have been removed" - ) in caplog.text + assert not resp["success"] + assert resp["error"]["code"] == "unknown_error" + assert resp["error"]["message"] == "Duplicate options are not allowed" state = hass.states.get(input_entity_id) - assert state.attributes[ATTR_OPTIONS] == ["new option", "newer option"] + assert state.attributes[ATTR_OPTIONS] == ["yaml update 1", "yaml update 2"] async def test_ws_create(hass, hass_ws_client, storage_setup): @@ -774,17 +770,11 @@ async def test_ws_create_duplicates(hass, hass_ws_client, storage_setup, caplog) } ) resp = await client.receive_json() - assert resp["success"] - - assert ( - "Input select 'New Input' with options " - "['new option', 'even newer option', 'even newer option'] " - "had duplicated options, the duplicates have been removed" - ) in caplog.text + assert not resp["success"] + assert resp["error"]["code"] == "unknown_error" + assert resp["error"]["message"] == "Duplicate options are not allowed" - state = hass.states.get(input_entity_id) - assert state.state == "even newer option" - assert state.attributes[ATTR_OPTIONS] == ["new option", "even newer option"] + assert not hass.states.get(input_entity_id) async def test_setup_no_config(hass, hass_admin_user):