Modernize SimpliSafe config flow (#32130)

* Modernize SimpliSafe config flow

* Fix tests
This commit is contained in:
Aaron Bach 2020-02-24 13:03:08 -07:00 committed by GitHub
parent db40b2fc32
commit f7e336eaa6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 43 additions and 18 deletions

View File

@ -1,5 +1,8 @@
{ {
"config": { "config": {
"abort": {
"already_configured": "This SimpliSafe account is already in use."
},
"error": { "error": {
"identifier_exists": "Account already registered", "identifier_exists": "Account already registered",
"invalid_credentials": "Invalid credentials" "invalid_credentials": "Invalid credentials"

View File

@ -1,6 +1,4 @@
"""Config flow to configure the SimpliSafe component.""" """Config flow to configure the SimpliSafe component."""
from collections import OrderedDict
from simplipy import API from simplipy import API
from simplipy.errors import SimplipyError from simplipy.errors import SimplipyError
import voluptuous as vol import voluptuous as vol
@ -21,8 +19,7 @@ def configured_instances(hass):
) )
@config_entries.HANDLERS.register(DOMAIN) class SimpliSafeFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
class SimpliSafeFlowHandler(config_entries.ConfigFlow):
"""Handle a SimpliSafe config flow.""" """Handle a SimpliSafe config flow."""
VERSION = 1 VERSION = 1
@ -30,16 +27,19 @@ class SimpliSafeFlowHandler(config_entries.ConfigFlow):
def __init__(self): def __init__(self):
"""Initialize the config flow.""" """Initialize the config flow."""
self.data_schema = OrderedDict() self.data_schema = vol.Schema(
self.data_schema[vol.Required(CONF_USERNAME)] = str {
self.data_schema[vol.Required(CONF_PASSWORD)] = str vol.Required(CONF_USERNAME): str,
self.data_schema[vol.Optional(CONF_CODE)] = str vol.Required(CONF_PASSWORD): str,
vol.Optional(CONF_CODE): str,
}
)
async def _show_form(self, errors=None): async def _show_form(self, errors=None):
"""Show the form to the user.""" """Show the form to the user."""
return self.async_show_form( return self.async_show_form(
step_id="user", step_id="user",
data_schema=vol.Schema(self.data_schema), data_schema=self.data_schema,
errors=errors if errors else {}, errors=errors if errors else {},
) )
@ -49,12 +49,11 @@ class SimpliSafeFlowHandler(config_entries.ConfigFlow):
async def async_step_user(self, user_input=None): async def async_step_user(self, user_input=None):
"""Handle the start of the config flow.""" """Handle the start of the config flow."""
if not user_input: if not user_input:
return await self._show_form() return await self._show_form()
if user_input[CONF_USERNAME] in configured_instances(self.hass): await self.async_set_unique_id(user_input[CONF_USERNAME])
return await self._show_form({CONF_USERNAME: "identifier_exists"}) self._abort_if_unique_id_configured()
username = user_input[CONF_USERNAME] username = user_input[CONF_USERNAME]
websession = aiohttp_client.async_get_clientsession(self.hass) websession = aiohttp_client.async_get_clientsession(self.hass)
@ -64,7 +63,7 @@ class SimpliSafeFlowHandler(config_entries.ConfigFlow):
username, user_input[CONF_PASSWORD], websession username, user_input[CONF_PASSWORD], websession
) )
except SimplipyError: except SimplipyError:
return await self._show_form({"base": "invalid_credentials"}) return await self._show_form(errors={"base": "invalid_credentials"})
return self.async_create_entry( return self.async_create_entry(
title=user_input[CONF_USERNAME], title=user_input[CONF_USERNAME],

View File

@ -14,6 +14,9 @@
"error": { "error": {
"identifier_exists": "Account already registered", "identifier_exists": "Account already registered",
"invalid_credentials": "Invalid credentials" "invalid_credentials": "Invalid credentials"
},
"abort": {
"already_configured": "This SimpliSafe account is already in use."
} }
} }
} }

View File

@ -4,6 +4,7 @@ from unittest.mock import MagicMock, PropertyMock, mock_open, patch
from homeassistant import data_entry_flow from homeassistant import data_entry_flow
from homeassistant.components.simplisafe import DOMAIN, config_flow from homeassistant.components.simplisafe import DOMAIN, config_flow
from homeassistant.config_entries import SOURCE_USER
from homeassistant.const import CONF_PASSWORD, CONF_TOKEN, CONF_USERNAME from homeassistant.const import CONF_PASSWORD, CONF_TOKEN, CONF_USERNAME
from tests.common import MockConfigEntry, mock_coro from tests.common import MockConfigEntry, mock_coro
@ -20,12 +21,27 @@ async def test_duplicate_error(hass):
"""Test that errors are shown when duplicates are added.""" """Test that errors are shown when duplicates are added."""
conf = {CONF_USERNAME: "user@email.com", CONF_PASSWORD: "password"} conf = {CONF_USERNAME: "user@email.com", CONF_PASSWORD: "password"}
MockConfigEntry(domain=DOMAIN, data=conf).add_to_hass(hass) MockConfigEntry(domain=DOMAIN, unique_id="user@email.com", data=conf).add_to_hass(
flow = config_flow.SimpliSafeFlowHandler() hass
flow.hass = hass )
result = await flow.async_step_user(user_input=conf) result = await hass.config_entries.flow.async_init(
assert result["errors"] == {CONF_USERNAME: "identifier_exists"} DOMAIN, context={"source": SOURCE_USER}, data=conf
)
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
assert result["reason"] == "already_configured"
async def test_get_configured_instances(hass):
"""Test retrieving all configured instances."""
conf = {CONF_USERNAME: "user@email.com", CONF_PASSWORD: "password"}
MockConfigEntry(domain=DOMAIN, unique_id="user@email.com", data=conf).add_to_hass(
hass
)
assert len(config_flow.configured_instances(hass)) == 1
async def test_invalid_credentials(hass): async def test_invalid_credentials(hass):
@ -36,6 +52,7 @@ async def test_invalid_credentials(hass):
flow = config_flow.SimpliSafeFlowHandler() flow = config_flow.SimpliSafeFlowHandler()
flow.hass = hass flow.hass = hass
flow.context = {"source": SOURCE_USER}
with patch( with patch(
"simplipy.API.login_via_credentials", "simplipy.API.login_via_credentials",
@ -49,6 +66,7 @@ async def test_show_form(hass):
"""Test that the form is served with no input.""" """Test that the form is served with no input."""
flow = config_flow.SimpliSafeFlowHandler() flow = config_flow.SimpliSafeFlowHandler()
flow.hass = hass flow.hass = hass
flow.context = {"source": SOURCE_USER}
result = await flow.async_step_user(user_input=None) result = await flow.async_step_user(user_input=None)
@ -62,6 +80,7 @@ async def test_step_import(hass):
flow = config_flow.SimpliSafeFlowHandler() flow = config_flow.SimpliSafeFlowHandler()
flow.hass = hass flow.hass = hass
flow.context = {"source": SOURCE_USER}
mop = mock_open(read_data=json.dumps({"refresh_token": "12345"})) mop = mock_open(read_data=json.dumps({"refresh_token": "12345"}))
@ -91,6 +110,7 @@ async def test_step_user(hass):
flow = config_flow.SimpliSafeFlowHandler() flow = config_flow.SimpliSafeFlowHandler()
flow.hass = hass flow.hass = hass
flow.context = {"source": SOURCE_USER}
mop = mock_open(read_data=json.dumps({"refresh_token": "12345"})) mop = mock_open(read_data=json.dumps({"refresh_token": "12345"}))