Improve UniFi config flow tests and add options flow test (#27340)

This commit is contained in:
Robert Svensson 2019-10-08 23:44:33 +02:00 committed by Paulus Schoutsen
parent 7f20210e93
commit d345b58ce6
4 changed files with 268 additions and 177 deletions

View file

@ -150,12 +150,6 @@ class UnifiFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
self.desc = next(iter(self.sites.values()))["desc"]
return await self.async_step_site(user_input={})
if self.desc is not None:
for site in self.sites.values():
if self.desc == site["name"]:
self.desc = site["desc"]
return await self.async_step_site(user_input={})
sites = []
for site in self.sites.values():
sites.append(site["desc"])

View file

@ -387,7 +387,7 @@ async def test_hassio_confirm(hass):
async def test_option_flow(hass):
"""Test config flow selection of one of two bridges."""
"""Test config flow options."""
entry = MockConfigEntry(domain=config_flow.DOMAIN, data={}, options=None)
hass.config_entries._entries.append(entry)

View file

@ -0,0 +1,265 @@
"""Test UniFi config flow."""
from asynctest import patch
from homeassistant.components import unifi
from homeassistant.components.unifi import config_flow
from homeassistant.components.unifi.const import CONF_CONTROLLER, CONF_SITE_ID
from homeassistant.const import (
CONF_HOST,
CONF_PASSWORD,
CONF_PORT,
CONF_USERNAME,
CONF_VERIFY_SSL,
)
from tests.common import MockConfigEntry
import aiounifi
async def test_flow_works(hass, aioclient_mock):
"""Test config flow."""
result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, context={"source": "user"}
)
assert result["type"] == "form"
assert result["step_id"] == "user"
aioclient_mock.post(
"https://1.2.3.4:1234/api/login",
json={"data": "login successful", "meta": {"rc": "ok"}},
headers={"content-type": "application/json"},
)
aioclient_mock.get(
"https://1.2.3.4:1234/api/self/sites",
json={
"data": [{"desc": "Site name", "name": "site_id", "role": "admin"}],
"meta": {"rc": "ok"},
},
headers={"content-type": "application/json"},
)
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={
CONF_HOST: "1.2.3.4",
CONF_USERNAME: "username",
CONF_PASSWORD: "password",
CONF_PORT: 1234,
CONF_VERIFY_SSL: True,
},
)
assert result["type"] == "create_entry"
assert result["title"] == "Site name"
assert result["data"] == {
CONF_CONTROLLER: {
CONF_HOST: "1.2.3.4",
CONF_USERNAME: "username",
CONF_PASSWORD: "password",
CONF_PORT: 1234,
CONF_SITE_ID: "site_id",
CONF_VERIFY_SSL: True,
}
}
async def test_flow_works_multiple_sites(hass, aioclient_mock):
"""Test config flow works when finding multiple sites."""
result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, context={"source": "user"}
)
assert result["type"] == "form"
assert result["step_id"] == "user"
aioclient_mock.post(
"https://1.2.3.4:1234/api/login",
json={"data": "login successful", "meta": {"rc": "ok"}},
headers={"content-type": "application/json"},
)
aioclient_mock.get(
"https://1.2.3.4:1234/api/self/sites",
json={
"data": [
{"name": "default", "role": "admin", "desc": "site name"},
{"name": "site2", "role": "admin", "desc": "site2 name"},
],
"meta": {"rc": "ok"},
},
headers={"content-type": "application/json"},
)
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={
CONF_HOST: "1.2.3.4",
CONF_USERNAME: "username",
CONF_PASSWORD: "password",
CONF_PORT: 1234,
CONF_VERIFY_SSL: True,
},
)
assert result["type"] == "form"
assert result["step_id"] == "site"
assert result["data_schema"]({"site": "site name"})
assert result["data_schema"]({"site": "site2 name"})
async def test_flow_fails_site_already_configured(hass, aioclient_mock):
"""Test config flow."""
entry = MockConfigEntry(
domain=unifi.DOMAIN, data={"controller": {"host": "1.2.3.4", "site": "site_id"}}
)
entry.add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, context={"source": "user"}
)
assert result["type"] == "form"
assert result["step_id"] == "user"
aioclient_mock.post(
"https://1.2.3.4:1234/api/login",
json={"data": "login successful", "meta": {"rc": "ok"}},
headers={"content-type": "application/json"},
)
aioclient_mock.get(
"https://1.2.3.4:1234/api/self/sites",
json={
"data": [{"desc": "Site name", "name": "site_id", "role": "admin"}],
"meta": {"rc": "ok"},
},
headers={"content-type": "application/json"},
)
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={
CONF_HOST: "1.2.3.4",
CONF_USERNAME: "username",
CONF_PASSWORD: "password",
CONF_PORT: 1234,
CONF_VERIFY_SSL: True,
},
)
assert result["type"] == "abort"
async def test_flow_fails_user_credentials_faulty(hass, aioclient_mock):
"""Test config flow."""
result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, context={"source": "user"}
)
assert result["type"] == "form"
assert result["step_id"] == "user"
with patch("aiounifi.Controller.login", side_effect=aiounifi.errors.Unauthorized):
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={
CONF_HOST: "1.2.3.4",
CONF_USERNAME: "username",
CONF_PASSWORD: "password",
CONF_PORT: 1234,
CONF_VERIFY_SSL: True,
},
)
assert result["type"] == "form"
assert result["errors"] == {"base": "faulty_credentials"}
async def test_flow_fails_controller_unavailable(hass, aioclient_mock):
"""Test config flow."""
result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, context={"source": "user"}
)
assert result["type"] == "form"
assert result["step_id"] == "user"
with patch("aiounifi.Controller.login", side_effect=aiounifi.errors.RequestError):
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={
CONF_HOST: "1.2.3.4",
CONF_USERNAME: "username",
CONF_PASSWORD: "password",
CONF_PORT: 1234,
CONF_VERIFY_SSL: True,
},
)
assert result["type"] == "form"
assert result["errors"] == {"base": "service_unavailable"}
async def test_flow_fails_unknown_problem(hass, aioclient_mock):
"""Test config flow."""
result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, context={"source": "user"}
)
assert result["type"] == "form"
assert result["step_id"] == "user"
with patch("aiounifi.Controller.login", side_effect=Exception):
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={
CONF_HOST: "1.2.3.4",
CONF_USERNAME: "username",
CONF_PASSWORD: "password",
CONF_PORT: 1234,
CONF_VERIFY_SSL: True,
},
)
assert result["type"] == "abort"
async def test_option_flow(hass):
"""Test config flow options."""
entry = MockConfigEntry(domain=config_flow.DOMAIN, data={}, options=None)
hass.config_entries._entries.append(entry)
flow = await hass.config_entries.options._async_create_flow(
entry.entry_id, context={"source": "test"}, data=None
)
result = await flow.async_step_init()
assert result["type"] == "form"
assert result["step_id"] == "device_tracker"
result = await flow.async_step_device_tracker(
user_input={
config_flow.CONF_TRACK_CLIENTS: False,
config_flow.CONF_TRACK_WIRED_CLIENTS: False,
config_flow.CONF_TRACK_DEVICES: False,
config_flow.CONF_DETECTION_TIME: 100,
}
)
assert result["type"] == "form"
assert result["step_id"] == "statistics_sensors"
result = await flow.async_step_statistics_sensors(
user_input={config_flow.CONF_ALLOW_BANDWIDTH_SENSORS: True}
)
assert result["type"] == "create_entry"
assert result["data"] == {
config_flow.CONF_TRACK_CLIENTS: False,
config_flow.CONF_TRACK_WIRED_CLIENTS: False,
config_flow.CONF_TRACK_DEVICES: False,
config_flow.CONF_DETECTION_TIME: 100,
config_flow.CONF_ALLOW_BANDWIDTH_SENSORS: True,
}

View file

@ -2,16 +2,9 @@
from unittest.mock import Mock, patch
from homeassistant.components import unifi
from homeassistant.components.unifi import config_flow
from homeassistant.setup import async_setup_component
from homeassistant.components.unifi.const import CONF_CONTROLLER, CONF_SITE_ID
from homeassistant.const import (
CONF_HOST,
CONF_PASSWORD,
CONF_PORT,
CONF_USERNAME,
CONF_VERIFY_SSL,
)
from tests.common import mock_coro, MockConfigEntry
@ -179,164 +172,3 @@ async def test_unload_entry(hass):
assert await unifi.async_unload_entry(hass, entry)
assert len(mock_controller.return_value.async_reset.mock_calls) == 1
assert hass.data[unifi.DOMAIN] == {}
async def test_flow_works(hass, aioclient_mock):
"""Test config flow."""
flow = config_flow.UnifiFlowHandler()
flow.hass = hass
with patch("aiounifi.Controller") as mock_controller:
def mock_constructor(
host, username, password, port, site, websession, sslcontext
):
"""Fake the controller constructor."""
mock_controller.host = host
mock_controller.username = username
mock_controller.password = password
mock_controller.port = port
mock_controller.site = site
return mock_controller
mock_controller.side_effect = mock_constructor
mock_controller.login.return_value = mock_coro()
mock_controller.sites.return_value = mock_coro(
{"site1": {"name": "default", "role": "admin", "desc": "site name"}}
)
await flow.async_step_user(
user_input={
CONF_HOST: "1.2.3.4",
CONF_USERNAME: "username",
CONF_PASSWORD: "password",
CONF_PORT: 1234,
CONF_VERIFY_SSL: True,
}
)
result = await flow.async_step_site(user_input={})
assert mock_controller.host == "1.2.3.4"
assert len(mock_controller.login.mock_calls) == 1
assert len(mock_controller.sites.mock_calls) == 1
assert result["type"] == "create_entry"
assert result["title"] == "site name"
assert result["data"] == {
CONF_CONTROLLER: {
CONF_HOST: "1.2.3.4",
CONF_USERNAME: "username",
CONF_PASSWORD: "password",
CONF_PORT: 1234,
CONF_SITE_ID: "default",
CONF_VERIFY_SSL: True,
}
}
async def test_controller_multiple_sites(hass):
"""Test config flow."""
flow = config_flow.UnifiFlowHandler()
flow.hass = hass
flow.config = {
CONF_HOST: "1.2.3.4",
CONF_USERNAME: "username",
CONF_PASSWORD: "password",
}
flow.sites = {
"site1": {"name": "default", "role": "admin", "desc": "site name"},
"site2": {"name": "site2", "role": "admin", "desc": "site2 name"},
}
result = await flow.async_step_site()
assert result["type"] == "form"
assert result["step_id"] == "site"
assert result["data_schema"]({"site": "site name"})
assert result["data_schema"]({"site": "site2 name"})
async def test_controller_site_already_configured(hass):
"""Test config flow."""
flow = config_flow.UnifiFlowHandler()
flow.hass = hass
entry = MockConfigEntry(
domain=unifi.DOMAIN, data={"controller": {"host": "1.2.3.4", "site": "default"}}
)
entry.add_to_hass(hass)
flow.config = {
CONF_HOST: "1.2.3.4",
CONF_USERNAME: "username",
CONF_PASSWORD: "password",
}
flow.desc = "site name"
flow.sites = {"site1": {"name": "default", "role": "admin", "desc": "site name"}}
result = await flow.async_step_site()
assert result["type"] == "abort"
async def test_user_credentials_faulty(hass, aioclient_mock):
"""Test config flow."""
flow = config_flow.UnifiFlowHandler()
flow.hass = hass
with patch.object(
config_flow, "get_controller", side_effect=unifi.errors.AuthenticationRequired
):
result = await flow.async_step_user(
{
CONF_HOST: "1.2.3.4",
CONF_USERNAME: "username",
CONF_PASSWORD: "password",
CONF_SITE_ID: "default",
}
)
assert result["type"] == "form"
assert result["errors"] == {"base": "faulty_credentials"}
async def test_controller_is_unavailable(hass, aioclient_mock):
"""Test config flow."""
flow = config_flow.UnifiFlowHandler()
flow.hass = hass
with patch.object(
config_flow, "get_controller", side_effect=unifi.errors.CannotConnect
):
result = await flow.async_step_user(
{
CONF_HOST: "1.2.3.4",
CONF_USERNAME: "username",
CONF_PASSWORD: "password",
CONF_SITE_ID: "default",
}
)
assert result["type"] == "form"
assert result["errors"] == {"base": "service_unavailable"}
async def test_controller_unkown_problem(hass, aioclient_mock):
"""Test config flow."""
flow = config_flow.UnifiFlowHandler()
flow.hass = hass
with patch.object(config_flow, "get_controller", side_effect=Exception):
result = await flow.async_step_user(
{
CONF_HOST: "1.2.3.4",
CONF_USERNAME: "username",
CONF_PASSWORD: "password",
CONF_SITE_ID: "default",
}
)
assert result["type"] == "abort"