Exception handling config flow yale_smart_alarm (#63623)

This commit is contained in:
G Johansson 2022-01-18 04:29:55 +01:00 committed by GitHub
parent eda806ca12
commit a334e0c7b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 127 additions and 50 deletions

View File

@ -5,7 +5,7 @@ from typing import Any
import voluptuous as vol import voluptuous as vol
from yalesmartalarmclient.client import YaleSmartAlarmClient from yalesmartalarmclient.client import YaleSmartAlarmClient
from yalesmartalarmclient.exceptions import AuthenticationError from yalesmartalarmclient.exceptions import AuthenticationError, UnknownError
from homeassistant.config_entries import ConfigEntry, ConfigFlow, OptionsFlow from homeassistant.config_entries import ConfigEntry, ConfigFlow, OptionsFlow
from homeassistant.const import CONF_CODE, CONF_NAME, CONF_PASSWORD, CONF_USERNAME from homeassistant.const import CONF_CODE, CONF_NAME, CONF_PASSWORD, CONF_USERNAME
@ -80,12 +80,12 @@ class YaleConfigFlow(ConfigFlow, domain=DOMAIN):
) )
except AuthenticationError as error: except AuthenticationError as error:
LOGGER.error("Authentication failed. Check credentials %s", error) LOGGER.error("Authentication failed. Check credentials %s", error)
return self.async_show_form( errors = {"base": "invalid_auth"}
step_id="reauth_confirm", except (ConnectionError, TimeoutError, UnknownError) as error:
data_schema=DATA_SCHEMA, LOGGER.error("Connection to API failed %s", error)
errors={"base": "invalid_auth"}, errors = {"base": "cannot_connect"}
)
if not errors:
existing_entry = await self.async_set_unique_id(username) existing_entry = await self.async_set_unique_id(username)
if existing_entry: if existing_entry:
self.hass.config_entries.async_update_entry( self.hass.config_entries.async_update_entry(
@ -121,12 +121,12 @@ class YaleConfigFlow(ConfigFlow, domain=DOMAIN):
) )
except AuthenticationError as error: except AuthenticationError as error:
LOGGER.error("Authentication failed. Check credentials %s", error) LOGGER.error("Authentication failed. Check credentials %s", error)
return self.async_show_form( errors = {"base": "invalid_auth"}
step_id="user", except (ConnectionError, TimeoutError, UnknownError) as error:
data_schema=DATA_SCHEMA, LOGGER.error("Connection to API failed %s", error)
errors={"base": "invalid_auth"}, errors = {"base": "cannot_connect"}
)
if not errors:
await self.async_set_unique_id(username) await self.async_set_unique_id(username)
self._abort_if_unique_id_configured() self._abort_if_unique_id_configured()

View File

@ -5,7 +5,8 @@
"reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]" "reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]"
}, },
"error": { "error": {
"invalid_auth": "[%key:common::config_flow::error::invalid_auth%]" "invalid_auth": "[%key:common::config_flow::error::invalid_auth%]",
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]"
}, },
"step": { "step": {
"user": { "user": {

View File

@ -5,7 +5,8 @@
"reauth_successful": "Re-authentication was successful" "reauth_successful": "Re-authentication was successful"
}, },
"error": { "error": {
"invalid_auth": "Invalid authentication" "invalid_auth": "Invalid authentication",
"cannot_connect": "Failed to connect"
}, },
"step": { "step": {
"reauth_confirm": { "reauth_confirm": {
@ -15,6 +16,7 @@
"password": "Password", "password": "Password",
"username": "Username" "username": "Username"
} }
}
}, },
"user": { "user": {
"data": { "data": {
@ -24,7 +26,6 @@
"username": "Username" "username": "Username"
} }
} }
}
}, },
"options": { "options": {
"error": { "error": {

View File

@ -4,7 +4,7 @@ from __future__ import annotations
from unittest.mock import patch from unittest.mock import patch
import pytest import pytest
from yalesmartalarmclient.exceptions import AuthenticationError from yalesmartalarmclient.exceptions import AuthenticationError, UnknownError
from homeassistant import config_entries from homeassistant import config_entries
from homeassistant.components.yale_smart_alarm.const import DOMAIN from homeassistant.components.yale_smart_alarm.const import DOMAIN
@ -24,7 +24,7 @@ async def test_form(hass: HomeAssistant) -> None:
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER} DOMAIN, context={"source": config_entries.SOURCE_USER}
) )
assert result["type"] == "form" assert result["type"] == RESULT_TYPE_FORM
assert result["errors"] == {} assert result["errors"] == {}
with patch( with patch(
@ -44,7 +44,7 @@ async def test_form(hass: HomeAssistant) -> None:
) )
await hass.async_block_till_done() await hass.async_block_till_done()
assert result2["type"] == "create_entry" assert result2["type"] == RESULT_TYPE_CREATE_ENTRY
assert result2["title"] == "test-username" assert result2["title"] == "test-username"
assert result2["data"] == { assert result2["data"] == {
"username": "test-username", "username": "test-username",
@ -55,7 +55,18 @@ async def test_form(hass: HomeAssistant) -> None:
assert len(mock_setup_entry.mock_calls) == 1 assert len(mock_setup_entry.mock_calls) == 1
async def test_form_invalid_auth(hass: HomeAssistant) -> None: @pytest.mark.parametrize(
"sideeffect,p_error",
[
(AuthenticationError, "invalid_auth"),
(ConnectionError, "cannot_connect"),
(TimeoutError, "cannot_connect"),
(UnknownError, "cannot_connect"),
],
)
async def test_form_invalid_auth(
hass: HomeAssistant, sideeffect: Exception, p_error: str
) -> None:
"""Test we handle invalid auth.""" """Test we handle invalid auth."""
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER} DOMAIN, context={"source": config_entries.SOURCE_USER}
@ -63,7 +74,7 @@ async def test_form_invalid_auth(hass: HomeAssistant) -> None:
with patch( with patch(
"homeassistant.components.yale_smart_alarm.config_flow.YaleSmartAlarmClient", "homeassistant.components.yale_smart_alarm.config_flow.YaleSmartAlarmClient",
side_effect=AuthenticationError, side_effect=sideeffect,
): ):
result2 = await hass.config_entries.flow.async_configure( result2 = await hass.config_entries.flow.async_configure(
result["flow_id"], result["flow_id"],
@ -76,8 +87,34 @@ async def test_form_invalid_auth(hass: HomeAssistant) -> None:
) )
await hass.async_block_till_done() await hass.async_block_till_done()
assert result2["type"] == "form" assert result2["type"] == RESULT_TYPE_FORM
assert result2["errors"] == {"base": "invalid_auth"} assert result2["errors"] == {"base": p_error}
with patch(
"homeassistant.components.yale_smart_alarm.config_flow.YaleSmartAlarmClient",
), patch(
"homeassistant.components.yale_smart_alarm.async_setup_entry",
return_value=True,
):
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{
"username": "test-username",
"password": "test-password",
"name": "Yale Smart Alarm",
"area_id": "1",
},
)
await hass.async_block_till_done()
assert result2["type"] == RESULT_TYPE_CREATE_ENTRY
assert result2["title"] == "test-username"
assert result2["data"] == {
"username": "test-username",
"password": "test-password",
"name": "Yale Smart Alarm",
"area_id": "1",
}
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -190,7 +227,18 @@ async def test_reauth_flow(hass: HomeAssistant) -> None:
assert len(mock_setup_entry.mock_calls) == 1 assert len(mock_setup_entry.mock_calls) == 1
async def test_reauth_flow_invalid_login(hass: HomeAssistant) -> None: @pytest.mark.parametrize(
"sideeffect,p_error",
[
(AuthenticationError, "invalid_auth"),
(ConnectionError, "cannot_connect"),
(TimeoutError, "cannot_connect"),
(UnknownError, "cannot_connect"),
],
)
async def test_reauth_flow_error(
hass: HomeAssistant, sideeffect: Exception, p_error: str
) -> None:
"""Test a reauthentication flow.""" """Test a reauthentication flow."""
entry = MockConfigEntry( entry = MockConfigEntry(
domain=DOMAIN, domain=DOMAIN,
@ -198,6 +246,8 @@ async def test_reauth_flow_invalid_login(hass: HomeAssistant) -> None:
data={ data={
"username": "test-username", "username": "test-username",
"password": "test-password", "password": "test-password",
"name": "Yale Smart Alarm",
"area_id": "1",
}, },
) )
entry.add_to_hass(hass) entry.add_to_hass(hass)
@ -214,7 +264,7 @@ async def test_reauth_flow_invalid_login(hass: HomeAssistant) -> None:
with patch( with patch(
"homeassistant.components.yale_smart_alarm.config_flow.YaleSmartAlarmClient", "homeassistant.components.yale_smart_alarm.config_flow.YaleSmartAlarmClient",
side_effect=AuthenticationError, side_effect=sideeffect,
): ):
result2 = await hass.config_entries.flow.async_configure( result2 = await hass.config_entries.flow.async_configure(
result["flow_id"], result["flow_id"],
@ -226,8 +276,33 @@ async def test_reauth_flow_invalid_login(hass: HomeAssistant) -> None:
await hass.async_block_till_done() await hass.async_block_till_done()
assert result2["step_id"] == "reauth_confirm" assert result2["step_id"] == "reauth_confirm"
assert result2["type"] == "form" assert result2["type"] == RESULT_TYPE_FORM
assert result2["errors"] == {"base": "invalid_auth"} assert result2["errors"] == {"base": p_error}
with patch(
"homeassistant.components.yale_smart_alarm.config_flow.YaleSmartAlarmClient",
return_value="",
), patch(
"homeassistant.components.yale_smart_alarm.async_setup_entry",
return_value=True,
):
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{
"username": "test-username",
"password": "new-test-password",
},
)
await hass.async_block_till_done()
assert result2["type"] == RESULT_TYPE_ABORT
assert result2["reason"] == "reauth_successful"
assert entry.data == {
"username": "test-username",
"password": "new-test-password",
"name": "Yale Smart Alarm",
"area_id": "1",
}
async def test_options_flow(hass: HomeAssistant) -> None: async def test_options_flow(hass: HomeAssistant) -> None: