214 lines
6.7 KiB
Python
214 lines
6.7 KiB
Python
"""The tests for the UniFi Network update platform."""
|
|
from copy import deepcopy
|
|
|
|
from aiounifi.models.message import MessageKey
|
|
from aiounifi.websocket import WebsocketState
|
|
from yarl import URL
|
|
|
|
from homeassistant.components.unifi.const import CONF_SITE_ID
|
|
from homeassistant.components.update import (
|
|
ATTR_IN_PROGRESS,
|
|
ATTR_INSTALLED_VERSION,
|
|
ATTR_LATEST_VERSION,
|
|
DOMAIN as UPDATE_DOMAIN,
|
|
SERVICE_INSTALL,
|
|
UpdateDeviceClass,
|
|
UpdateEntityFeature,
|
|
)
|
|
from homeassistant.const import (
|
|
ATTR_DEVICE_CLASS,
|
|
ATTR_ENTITY_ID,
|
|
ATTR_SUPPORTED_FEATURES,
|
|
CONF_HOST,
|
|
STATE_OFF,
|
|
STATE_ON,
|
|
STATE_UNAVAILABLE,
|
|
)
|
|
from homeassistant.core import HomeAssistant
|
|
|
|
from .test_controller import DESCRIPTION, setup_unifi_integration
|
|
|
|
from tests.test_util.aiohttp import AiohttpClientMocker
|
|
|
|
DEVICE_1 = {
|
|
"board_rev": 3,
|
|
"device_id": "mock-id",
|
|
"ip": "10.0.1.1",
|
|
"last_seen": 1562600145,
|
|
"mac": "00:00:00:00:01:01",
|
|
"model": "US16P150",
|
|
"name": "Device 1",
|
|
"next_interval": 20,
|
|
"state": 1,
|
|
"type": "usw",
|
|
"upgradable": True,
|
|
"version": "4.0.42.10433",
|
|
"upgrade_to_firmware": "4.3.17.11279",
|
|
}
|
|
|
|
DEVICE_2 = {
|
|
"board_rev": 3,
|
|
"device_id": "mock-id",
|
|
"ip": "10.0.1.2",
|
|
"mac": "00:00:00:00:01:02",
|
|
"model": "US16P150",
|
|
"name": "Device 2",
|
|
"next_interval": 20,
|
|
"state": 0,
|
|
"type": "usw",
|
|
"version": "4.0.42.10433",
|
|
}
|
|
|
|
|
|
async def test_no_entities(
|
|
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
|
) -> None:
|
|
"""Test the update_clients function when no clients are found."""
|
|
await setup_unifi_integration(hass, aioclient_mock)
|
|
|
|
assert len(hass.states.async_entity_ids(UPDATE_DOMAIN)) == 0
|
|
|
|
|
|
async def test_device_updates(
|
|
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker, mock_unifi_websocket
|
|
) -> None:
|
|
"""Test the update_items function with some devices."""
|
|
device_1 = deepcopy(DEVICE_1)
|
|
await setup_unifi_integration(
|
|
hass,
|
|
aioclient_mock,
|
|
devices_response=[device_1, DEVICE_2],
|
|
)
|
|
|
|
assert len(hass.states.async_entity_ids(UPDATE_DOMAIN)) == 2
|
|
|
|
device_1_state = hass.states.get("update.device_1")
|
|
assert device_1_state.state == STATE_ON
|
|
assert device_1_state.attributes[ATTR_INSTALLED_VERSION] == "4.0.42.10433"
|
|
assert device_1_state.attributes[ATTR_LATEST_VERSION] == "4.3.17.11279"
|
|
assert device_1_state.attributes[ATTR_IN_PROGRESS] is False
|
|
assert device_1_state.attributes[ATTR_DEVICE_CLASS] == UpdateDeviceClass.FIRMWARE
|
|
assert (
|
|
device_1_state.attributes[ATTR_SUPPORTED_FEATURES]
|
|
== UpdateEntityFeature.PROGRESS | UpdateEntityFeature.INSTALL
|
|
)
|
|
|
|
device_2_state = hass.states.get("update.device_2")
|
|
assert device_2_state.state == STATE_OFF
|
|
assert device_2_state.attributes[ATTR_INSTALLED_VERSION] == "4.0.42.10433"
|
|
assert device_2_state.attributes[ATTR_LATEST_VERSION] == "4.0.42.10433"
|
|
assert device_2_state.attributes[ATTR_IN_PROGRESS] is False
|
|
assert device_2_state.attributes[ATTR_DEVICE_CLASS] == UpdateDeviceClass.FIRMWARE
|
|
assert (
|
|
device_2_state.attributes[ATTR_SUPPORTED_FEATURES]
|
|
== UpdateEntityFeature.PROGRESS | UpdateEntityFeature.INSTALL
|
|
)
|
|
|
|
# Simulate start of update
|
|
|
|
device_1["state"] = 4
|
|
mock_unifi_websocket(message=MessageKey.DEVICE, data=device_1)
|
|
await hass.async_block_till_done()
|
|
|
|
device_1_state = hass.states.get("update.device_1")
|
|
assert device_1_state.state == STATE_ON
|
|
assert device_1_state.attributes[ATTR_INSTALLED_VERSION] == "4.0.42.10433"
|
|
assert device_1_state.attributes[ATTR_LATEST_VERSION] == "4.3.17.11279"
|
|
assert device_1_state.attributes[ATTR_IN_PROGRESS] is True
|
|
|
|
# Simulate update finished
|
|
|
|
device_1["state"] = "0"
|
|
device_1["version"] = "4.3.17.11279"
|
|
device_1["upgradable"] = False
|
|
del device_1["upgrade_to_firmware"]
|
|
mock_unifi_websocket(message=MessageKey.DEVICE, data=device_1)
|
|
await hass.async_block_till_done()
|
|
|
|
device_1_state = hass.states.get("update.device_1")
|
|
assert device_1_state.state == STATE_OFF
|
|
assert device_1_state.attributes[ATTR_INSTALLED_VERSION] == "4.3.17.11279"
|
|
assert device_1_state.attributes[ATTR_LATEST_VERSION] == "4.3.17.11279"
|
|
assert device_1_state.attributes[ATTR_IN_PROGRESS] is False
|
|
|
|
|
|
async def test_not_admin(
|
|
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
|
) -> None:
|
|
"""Test that the INSTALL feature is not available on a non-admin account."""
|
|
description = deepcopy(DESCRIPTION)
|
|
description[0]["site_role"] = "not admin"
|
|
|
|
await setup_unifi_integration(
|
|
hass,
|
|
aioclient_mock,
|
|
site_description=description,
|
|
devices_response=[DEVICE_1],
|
|
)
|
|
|
|
assert len(hass.states.async_entity_ids(UPDATE_DOMAIN)) == 1
|
|
device_state = hass.states.get("update.device_1")
|
|
assert device_state.state == STATE_ON
|
|
assert (
|
|
device_state.attributes[ATTR_SUPPORTED_FEATURES] == UpdateEntityFeature.PROGRESS
|
|
)
|
|
|
|
|
|
async def test_install(
|
|
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
|
) -> None:
|
|
"""Test the device update install call."""
|
|
config_entry = await setup_unifi_integration(
|
|
hass, aioclient_mock, devices_response=[DEVICE_1]
|
|
)
|
|
|
|
assert len(hass.states.async_entity_ids(UPDATE_DOMAIN)) == 1
|
|
device_state = hass.states.get("update.device_1")
|
|
assert device_state.state == STATE_ON
|
|
|
|
url = f"https://{config_entry.data[CONF_HOST]}:1234/api/s/{config_entry.data[CONF_SITE_ID]}/cmd/devmgr"
|
|
aioclient_mock.clear_requests()
|
|
aioclient_mock.post(url)
|
|
|
|
await hass.services.async_call(
|
|
UPDATE_DOMAIN,
|
|
SERVICE_INSTALL,
|
|
{ATTR_ENTITY_ID: "update.device_1"},
|
|
blocking=True,
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert aioclient_mock.call_count == 1
|
|
assert aioclient_mock.mock_calls[0] == (
|
|
"post",
|
|
URL(url),
|
|
{"cmd": "upgrade", "mac": "00:00:00:00:01:01"},
|
|
{},
|
|
)
|
|
|
|
|
|
async def test_controller_state_change(
|
|
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker, mock_unifi_websocket
|
|
) -> None:
|
|
"""Verify entities state reflect on controller becoming unavailable."""
|
|
await setup_unifi_integration(
|
|
hass,
|
|
aioclient_mock,
|
|
devices_response=[DEVICE_1],
|
|
)
|
|
|
|
assert len(hass.states.async_entity_ids(UPDATE_DOMAIN)) == 1
|
|
assert hass.states.get("update.device_1").state == STATE_ON
|
|
|
|
# Controller unavailable
|
|
mock_unifi_websocket(state=WebsocketState.DISCONNECTED)
|
|
await hass.async_block_till_done()
|
|
|
|
assert hass.states.get("update.device_1").state == STATE_UNAVAILABLE
|
|
|
|
# Controller available
|
|
mock_unifi_websocket(state=WebsocketState.RUNNING)
|
|
await hass.async_block_till_done()
|
|
|
|
assert hass.states.get("update.device_1").state == STATE_ON
|