Don't allow creating or updating input_select with duplicates (#66718)

* Don't allow creating or updating input_select with duplicates

* Simplify error message

* Improve error message
This commit is contained in:
Erik Montnemery 2022-02-17 13:11:49 +01:00 committed by GitHub
parent a9aefb66b5
commit 4236764fd5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 22 additions and 20 deletions

View file

@ -45,15 +45,27 @@ STORAGE_KEY = DOMAIN
STORAGE_VERSION = 1 STORAGE_VERSION = 1
STORAGE_VERSION_MINOR = 2 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 = { CREATE_FIELDS = {
vol.Required(CONF_NAME): vol.All(str, vol.Length(min=1)), 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_INITIAL): cv.string,
vol.Optional(CONF_ICON): cv.icon, vol.Optional(CONF_ICON): cv.icon,
} }
UPDATE_FIELDS = { UPDATE_FIELDS = {
vol.Optional(CONF_NAME): cv.string, 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_INITIAL): cv.string,
vol.Optional(CONF_ICON): cv.icon, vol.Optional(CONF_ICON): cv.icon,
} }

View file

@ -707,16 +707,12 @@ async def test_update_duplicates(hass, hass_ws_client, storage_setup, caplog):
} }
) )
resp = await client.receive_json() resp = await client.receive_json()
assert resp["success"] assert not resp["success"]
assert resp["error"]["code"] == "unknown_error"
assert ( assert resp["error"]["message"] == "Duplicate options are not allowed"
"Input select 'from storage' with options "
"['new option', 'newer option', 'newer option'] "
"had duplicated options, the duplicates have been removed"
) in caplog.text
state = hass.states.get(input_entity_id) 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): 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() resp = await client.receive_json()
assert resp["success"] assert not resp["success"]
assert resp["error"]["code"] == "unknown_error"
assert resp["error"]["message"] == "Duplicate options are not allowed"
assert ( assert not hass.states.get(input_entity_id)
"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
state = hass.states.get(input_entity_id)
assert state.state == "even newer option"
assert state.attributes[ATTR_OPTIONS] == ["new option", "even newer option"]
async def test_setup_no_config(hass, hass_admin_user): async def test_setup_no_config(hass, hass_admin_user):