mirror of
https://github.com/home-assistant/core.git
synced 2025-07-14 00:37:13 +00:00
Update vizio host check to handle entries that don't have port (#31463)
* Update vizio host check to handle entries that don't have port * add comment explaining no_port test for future * remove _name_is_same function and support user updating name in config * Update strings.json Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
This commit is contained in:
parent
8af9585f12
commit
1efea50654
@ -53,6 +53,11 @@ def _get_config_flow_schema(input_dict: Dict[str, Any] = None) -> vol.Schema:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _host_is_same(host1: str, host2: str) -> bool:
|
||||||
|
"""Check if host1 and host2 are the same."""
|
||||||
|
return host1.split(":")[0] == host2.split(":")[0]
|
||||||
|
|
||||||
|
|
||||||
class VizioOptionsConfigFlow(config_entries.OptionsFlow):
|
class VizioOptionsConfigFlow(config_entries.OptionsFlow):
|
||||||
"""Handle Transmission client options."""
|
"""Handle Transmission client options."""
|
||||||
|
|
||||||
@ -108,7 +113,7 @@ class VizioConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
|
|
||||||
# Check if new config entry matches any existing config entries
|
# Check if new config entry matches any existing config entries
|
||||||
for entry in self.hass.config_entries.async_entries(DOMAIN):
|
for entry in self.hass.config_entries.async_entries(DOMAIN):
|
||||||
if entry.data[CONF_HOST] == user_input[CONF_HOST]:
|
if _host_is_same(entry.data[CONF_HOST], user_input[CONF_HOST]):
|
||||||
errors[CONF_HOST] = "host_exists"
|
errors[CONF_HOST] = "host_exists"
|
||||||
break
|
break
|
||||||
|
|
||||||
@ -165,24 +170,31 @@ class VizioConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
"""Import a config entry from configuration.yaml."""
|
"""Import a config entry from configuration.yaml."""
|
||||||
# Check if new config entry matches any existing config entries
|
# Check if new config entry matches any existing config entries
|
||||||
for entry in self.hass.config_entries.async_entries(DOMAIN):
|
for entry in self.hass.config_entries.async_entries(DOMAIN):
|
||||||
if entry.data[CONF_HOST] == import_config[CONF_HOST] and entry.data[
|
if _host_is_same(entry.data[CONF_HOST], import_config[CONF_HOST]):
|
||||||
CONF_NAME
|
|
||||||
] == import_config.get(CONF_NAME):
|
|
||||||
updated_options = {}
|
updated_options = {}
|
||||||
|
updated_name = {}
|
||||||
|
|
||||||
|
if entry.data[CONF_NAME] != import_config[CONF_NAME]:
|
||||||
|
updated_name[CONF_NAME] = import_config[CONF_NAME]
|
||||||
|
|
||||||
if entry.data[CONF_VOLUME_STEP] != import_config[CONF_VOLUME_STEP]:
|
if entry.data[CONF_VOLUME_STEP] != import_config[CONF_VOLUME_STEP]:
|
||||||
updated_options[CONF_VOLUME_STEP] = import_config[CONF_VOLUME_STEP]
|
updated_options[CONF_VOLUME_STEP] = import_config[CONF_VOLUME_STEP]
|
||||||
|
|
||||||
if updated_options:
|
if updated_options or updated_name:
|
||||||
new_data = entry.data.copy()
|
new_data = entry.data.copy()
|
||||||
new_data.update(updated_options)
|
|
||||||
new_options = entry.options.copy()
|
new_options = entry.options.copy()
|
||||||
|
|
||||||
|
if updated_name:
|
||||||
|
new_data.update(updated_name)
|
||||||
|
|
||||||
|
if updated_options:
|
||||||
|
new_data.update(updated_options)
|
||||||
new_options.update(updated_options)
|
new_options.update(updated_options)
|
||||||
|
|
||||||
self.hass.config_entries.async_update_entry(
|
self.hass.config_entries.async_update_entry(
|
||||||
entry=entry, data=new_data, options=new_options,
|
entry=entry, data=new_data, options=new_options,
|
||||||
)
|
)
|
||||||
return self.async_abort(reason="updated_options")
|
return self.async_abort(reason="updated_entry")
|
||||||
|
|
||||||
return self.async_abort(reason="already_setup")
|
return self.async_abort(reason="already_setup")
|
||||||
|
|
||||||
@ -199,7 +211,7 @@ class VizioConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
|
|
||||||
# Check if new config entry matches any existing config entries and abort if so
|
# Check if new config entry matches any existing config entries and abort if so
|
||||||
for entry in self.hass.config_entries.async_entries(DOMAIN):
|
for entry in self.hass.config_entries.async_entries(DOMAIN):
|
||||||
if entry.data[CONF_HOST] == discovery_info[CONF_HOST]:
|
if _host_is_same(entry.data[CONF_HOST], discovery_info[CONF_HOST]):
|
||||||
return self.async_abort(reason="already_setup")
|
return self.async_abort(reason="already_setup")
|
||||||
|
|
||||||
# Set default name to discovered device name by stripping zeroconf service
|
# Set default name to discovered device name by stripping zeroconf service
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
"abort": {
|
"abort": {
|
||||||
"already_setup": "This entry has already been setup.",
|
"already_setup": "This entry has already been setup.",
|
||||||
"already_setup_with_diff_host_and_name": "This entry appears to have already been setup with a different host and name based on its serial number. Please remove any old entries from your configuration.yaml and from the Integrations menu before reattempting to add this device.",
|
"already_setup_with_diff_host_and_name": "This entry appears to have already been setup with a different host and name based on its serial number. Please remove any old entries from your configuration.yaml and from the Integrations menu before reattempting to add this device.",
|
||||||
"updated_options": "This entry has already been setup but the options defined in the config do not match the previously imported options values so the config entry has been updated accordingly."
|
"updated_entry": "This entry has already been setup but the name and/or options defined in the config do not match the previously imported config so the config entry has been updated accordingly."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
|
@ -130,6 +130,30 @@ async def test_user_host_already_configured(
|
|||||||
assert result["errors"] == {CONF_HOST: "host_exists"}
|
assert result["errors"] == {CONF_HOST: "host_exists"}
|
||||||
|
|
||||||
|
|
||||||
|
async def test_user_host_already_configured_no_port(
|
||||||
|
hass: HomeAssistantType,
|
||||||
|
vizio_connect: pytest.fixture,
|
||||||
|
vizio_bypass_setup: pytest.fixture,
|
||||||
|
) -> None:
|
||||||
|
"""Test host is already configured during user setup when existing entry has no port."""
|
||||||
|
# Mock entry without port so we can test that the same entry WITH a port will fail
|
||||||
|
no_port_entry = MOCK_SPEAKER_CONFIG.copy()
|
||||||
|
no_port_entry[CONF_HOST] = no_port_entry[CONF_HOST].split(":")[0]
|
||||||
|
entry = MockConfigEntry(
|
||||||
|
domain=DOMAIN, data=no_port_entry, options={CONF_VOLUME_STEP: VOLUME_STEP}
|
||||||
|
)
|
||||||
|
entry.add_to_hass(hass)
|
||||||
|
fail_entry = MOCK_SPEAKER_CONFIG.copy()
|
||||||
|
fail_entry[CONF_NAME] = "newtestname"
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": SOURCE_USER}, data=fail_entry
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
|
assert result["errors"] == {CONF_HOST: "host_exists"}
|
||||||
|
|
||||||
|
|
||||||
async def test_user_name_already_configured(
|
async def test_user_name_already_configured(
|
||||||
hass: HomeAssistantType,
|
hass: HomeAssistantType,
|
||||||
vizio_connect: pytest.fixture,
|
vizio_connect: pytest.fixture,
|
||||||
@ -293,13 +317,43 @@ async def test_import_flow_update_options(
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
||||||
assert result["reason"] == "updated_options"
|
assert result["reason"] == "updated_entry"
|
||||||
assert (
|
assert (
|
||||||
hass.config_entries.async_get_entry(entry_id).options[CONF_VOLUME_STEP]
|
hass.config_entries.async_get_entry(entry_id).options[CONF_VOLUME_STEP]
|
||||||
== VOLUME_STEP + 1
|
== VOLUME_STEP + 1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_import_flow_update_name(
|
||||||
|
hass: HomeAssistantType,
|
||||||
|
vizio_connect: pytest.fixture,
|
||||||
|
vizio_bypass_update: pytest.fixture,
|
||||||
|
) -> None:
|
||||||
|
"""Test import config flow with updated name."""
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN,
|
||||||
|
context={"source": SOURCE_IMPORT},
|
||||||
|
data=vol.Schema(VIZIO_SCHEMA)(MOCK_IMPORT_VALID_TV_CONFIG),
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert result["result"].data[CONF_NAME] == NAME
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||||
|
entry_id = result["result"].entry_id
|
||||||
|
|
||||||
|
updated_config = MOCK_IMPORT_VALID_TV_CONFIG.copy()
|
||||||
|
updated_config[CONF_NAME] = NAME2
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN,
|
||||||
|
context={"source": SOURCE_IMPORT},
|
||||||
|
data=vol.Schema(VIZIO_SCHEMA)(updated_config),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
||||||
|
assert result["reason"] == "updated_entry"
|
||||||
|
assert hass.config_entries.async_get_entry(entry_id).data[CONF_NAME] == NAME2
|
||||||
|
|
||||||
|
|
||||||
async def test_zeroconf_flow(
|
async def test_zeroconf_flow(
|
||||||
hass: HomeAssistantType,
|
hass: HomeAssistantType,
|
||||||
vizio_connect: pytest.fixture,
|
vizio_connect: pytest.fixture,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user