Improve UniFi config flow tests and add options flow test (#27340)
This commit is contained in:
parent
7f20210e93
commit
d345b58ce6
4 changed files with 268 additions and 177 deletions
|
@ -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"])
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
265
tests/components/unifi/test_config_flow.py
Normal file
265
tests/components/unifi/test_config_flow.py
Normal 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,
|
||||
}
|
|
@ -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"
|
||||
|
|
Loading…
Add table
Reference in a new issue