Limit the scope of try except blocks in Android TV Remote (#151746)

This commit is contained in:
tronikos
2025-09-05 03:28:46 -07:00
committed by GitHub
parent caa0e357ee
commit 71b8da6497
2 changed files with 81 additions and 20 deletions

View File

@@ -66,9 +66,14 @@ class AndroidTVRemoteConfigFlow(ConfigFlow, domain=DOMAIN):
if user_input is not None:
self.host = user_input[CONF_HOST]
api = create_api(self.hass, self.host, enable_ime=False)
await api.async_generate_cert_if_missing()
try:
await api.async_generate_cert_if_missing()
self.name, self.mac = await api.async_get_name_and_mac()
except CannotConnect:
# Likely invalid IP address or device is network unreachable. Stay
# in the user step allowing the user to enter a different host.
errors["base"] = "cannot_connect"
else:
await self.async_set_unique_id(format_mac(self.mac))
if self.source == SOURCE_RECONFIGURE:
self._abort_if_unique_id_mismatch()
@@ -81,11 +86,10 @@ class AndroidTVRemoteConfigFlow(ConfigFlow, domain=DOMAIN):
},
)
self._abort_if_unique_id_configured(updates={CONF_HOST: self.host})
return await self._async_start_pair()
except (CannotConnect, ConnectionClosed):
# Likely invalid IP address or device is network unreachable. Stay
# in the user step allowing the user to enter a different host.
errors["base"] = "cannot_connect"
try:
return await self._async_start_pair()
except (CannotConnect, ConnectionClosed):
errors["base"] = "cannot_connect"
else:
user_input = {}
default_host = user_input.get(CONF_HOST, vol.UNDEFINED)
@@ -112,22 +116,9 @@ class AndroidTVRemoteConfigFlow(ConfigFlow, domain=DOMAIN):
"""Handle the pair step."""
errors: dict[str, str] = {}
if user_input is not None:
pin = user_input["pin"]
try:
pin = user_input["pin"]
await self.api.async_finish_pairing(pin)
if self.source == SOURCE_REAUTH:
return self.async_update_reload_and_abort(
self._get_reauth_entry(), reload_even_if_entry_is_unchanged=True
)
return self.async_create_entry(
title=self.name,
data={
CONF_HOST: self.host,
CONF_NAME: self.name,
CONF_MAC: self.mac,
},
)
except InvalidAuth:
# Invalid PIN. Stay in the pair step allowing the user to enter
# a different PIN.
@@ -145,6 +136,20 @@ class AndroidTVRemoteConfigFlow(ConfigFlow, domain=DOMAIN):
# them to enter a new IP address but we cannot do that for the zeroconf
# flow. Simpler to abort for both flows.
return self.async_abort(reason="cannot_connect")
else:
if self.source == SOURCE_REAUTH:
return self.async_update_reload_and_abort(
self._get_reauth_entry(), reload_even_if_entry_is_unchanged=True
)
return self.async_create_entry(
title=self.name,
data={
CONF_HOST: self.host,
CONF_NAME: self.name,
CONF_MAC: self.mac,
},
)
return self.async_show_form(
step_id="pair",
data_schema=STEP_PAIR_DATA_SCHEMA,

View File

@@ -150,6 +150,62 @@ async def test_user_flow_cannot_connect(
assert len(mock_setup_entry.mock_calls) == 1
async def test_user_flow_start_pair_cannot_connect(
hass: HomeAssistant,
mock_setup_entry: AsyncMock,
mock_unload_entry: AsyncMock,
mock_api: MagicMock,
) -> None:
"""Test async_start_pairing raises CannotConnect in the user flow."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "user"
assert "host" in result["data_schema"].schema
assert not result["errors"]
host = "1.2.3.4"
name = "My Android TV"
mac = "1A:2B:3C:4D:5E:6F"
mock_api.async_generate_cert_if_missing = AsyncMock(return_value=True)
mock_api.async_get_name_and_mac = AsyncMock(return_value=(name, mac))
mock_api.async_start_pairing = AsyncMock(side_effect=CannotConnect())
result = await hass.config_entries.flow.async_configure(
result["flow_id"], {"host": host}
)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "user"
assert "host" in result["data_schema"].schema
assert result["errors"] == {"base": "cannot_connect"}
mock_api.async_generate_cert_if_missing.assert_called()
mock_api.async_get_name_and_mac.assert_called()
mock_api.async_start_pairing.assert_called()
pin = "123456"
mock_api.async_start_pairing = AsyncMock(return_value=None)
mock_api.async_finish_pairing = AsyncMock(return_value=None)
result = await hass.config_entries.flow.async_configure(
result["flow_id"], {"host": host}
)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "pair"
assert not result["errors"]
result = await hass.config_entries.flow.async_configure(
result["flow_id"], {"pin": pin}
)
assert result["type"] is FlowResultType.CREATE_ENTRY
await hass.async_block_till_done()
assert len(mock_setup_entry.mock_calls) == 1
async def test_user_flow_pairing_invalid_auth(
hass: HomeAssistant,
mock_setup_entry: AsyncMock,