Fix empty selector validation (#151340)
parent
5e22533fc0
commit
d7e6f84d28
|
@ -50,7 +50,7 @@ def validate_selector(config: Any) -> dict:
|
|||
|
||||
# Selectors can be empty
|
||||
if config[selector_type] is None:
|
||||
return {selector_type: {}}
|
||||
config = {selector_type: {}}
|
||||
|
||||
return {
|
||||
selector_type: cast(dict, selector_class.CONFIG_SCHEMA(config[selector_type]))
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
'required': True,
|
||||
'selector': dict({
|
||||
'object': dict({
|
||||
'multiple': False,
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
|
@ -74,6 +75,8 @@
|
|||
'name': 'Name',
|
||||
'selector': dict({
|
||||
'text': dict({
|
||||
'multiline': False,
|
||||
'multiple': False,
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
|
@ -84,6 +87,8 @@
|
|||
'required': True,
|
||||
'selector': dict({
|
||||
'text': dict({
|
||||
'multiline': False,
|
||||
'multiple': False,
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
|
|
|
@ -146,7 +146,9 @@ async def test_fetch_blueprint_from_github_url(
|
|||
assert imported_blueprint.blueprint.domain == "automation"
|
||||
assert imported_blueprint.blueprint.inputs == {
|
||||
"service_to_call": None,
|
||||
"trigger_event": {"selector": {"text": {}}},
|
||||
"trigger_event": {
|
||||
"selector": {"text": {"multiline": False, "multiple": False}}
|
||||
},
|
||||
"a_number": {"selector": {"number": {"mode": "box", "step": 1.0}}},
|
||||
}
|
||||
assert imported_blueprint.suggested_filename == "balloob/motion_light"
|
||||
|
|
|
@ -58,7 +58,9 @@ async def test_list_blueprints(
|
|||
"domain": "automation",
|
||||
"input": {
|
||||
"service_to_call": None,
|
||||
"trigger_event": {"selector": {"text": {}}},
|
||||
"trigger_event": {
|
||||
"selector": {"text": {"multiline": False, "multiple": False}}
|
||||
},
|
||||
"a_number": {"selector": {"number": {"mode": "box", "step": 1.0}}},
|
||||
},
|
||||
"name": "Call service based on event",
|
||||
|
@ -69,7 +71,9 @@ async def test_list_blueprints(
|
|||
"domain": "automation",
|
||||
"input": {
|
||||
"service_to_call": None,
|
||||
"trigger_event": {"selector": {"text": {}}},
|
||||
"trigger_event": {
|
||||
"selector": {"text": {"multiline": False, "multiple": False}}
|
||||
},
|
||||
"a_number": {"selector": {"number": {"mode": "box", "step": 1.0}}},
|
||||
},
|
||||
"name": "Call service based on event",
|
||||
|
@ -133,7 +137,9 @@ async def test_import_blueprint(
|
|||
"domain": "automation",
|
||||
"input": {
|
||||
"service_to_call": None,
|
||||
"trigger_event": {"selector": {"text": {}}},
|
||||
"trigger_event": {
|
||||
"selector": {"text": {"multiline": False, "multiple": False}}
|
||||
},
|
||||
"a_number": {"selector": {"number": {"mode": "box", "step": 1.0}}},
|
||||
},
|
||||
"name": "Call service based on event",
|
||||
|
@ -219,21 +225,51 @@ async def test_save_blueprint(
|
|||
output_yaml = write_mock.call_args[0][0]
|
||||
assert output_yaml in (
|
||||
# pure python dumper will quote the value after !input
|
||||
"blueprint:\n name: Call service based on event\n domain: automation\n "
|
||||
" input:\n trigger_event:\n selector:\n text: {}\n "
|
||||
" service_to_call:\n a_number:\n selector:\n number:\n "
|
||||
" mode: box\n step: 1.0\n source_url:"
|
||||
" https://github.com/balloob/home-assistant-config/blob/main/blueprints/automation/motion_light.yaml\ntriggers:\n"
|
||||
" trigger: event\n event_type: !input 'trigger_event'\nactions:\n "
|
||||
" service: !input 'service_to_call'\n entity_id: light.kitchen\n"
|
||||
"blueprint:\n"
|
||||
" name: Call service based on event\n"
|
||||
" domain: automation\n"
|
||||
" input:\n"
|
||||
" trigger_event:\n"
|
||||
" selector:\n"
|
||||
" text:\n"
|
||||
" multiline: false\n"
|
||||
" multiple: false\n"
|
||||
" service_to_call:\n"
|
||||
" a_number:\n"
|
||||
" selector:\n"
|
||||
" number:\n"
|
||||
" mode: box\n"
|
||||
" step: 1.0\n"
|
||||
" source_url: https://github.com/balloob/home-assistant-config/blob/main/blueprints/automation/motion_light.yaml\n"
|
||||
"triggers:\n"
|
||||
" trigger: event\n"
|
||||
" event_type: !input 'trigger_event'\n"
|
||||
"actions:\n"
|
||||
" service: !input 'service_to_call'\n"
|
||||
" entity_id: light.kitchen\n",
|
||||
# c dumper will not quote the value after !input
|
||||
"blueprint:\n name: Call service based on event\n domain: automation\n "
|
||||
" input:\n trigger_event:\n selector:\n text: {}\n "
|
||||
" service_to_call:\n a_number:\n selector:\n number:\n "
|
||||
" mode: box\n step: 1.0\n source_url:"
|
||||
" https://github.com/balloob/home-assistant-config/blob/main/blueprints/automation/motion_light.yaml\ntriggers:\n"
|
||||
" trigger: event\n event_type: !input trigger_event\nactions:\n service:"
|
||||
" !input service_to_call\n entity_id: light.kitchen\n"
|
||||
"blueprint:\n"
|
||||
" name: Call service based on event\n"
|
||||
" domain: automation\n"
|
||||
" input:\n"
|
||||
" trigger_event:\n"
|
||||
" selector:\n"
|
||||
" text:\n"
|
||||
" multiline: false\n"
|
||||
" multiple: false\n"
|
||||
" service_to_call:\n"
|
||||
" a_number:\n"
|
||||
" selector:\n"
|
||||
" number:\n"
|
||||
" mode: box\n"
|
||||
" step: 1.0\n"
|
||||
" source_url: https://github.com/balloob/home-assistant-config/blob/main/blueprints/automation/motion_light.yaml\n"
|
||||
"triggers:\n"
|
||||
" trigger: event\n"
|
||||
" event_type: !input trigger_event\n"
|
||||
"actions:\n"
|
||||
" service: !input service_to_call\n"
|
||||
" entity_id: light.kitchen\n",
|
||||
)
|
||||
# Make sure ita parsable and does not raise
|
||||
assert len(parse_yaml(output_yaml)) > 1
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
'required': True,
|
||||
'selector': dict({
|
||||
'object': dict({
|
||||
'multiple': False,
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
|
@ -71,6 +72,8 @@
|
|||
'name': 'Name',
|
||||
'selector': dict({
|
||||
'text': dict({
|
||||
'multiline': False,
|
||||
'multiple': False,
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
|
@ -81,6 +84,8 @@
|
|||
'required': True,
|
||||
'selector': dict({
|
||||
'text': dict({
|
||||
'multiline': False,
|
||||
'multiple': False,
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
|
|
|
@ -1160,6 +1160,7 @@ def test_constant_selector_schema(schema, valid_selections, invalid_selections)
|
|||
@pytest.mark.parametrize(
|
||||
"schema",
|
||||
[
|
||||
None, # Value is mandatory
|
||||
{}, # Value is mandatory
|
||||
{"value": []}, # Value must be str, int or bool
|
||||
{"value": 123, "label": 123}, # Label must be str
|
||||
|
|
|
@ -987,7 +987,16 @@ async def test_async_get_all_descriptions_dot_keys(hass: HomeAssistant) -> None:
|
|||
"test_domain": {
|
||||
"test_service": {
|
||||
"description": "",
|
||||
"fields": {"test": {"selector": {"text": {}}}},
|
||||
"fields": {
|
||||
"test": {
|
||||
"selector": {
|
||||
"text": {
|
||||
"multiline": False,
|
||||
"multiple": False,
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": "",
|
||||
}
|
||||
}
|
||||
|
@ -1079,7 +1088,12 @@ async def test_async_get_all_descriptions_filter(hass: HomeAssistant) -> None:
|
|||
"attribute": {"supported_color_modes": ["color_temp"]},
|
||||
"supported_features": [1],
|
||||
},
|
||||
"selector": {"number": {}},
|
||||
"selector": {
|
||||
"number": {
|
||||
"mode": "box",
|
||||
"step": 1.0,
|
||||
}
|
||||
},
|
||||
},
|
||||
"entity": {
|
||||
"selector": {
|
||||
|
@ -1102,7 +1116,12 @@ async def test_async_get_all_descriptions_filter(hass: HomeAssistant) -> None:
|
|||
"attribute": {"supported_color_modes": ["color_temp"]},
|
||||
"supported_features": [1],
|
||||
},
|
||||
"selector": {"number": {}},
|
||||
"selector": {
|
||||
"number": {
|
||||
"mode": "box",
|
||||
"step": 1.0,
|
||||
}
|
||||
},
|
||||
},
|
||||
"entity": {
|
||||
"selector": {
|
||||
|
|
|
@ -5,6 +5,8 @@ blueprint:
|
|||
trigger_event:
|
||||
selector:
|
||||
text:
|
||||
multiline: false
|
||||
multiple: false
|
||||
service_to_call:
|
||||
a_number:
|
||||
selector:
|
||||
|
|
Loading…
Reference in New Issue