Improve Google Cast options flow (#50028)

This commit is contained in:
Erik Montnemery 2021-05-07 21:59:51 +02:00 committed by GitHub
parent 3a36a976ee
commit 934d241b70
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 121 additions and 56 deletions

View File

@ -107,53 +107,77 @@ class CastOptionsFlowHandler(config_entries.OptionsFlow):
"""Handle Google Cast options.""" """Handle Google Cast options."""
def __init__(self, config_entry): def __init__(self, config_entry):
"""Initialize MQTT options flow.""" """Initialize Google Cast options flow."""
self.config_entry = config_entry self.config_entry = config_entry
self.broker_config = {} self.updated_config = {}
self.options = dict(config_entry.options)
async def async_step_init(self, user_input=None): async def async_step_init(self, user_input=None):
"""Manage the Cast options.""" """Manage the Google Cast options."""
return await self.async_step_options() return await self.async_step_basic_options()
async def async_step_options(self, user_input=None): async def async_step_basic_options(self, user_input=None):
"""Manage the MQTT options.""" """Manage the Google Cast options."""
errors = {} errors = {}
current_config = self.config_entry.data current_config = self.config_entry.data
if user_input is not None: if user_input is not None:
bad_cec, ignore_cec = _string_to_list(
user_input.get(CONF_IGNORE_CEC, ""), IGNORE_CEC_SCHEMA
)
bad_hosts, known_hosts = _string_to_list( bad_hosts, known_hosts = _string_to_list(
user_input.get(CONF_KNOWN_HOSTS, ""), KNOWN_HOSTS_SCHEMA user_input.get(CONF_KNOWN_HOSTS, ""), KNOWN_HOSTS_SCHEMA
) )
bad_uuid, wanted_uuid = _string_to_list(
user_input.get(CONF_UUID, ""), WANTED_UUID_SCHEMA
)
if not bad_cec and not bad_hosts and not bad_uuid: if not bad_hosts:
updated_config = dict(current_config) self.updated_config = dict(current_config)
updated_config[CONF_IGNORE_CEC] = ignore_cec self.updated_config[CONF_KNOWN_HOSTS] = known_hosts
updated_config[CONF_KNOWN_HOSTS] = known_hosts
updated_config[CONF_UUID] = wanted_uuid if self.show_advanced_options:
return await self.async_step_advanced_options()
self.hass.config_entries.async_update_entry( self.hass.config_entries.async_update_entry(
self.config_entry, data=updated_config self.config_entry, data=self.updated_config
) )
return self.async_create_entry(title="", data=None) return self.async_create_entry(title="", data=None)
fields = {} fields = {}
suggested_value = _list_to_string(current_config.get(CONF_KNOWN_HOSTS)) suggested_value = _list_to_string(current_config.get(CONF_KNOWN_HOSTS))
_add_with_suggestion(fields, CONF_KNOWN_HOSTS, suggested_value) _add_with_suggestion(fields, CONF_KNOWN_HOSTS, suggested_value)
if self.show_advanced_options:
suggested_value = _list_to_string(current_config.get(CONF_UUID))
_add_with_suggestion(fields, CONF_UUID, suggested_value)
suggested_value = _list_to_string(current_config.get(CONF_IGNORE_CEC))
_add_with_suggestion(fields, CONF_IGNORE_CEC, suggested_value)
return self.async_show_form( return self.async_show_form(
step_id="options", step_id="basic_options",
data_schema=vol.Schema(fields), data_schema=vol.Schema(fields),
errors=errors, errors=errors,
last_step=not self.show_advanced_options,
)
async def async_step_advanced_options(self, user_input=None):
"""Manage the Google Cast options."""
errors = {}
if user_input is not None:
bad_cec, ignore_cec = _string_to_list(
user_input.get(CONF_IGNORE_CEC, ""), IGNORE_CEC_SCHEMA
)
bad_uuid, wanted_uuid = _string_to_list(
user_input.get(CONF_UUID, ""), WANTED_UUID_SCHEMA
)
if not bad_cec and not bad_uuid:
self.updated_config[CONF_IGNORE_CEC] = ignore_cec
self.updated_config[CONF_UUID] = wanted_uuid
self.hass.config_entries.async_update_entry(
self.config_entry, data=self.updated_config
)
return self.async_create_entry(title="", data=None)
fields = {}
current_config = self.config_entry.data
suggested_value = _list_to_string(current_config.get(CONF_UUID))
_add_with_suggestion(fields, CONF_UUID, suggested_value)
suggested_value = _list_to_string(current_config.get(CONF_IGNORE_CEC))
_add_with_suggestion(fields, CONF_IGNORE_CEC, suggested_value)
return self.async_show_form(
step_id="advanced_options",
data_schema=vol.Schema(fields),
errors=errors,
last_step=True,
) )

View File

@ -5,10 +5,10 @@
"description": "[%key:common::config_flow::description::confirm_setup%]" "description": "[%key:common::config_flow::description::confirm_setup%]"
}, },
"config": { "config": {
"title": "Google Cast", "title": "Google Cast configuration",
"description": "Please enter the Google Cast configuration.", "description": "Known Hosts - A comma-separated list of hostnames or IP-addresses of cast devices, use if mDNS discovery is not working.",
"data": { "data": {
"known_hosts": "Optional list of known hosts if mDNS discovery is not working." "known_hosts": "Known hosts"
} }
} }
}, },
@ -21,12 +21,19 @@
}, },
"options": { "options": {
"step": { "step": {
"options": { "basic_options": {
"description": "Please enter the Google Cast configuration.", "title": "Google Cast configuration",
"description": "Known Hosts - A comma-separated list of hostnames or IP-addresses of cast devices, use if mDNS discovery is not working.",
"data": { "data": {
"ignore_cec": "Optional list which will be passed to pychromecast.IGNORE_CEC.", "known_hosts": "Known hosts"
"known_hosts": "Optional list of known hosts if mDNS discovery is not working.", }
"uuid": "Optional list of UUIDs. Casts not listed will not be added." },
"advanced_options": {
"title": "Advanced Google Cast configuration",
"description": "Allowed UUIDs - A comma-separated list of UUIDs of Cast devices to add to Home Assistant. Use only if you dont want to add all available cast devices.\nIgnore CEC - A comma-separated list of Chromecasts that should ignore CEC data for determining the active input. This will be will be passed to pychromecast.IGNORE_CEC.",
"data": {
"ignore_cec": "Ignore CEC",
"uuid": "Allowed UUIDs"
} }
} }
}, },

View File

@ -1,7 +1,6 @@
{ {
"config": { "config": {
"abort": { "abort": {
"no_devices_found": "No devices found on the network",
"single_instance_allowed": "Already configured. Only a single configuration possible." "single_instance_allowed": "Already configured. Only a single configuration possible."
}, },
"error": { "error": {
@ -10,10 +9,10 @@
"step": { "step": {
"config": { "config": {
"data": { "data": {
"known_hosts": "Optional list of known hosts if mDNS discovery is not working." "known_hosts": "Known hosts"
}, },
"description": "Please enter the Google Cast configuration.", "description": "### Known Hosts \n A comma-separated list of hostnames or IP-addresses of cast devices, use if mDNS discovery is not working.",
"title": "Google Cast" "title": "Google Cast configuration"
}, },
"confirm": { "confirm": {
"description": "Do you want to start set up?" "description": "Do you want to start set up?"
@ -25,13 +24,20 @@
"invalid_known_hosts": "Known hosts must be a comma separated list of hosts." "invalid_known_hosts": "Known hosts must be a comma separated list of hosts."
}, },
"step": { "step": {
"options": { "advanced_options": {
"data": { "data": {
"ignore_cec": "Optional list which will be passed to pychromecast.IGNORE_CEC.", "ignore_cec": "Ignore CEC",
"known_hosts": "Optional list of known hosts if mDNS discovery is not working.", "uuid": "Allowed UUIDs"
"uuid": "Optional list of UUIDs. Casts not listed will not be added."
}, },
"description": "Please enter the Google Cast configuration." "description": "### Allowed UUIDs\n A comma-separated list of UUIDs of Cast devices to add to Home Assistant. **Use only if you don\u2019t want to add all available cast devices.** \n ### Ignore CEC \n A comma-separated list of Chromecasts that should ignore CEC data for determining the active input. This will be will be passed to pychromecast.IGNORE_CEC. [See the upstream documentation for more information](https://github.com/balloob/pychromecast#ignoring-cec-data).",
"title": "Advanced Google Cast configuration"
},
"basic_options": {
"data": {
"known_hosts": "Known hosts"
},
"description": "### Known Hosts \n A comma-separated list of hostnames or IP-addresses of cast devices, use if mDNS discovery is not working.",
"title": "Google Cast configuration"
} }
} }
} }

View File

@ -153,7 +153,8 @@ def get_suggested(schema, key):
) )
async def test_option_flow(hass, parameter_data): async def test_option_flow(hass, parameter_data):
"""Test config flow options.""" """Test config flow options."""
all_parameters = ["ignore_cec", "known_hosts", "uuid"] basic_parameters = ["known_hosts"]
advanced_parameters = ["ignore_cec", "uuid"]
parameter, initial, suggested, user_input, updated = parameter_data parameter, initial, suggested, user_input, updated = parameter_data
data = { data = {
@ -170,32 +171,61 @@ async def test_option_flow(hass, parameter_data):
# Test ignore_cec and uuid options are hidden if advanced options are disabled # Test ignore_cec and uuid options are hidden if advanced options are disabled
result = await hass.config_entries.options.async_init(config_entry.entry_id) result = await hass.config_entries.options.async_init(config_entry.entry_id)
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["step_id"] == "options" assert result["step_id"] == "basic_options"
data_schema = result["data_schema"].schema data_schema = result["data_schema"].schema
assert set(data_schema) == {"known_hosts"} assert set(data_schema) == {"known_hosts"}
orig_data = dict(config_entry.data) orig_data = dict(config_entry.data)
# Reconfigure ignore_cec, known_hosts, uuid # Reconfigure known_hosts
context = {"source": config_entries.SOURCE_USER, "show_advanced_options": True} context = {"source": config_entries.SOURCE_USER, "show_advanced_options": True}
result = await hass.config_entries.options.async_init( result = await hass.config_entries.options.async_init(
config_entry.entry_id, context=context config_entry.entry_id, context=context
) )
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["step_id"] == "options" assert result["step_id"] == "basic_options"
data_schema = result["data_schema"].schema data_schema = result["data_schema"].schema
for other_param in all_parameters: for other_param in basic_parameters:
if other_param == parameter: if other_param == parameter:
continue continue
assert get_suggested(data_schema, other_param) == "" assert get_suggested(data_schema, other_param) == ""
assert get_suggested(data_schema, parameter) == suggested if parameter in basic_parameters:
assert get_suggested(data_schema, parameter) == suggested
user_input_dict = {}
if parameter in basic_parameters:
user_input_dict[parameter] = user_input
result = await hass.config_entries.options.async_configure( result = await hass.config_entries.options.async_configure(
result["flow_id"], result["flow_id"],
user_input={parameter: user_input}, user_input=user_input_dict,
)
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["step_id"] == "advanced_options"
for other_param in basic_parameters:
if other_param == parameter:
continue
assert config_entry.data[other_param] == []
# No update yet
assert config_entry.data[parameter] == initial
# Reconfigure ignore_cec, uuid
data_schema = result["data_schema"].schema
for other_param in advanced_parameters:
if other_param == parameter:
continue
assert get_suggested(data_schema, other_param) == ""
if parameter in advanced_parameters:
assert get_suggested(data_schema, parameter) == suggested
user_input_dict = {}
if parameter in advanced_parameters:
user_input_dict[parameter] = user_input
result = await hass.config_entries.options.async_configure(
result["flow_id"],
user_input=user_input_dict,
) )
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
assert result["data"] is None assert result["data"] is None
for other_param in all_parameters: for other_param in advanced_parameters:
if other_param == parameter: if other_param == parameter:
continue continue
assert config_entry.data[other_param] == [] assert config_entry.data[other_param] == []
@ -209,12 +239,10 @@ async def test_option_flow(hass, parameter_data):
) )
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
assert result["data"] is None assert result["data"] is None
assert config_entry.data == { expected_data = {**orig_data, "known_hosts": []}
**orig_data, if parameter in advanced_parameters:
"ignore_cec": [], expected_data[parameter] = updated
"known_hosts": [], assert dict(config_entry.data) == expected_data
"uuid": [],
}
async def test_known_hosts(hass, castbrowser_mock, castbrowser_constructor_mock): async def test_known_hosts(hass, castbrowser_mock, castbrowser_constructor_mock):