2018-10-16 08:35:35 +00:00
|
|
|
"""Test UniFi Controller."""
|
|
|
|
from unittest.mock import Mock, patch
|
|
|
|
|
2019-02-14 04:36:06 +00:00
|
|
|
import pytest
|
|
|
|
|
|
|
|
from homeassistant.exceptions import ConfigEntryNotReady
|
2019-07-14 19:57:09 +00:00
|
|
|
from homeassistant.components.unifi.const import (
|
2019-07-31 19:25:30 +00:00
|
|
|
CONF_CONTROLLER,
|
|
|
|
CONF_SITE_ID,
|
|
|
|
UNIFI_CONFIG,
|
|
|
|
)
|
2019-05-13 08:16:55 +00:00
|
|
|
from homeassistant.const import (
|
2019-07-31 19:25:30 +00:00
|
|
|
CONF_HOST,
|
|
|
|
CONF_PASSWORD,
|
|
|
|
CONF_PORT,
|
|
|
|
CONF_USERNAME,
|
|
|
|
CONF_VERIFY_SSL,
|
|
|
|
)
|
2018-10-16 08:35:35 +00:00
|
|
|
from homeassistant.components.unifi import controller, errors
|
|
|
|
|
|
|
|
from tests.common import mock_coro
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
CONTROLLER_SITES = {"site1": {"desc": "nice name", "name": "site", "role": "admin"}}
|
2019-07-14 19:57:09 +00:00
|
|
|
|
2018-10-16 08:35:35 +00:00
|
|
|
CONTROLLER_DATA = {
|
2019-07-31 19:25:30 +00:00
|
|
|
CONF_HOST: "1.2.3.4",
|
|
|
|
CONF_USERNAME: "username",
|
|
|
|
CONF_PASSWORD: "password",
|
2019-05-13 08:16:55 +00:00
|
|
|
CONF_PORT: 1234,
|
2019-07-31 19:25:30 +00:00
|
|
|
CONF_SITE_ID: "site",
|
|
|
|
CONF_VERIFY_SSL: True,
|
2018-10-16 08:35:35 +00:00
|
|
|
}
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
ENTRY_CONFIG = {CONF_CONTROLLER: CONTROLLER_DATA}
|
2018-10-16 08:35:35 +00:00
|
|
|
|
|
|
|
|
|
|
|
async def test_controller_setup():
|
|
|
|
"""Successful setup."""
|
|
|
|
hass = Mock()
|
2019-08-21 20:22:42 +00:00
|
|
|
hass.data = {
|
|
|
|
UNIFI_CONFIG: [
|
|
|
|
{
|
|
|
|
CONF_HOST: CONTROLLER_DATA[CONF_HOST],
|
|
|
|
CONF_SITE_ID: "nice name",
|
2019-08-31 20:04:04 +00:00
|
|
|
controller.CONF_BLOCK_CLIENT: ["mac"],
|
|
|
|
controller.CONF_DONT_TRACK_CLIENTS: True,
|
|
|
|
controller.CONF_DONT_TRACK_DEVICES: True,
|
|
|
|
controller.CONF_DONT_TRACK_WIRED_CLIENTS: True,
|
|
|
|
controller.CONF_DETECTION_TIME: 30,
|
|
|
|
controller.CONF_SSID_FILTER: ["ssid"],
|
2019-08-21 20:22:42 +00:00
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
2018-10-16 08:35:35 +00:00
|
|
|
entry = Mock()
|
|
|
|
entry.data = ENTRY_CONFIG
|
2019-08-21 20:22:42 +00:00
|
|
|
entry.options = {}
|
2018-10-16 08:35:35 +00:00
|
|
|
api = Mock()
|
|
|
|
api.initialize.return_value = mock_coro(True)
|
2019-07-14 19:57:09 +00:00
|
|
|
api.sites.return_value = mock_coro(CONTROLLER_SITES)
|
2018-10-16 08:35:35 +00:00
|
|
|
|
|
|
|
unifi_controller = controller.UniFiController(hass, entry)
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
with patch.object(controller, "get_controller", return_value=mock_coro(api)):
|
2018-10-16 08:35:35 +00:00
|
|
|
assert await unifi_controller.async_setup() is True
|
|
|
|
|
|
|
|
assert unifi_controller.api is api
|
2019-07-14 19:57:09 +00:00
|
|
|
assert len(hass.config_entries.async_forward_entry_setup.mock_calls) == 2
|
2019-07-31 19:25:30 +00:00
|
|
|
assert hass.config_entries.async_forward_entry_setup.mock_calls[0][1] == (
|
|
|
|
entry,
|
|
|
|
"device_tracker",
|
|
|
|
)
|
|
|
|
assert hass.config_entries.async_forward_entry_setup.mock_calls[1][1] == (
|
|
|
|
entry,
|
|
|
|
"switch",
|
|
|
|
)
|
2018-10-16 08:35:35 +00:00
|
|
|
|
|
|
|
|
|
|
|
async def test_controller_host():
|
|
|
|
"""Config entry host and controller host are the same."""
|
|
|
|
hass = Mock()
|
|
|
|
entry = Mock()
|
|
|
|
entry.data = ENTRY_CONFIG
|
|
|
|
|
|
|
|
unifi_controller = controller.UniFiController(hass, entry)
|
|
|
|
|
2019-07-14 19:57:09 +00:00
|
|
|
assert unifi_controller.host == CONTROLLER_DATA[CONF_HOST]
|
|
|
|
|
|
|
|
|
|
|
|
async def test_controller_site():
|
|
|
|
"""Config entry site and controller site are the same."""
|
|
|
|
hass = Mock()
|
|
|
|
entry = Mock()
|
|
|
|
entry.data = ENTRY_CONFIG
|
|
|
|
|
|
|
|
unifi_controller = controller.UniFiController(hass, entry)
|
|
|
|
|
|
|
|
assert unifi_controller.site == CONTROLLER_DATA[CONF_SITE_ID]
|
2018-10-16 08:35:35 +00:00
|
|
|
|
|
|
|
|
|
|
|
async def test_controller_mac():
|
|
|
|
"""Test that it is possible to identify controller mac."""
|
|
|
|
hass = Mock()
|
2019-07-14 19:57:09 +00:00
|
|
|
hass.data = {UNIFI_CONFIG: {}}
|
2018-10-16 08:35:35 +00:00
|
|
|
entry = Mock()
|
|
|
|
entry.data = ENTRY_CONFIG
|
2019-08-21 20:22:42 +00:00
|
|
|
entry.options = {}
|
2018-10-16 08:35:35 +00:00
|
|
|
client = Mock()
|
2019-07-31 19:25:30 +00:00
|
|
|
client.ip = "1.2.3.4"
|
|
|
|
client.mac = "00:11:22:33:44:55"
|
2018-10-16 08:35:35 +00:00
|
|
|
api = Mock()
|
|
|
|
api.initialize.return_value = mock_coro(True)
|
2019-07-31 19:25:30 +00:00
|
|
|
api.clients = {"client1": client}
|
2019-07-14 19:57:09 +00:00
|
|
|
api.sites.return_value = mock_coro(CONTROLLER_SITES)
|
2018-10-16 08:35:35 +00:00
|
|
|
|
|
|
|
unifi_controller = controller.UniFiController(hass, entry)
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
with patch.object(controller, "get_controller", return_value=mock_coro(api)):
|
2018-10-16 08:35:35 +00:00
|
|
|
assert await unifi_controller.async_setup() is True
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
assert unifi_controller.mac == "00:11:22:33:44:55"
|
2018-10-16 08:35:35 +00:00
|
|
|
|
|
|
|
|
|
|
|
async def test_controller_no_mac():
|
|
|
|
"""Test that it works to not find the controllers mac."""
|
|
|
|
hass = Mock()
|
2019-07-14 19:57:09 +00:00
|
|
|
hass.data = {UNIFI_CONFIG: {}}
|
2018-10-16 08:35:35 +00:00
|
|
|
entry = Mock()
|
|
|
|
entry.data = ENTRY_CONFIG
|
2019-08-21 20:22:42 +00:00
|
|
|
entry.options = {}
|
2018-10-16 08:35:35 +00:00
|
|
|
client = Mock()
|
2019-07-31 19:25:30 +00:00
|
|
|
client.ip = "5.6.7.8"
|
2018-10-16 08:35:35 +00:00
|
|
|
api = Mock()
|
|
|
|
api.initialize.return_value = mock_coro(True)
|
2019-07-31 19:25:30 +00:00
|
|
|
api.clients = {"client1": client}
|
2019-07-14 19:57:09 +00:00
|
|
|
api.sites.return_value = mock_coro(CONTROLLER_SITES)
|
2018-10-16 08:35:35 +00:00
|
|
|
|
|
|
|
unifi_controller = controller.UniFiController(hass, entry)
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
with patch.object(controller, "get_controller", return_value=mock_coro(api)):
|
2018-10-16 08:35:35 +00:00
|
|
|
assert await unifi_controller.async_setup() is True
|
|
|
|
|
|
|
|
assert unifi_controller.mac is None
|
|
|
|
|
|
|
|
|
|
|
|
async def test_controller_not_accessible():
|
|
|
|
"""Retry to login gets scheduled when connection fails."""
|
|
|
|
hass = Mock()
|
|
|
|
entry = Mock()
|
|
|
|
entry.data = ENTRY_CONFIG
|
|
|
|
api = Mock()
|
|
|
|
api.initialize.return_value = mock_coro(True)
|
|
|
|
|
|
|
|
unifi_controller = controller.UniFiController(hass, entry)
|
|
|
|
|
2019-02-14 04:36:06 +00:00
|
|
|
with patch.object(
|
2019-07-31 19:25:30 +00:00
|
|
|
controller, "get_controller", side_effect=errors.CannotConnect
|
2019-02-14 04:36:06 +00:00
|
|
|
), pytest.raises(ConfigEntryNotReady):
|
|
|
|
await unifi_controller.async_setup()
|
2018-10-16 08:35:35 +00:00
|
|
|
|
|
|
|
|
|
|
|
async def test_controller_unknown_error():
|
|
|
|
"""Unknown errors are handled."""
|
|
|
|
hass = Mock()
|
|
|
|
entry = Mock()
|
|
|
|
entry.data = ENTRY_CONFIG
|
|
|
|
api = Mock()
|
|
|
|
api.initialize.return_value = mock_coro(True)
|
|
|
|
|
|
|
|
unifi_controller = controller.UniFiController(hass, entry)
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
with patch.object(controller, "get_controller", side_effect=Exception):
|
2018-10-16 08:35:35 +00:00
|
|
|
assert await unifi_controller.async_setup() is False
|
|
|
|
|
|
|
|
assert not hass.helpers.event.async_call_later.mock_calls
|
|
|
|
|
|
|
|
|
|
|
|
async def test_reset_if_entry_had_wrong_auth():
|
|
|
|
"""Calling reset when the entry contains wrong auth."""
|
|
|
|
hass = Mock()
|
|
|
|
entry = Mock()
|
|
|
|
entry.data = ENTRY_CONFIG
|
|
|
|
|
|
|
|
unifi_controller = controller.UniFiController(hass, entry)
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
with patch.object(
|
|
|
|
controller, "get_controller", side_effect=errors.AuthenticationRequired
|
|
|
|
):
|
2018-10-16 08:35:35 +00:00
|
|
|
assert await unifi_controller.async_setup() is False
|
|
|
|
|
|
|
|
assert not hass.async_add_job.mock_calls
|
|
|
|
|
|
|
|
assert await unifi_controller.async_reset()
|
|
|
|
|
|
|
|
|
|
|
|
async def test_reset_unloads_entry_if_setup():
|
|
|
|
"""Calling reset when the entry has been setup."""
|
|
|
|
hass = Mock()
|
2019-07-14 19:57:09 +00:00
|
|
|
hass.data = {UNIFI_CONFIG: {}}
|
2018-10-16 08:35:35 +00:00
|
|
|
entry = Mock()
|
|
|
|
entry.data = ENTRY_CONFIG
|
2019-08-21 20:22:42 +00:00
|
|
|
entry.options = {}
|
2018-10-16 08:35:35 +00:00
|
|
|
api = Mock()
|
|
|
|
api.initialize.return_value = mock_coro(True)
|
2019-07-14 19:57:09 +00:00
|
|
|
api.sites.return_value = mock_coro(CONTROLLER_SITES)
|
2018-10-16 08:35:35 +00:00
|
|
|
|
|
|
|
unifi_controller = controller.UniFiController(hass, entry)
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
with patch.object(controller, "get_controller", return_value=mock_coro(api)):
|
2018-10-16 08:35:35 +00:00
|
|
|
assert await unifi_controller.async_setup() is True
|
|
|
|
|
2019-07-14 19:57:09 +00:00
|
|
|
assert len(hass.config_entries.async_forward_entry_setup.mock_calls) == 2
|
2018-10-16 08:35:35 +00:00
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
hass.config_entries.async_forward_entry_unload.return_value = mock_coro(True)
|
2018-10-16 08:35:35 +00:00
|
|
|
assert await unifi_controller.async_reset()
|
|
|
|
|
2019-07-14 19:57:09 +00:00
|
|
|
assert len(hass.config_entries.async_forward_entry_unload.mock_calls) == 2
|
2018-10-16 08:35:35 +00:00
|
|
|
|
|
|
|
|
|
|
|
async def test_get_controller(hass):
|
|
|
|
"""Successful call."""
|
2019-07-31 19:25:30 +00:00
|
|
|
with patch("aiounifi.Controller.login", return_value=mock_coro()):
|
2018-10-16 08:35:35 +00:00
|
|
|
assert await controller.get_controller(hass, **CONTROLLER_DATA)
|
|
|
|
|
|
|
|
|
|
|
|
async def test_get_controller_verify_ssl_false(hass):
|
|
|
|
"""Successful call with verify ssl set to false."""
|
|
|
|
controller_data = dict(CONTROLLER_DATA)
|
2019-05-13 08:16:55 +00:00
|
|
|
controller_data[CONF_VERIFY_SSL] = False
|
2019-07-31 19:25:30 +00:00
|
|
|
with patch("aiounifi.Controller.login", return_value=mock_coro()):
|
2018-10-16 08:35:35 +00:00
|
|
|
assert await controller.get_controller(hass, **controller_data)
|
|
|
|
|
|
|
|
|
|
|
|
async def test_get_controller_login_failed(hass):
|
|
|
|
"""Check that get_controller can handle a failed login."""
|
|
|
|
import aiounifi
|
2019-07-31 19:25:30 +00:00
|
|
|
|
2018-10-16 08:35:35 +00:00
|
|
|
result = None
|
2019-07-31 19:25:30 +00:00
|
|
|
with patch("aiounifi.Controller.login", side_effect=aiounifi.Unauthorized):
|
2018-10-16 08:35:35 +00:00
|
|
|
try:
|
|
|
|
result = await controller.get_controller(hass, **CONTROLLER_DATA)
|
|
|
|
except errors.AuthenticationRequired:
|
|
|
|
pass
|
|
|
|
assert result is None
|
|
|
|
|
|
|
|
|
|
|
|
async def test_get_controller_controller_unavailable(hass):
|
|
|
|
"""Check that get_controller can handle controller being unavailable."""
|
|
|
|
import aiounifi
|
2019-07-31 19:25:30 +00:00
|
|
|
|
2018-10-16 08:35:35 +00:00
|
|
|
result = None
|
2019-07-31 19:25:30 +00:00
|
|
|
with patch("aiounifi.Controller.login", side_effect=aiounifi.RequestError):
|
2018-10-16 08:35:35 +00:00
|
|
|
try:
|
|
|
|
result = await controller.get_controller(hass, **CONTROLLER_DATA)
|
|
|
|
except errors.CannotConnect:
|
|
|
|
pass
|
|
|
|
assert result is None
|
|
|
|
|
|
|
|
|
|
|
|
async def test_get_controller_unknown_error(hass):
|
|
|
|
"""Check that get_controller can handle unkown errors."""
|
|
|
|
import aiounifi
|
2019-07-31 19:25:30 +00:00
|
|
|
|
2018-10-16 08:35:35 +00:00
|
|
|
result = None
|
2019-07-31 19:25:30 +00:00
|
|
|
with patch("aiounifi.Controller.login", side_effect=aiounifi.AiounifiException):
|
2018-10-16 08:35:35 +00:00
|
|
|
try:
|
|
|
|
result = await controller.get_controller(hass, **CONTROLLER_DATA)
|
|
|
|
except errors.AuthenticationRequired:
|
|
|
|
pass
|
|
|
|
assert result is None
|