Axis - Improve tests (#30415)

This commit is contained in:
Robert Svensson 2020-01-03 00:02:59 +01:00 committed by GitHub
parent c1936f6fe4
commit 9b961632af
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 179 additions and 326 deletions

View file

@ -1,173 +1,180 @@
"""Test Axis device."""
from unittest.mock import Mock, patch
from copy import deepcopy
from asynctest import Mock, patch
import axis as axislib
import pytest
from homeassistant.components.axis import device, errors
from homeassistant.components.axis.camera import AxisCamera
from homeassistant import config_entries
from homeassistant.components import axis
from tests.common import MockConfigEntry, mock_coro
MAC = "00408C12345"
MODEL = "model"
NAME = "name"
DEVICE_DATA = {
device.CONF_HOST: "1.2.3.4",
device.CONF_USERNAME: "username",
device.CONF_PASSWORD: "password",
device.CONF_PORT: 1234,
axis.device.CONF_HOST: "1.2.3.4",
axis.device.CONF_USERNAME: "username",
axis.device.CONF_PASSWORD: "password",
axis.device.CONF_PORT: 1234,
}
ENTRY_OPTIONS = {device.CONF_CAMERA: True, device.CONF_EVENTS: True}
ENTRY_OPTIONS = {axis.device.CONF_CAMERA: True, axis.device.CONF_EVENTS: True}
ENTRY_CONFIG = {
device.CONF_DEVICE: DEVICE_DATA,
device.CONF_MAC: "mac",
device.CONF_MODEL: "model",
device.CONF_NAME: "name",
axis.device.CONF_DEVICE: DEVICE_DATA,
axis.device.CONF_MAC: MAC,
axis.device.CONF_MODEL: MODEL,
axis.device.CONF_NAME: NAME,
}
DEFAULT_BRAND = """root.Brand.Brand=AXIS
root.Brand.ProdFullName=AXIS M1065-LW Network Camera
root.Brand.ProdNbr=M1065-LW
root.Brand.ProdShortName=AXIS M1065-LW
root.Brand.ProdType=Network Camera
root.Brand.ProdVariant=
root.Brand.WebURL=http://www.axis.com
"""
async def test_device_setup():
"""Successful setup."""
hass = Mock()
entry = Mock()
entry.data = ENTRY_CONFIG
entry.options = ENTRY_OPTIONS
api = Mock()
DEFAULT_PORTS = """root.Input.NbrOfInputs=1
root.IOPort.I0.Configurable=no
root.IOPort.I0.Direction=input
root.IOPort.I0.Input.Name=PIR sensor
root.IOPort.I0.Input.Trig=closed
root.Output.NbrOfOutputs=0
"""
axis_device = device.AxisNetworkDevice(hass, entry)
axis_device.start = Mock()
DEFAULT_PROPERTIES = """root.Properties.API.HTTP.Version=3
root.Properties.API.Metadata.Metadata=yes
root.Properties.API.Metadata.Version=1.0
root.Properties.Firmware.BuildDate=Feb 15 2019 09:42
root.Properties.Firmware.BuildNumber=26
root.Properties.Firmware.Version=9.10.1
root.Properties.Image.Format=jpeg,mjpeg,h264
root.Properties.Image.NbrOfViews=2
root.Properties.Image.Resolution=1920x1080,1280x960,1280x720,1024x768,1024x576,800x600,640x480,640x360,352x240,320x240
root.Properties.Image.Rotation=0,180
root.Properties.System.SerialNumber=ACCC12345678
"""
assert axis_device.host == DEVICE_DATA[device.CONF_HOST]
assert axis_device.model == ENTRY_CONFIG[device.CONF_MODEL]
assert axis_device.name == ENTRY_CONFIG[device.CONF_NAME]
assert axis_device.serial == ENTRY_CONFIG[device.CONF_MAC]
with patch.object(device, "get_device", return_value=mock_coro(api)):
assert await axis_device.async_setup() is True
assert axis_device.api is api
assert len(hass.config_entries.async_forward_entry_setup.mock_calls) == 3
assert hass.config_entries.async_forward_entry_setup.mock_calls[0][1] == (
entry,
"camera",
)
assert hass.config_entries.async_forward_entry_setup.mock_calls[1][1] == (
entry,
"binary_sensor",
)
assert hass.config_entries.async_forward_entry_setup.mock_calls[2][1] == (
entry,
"switch",
async def setup_axis_integration(
hass,
config=ENTRY_CONFIG,
options=ENTRY_OPTIONS,
brand=DEFAULT_BRAND,
ports=DEFAULT_PORTS,
properties=DEFAULT_PROPERTIES,
):
"""Create the Axis device."""
config_entry = config_entries.ConfigEntry(
version=1,
domain=axis.DOMAIN,
title="Mock Title",
data=deepcopy(config),
source="test",
connection_class=config_entries.CONN_CLASS_LOCAL_PUSH,
system_options={},
options=deepcopy(options),
entry_id="1",
)
def mock_request(self, method, path, json=None):
if method == "get":
if path == "/axis-cgi/param.cgi?action=list&group=root.Brand":
return brand
if path in [
"/axis-cgi/param.cgi?action=list&group=root.Input",
"/axis-cgi/param.cgi?action=list&group=root.IOPort",
"/axis-cgi/param.cgi?action=list&group=root.Output",
]:
return ports
if path == "/axis-cgi/param.cgi?action=list&group=root.Properties":
return properties
async def test_device_signal_new_address(hass):
"""Successful setup."""
entry = MockConfigEntry(
domain=device.DOMAIN, data=ENTRY_CONFIG, options=ENTRY_OPTIONS
)
return None
api = Mock()
api.vapix.get_param.return_value = "1234"
axis_device = device.AxisNetworkDevice(hass, entry)
hass.data[device.DOMAIN] = {axis_device.serial: axis_device}
with patch.object(device, "get_device", return_value=mock_coro(api)), patch.object(
AxisCamera, "_new_address"
) as new_address_mock:
await axis_device.async_setup()
await hass.async_block_till_done()
assert len(hass.states.async_all()) == 1
assert len(axis_device.listeners) == 2
entry.data[device.CONF_DEVICE][device.CONF_HOST] = "2.3.4.5"
hass.config_entries.async_update_entry(entry, data=entry.data)
with patch("axis.vapix.Vapix.request", new=mock_request), patch(
"axis.AxisDevice.start", return_value=True
):
await axis.async_setup_entry(hass, config_entry)
await hass.async_block_till_done()
assert axis_device.host == "2.3.4.5"
assert axis_device.api.config.host == "2.3.4.5"
assert len(new_address_mock.mock_calls) == 1
hass.config_entries._entries.append(config_entry)
return hass.data[axis.DOMAIN].get(config[axis.CONF_MAC])
async def test_device_setup(hass):
"""Successful setup."""
with patch(
"homeassistant.config_entries.ConfigEntries.async_forward_entry_setup",
return_value=True,
) as forward_entry_setup:
device = await setup_axis_integration(hass)
entry = device.config_entry
assert len(forward_entry_setup.mock_calls) == 3
assert forward_entry_setup.mock_calls[0][1] == (entry, "camera")
assert forward_entry_setup.mock_calls[1][1] == (entry, "binary_sensor")
assert forward_entry_setup.mock_calls[2][1] == (entry, "switch")
assert device.host == DEVICE_DATA[axis.device.CONF_HOST]
assert device.model == ENTRY_CONFIG[axis.device.CONF_MODEL]
assert device.name == ENTRY_CONFIG[axis.device.CONF_NAME]
assert device.serial == ENTRY_CONFIG[axis.device.CONF_MAC]
async def test_update_address(hass):
"""Test update address works."""
device = await setup_axis_integration(hass)
assert device.api.config.host == "1.2.3.4"
await hass.config_entries.flow.async_init(
axis.DOMAIN,
data={
"host": "2.3.4.5",
"port": 80,
"hostname": "name",
"properties": {"macaddress": MAC},
},
context={"source": "zeroconf"},
)
await hass.async_block_till_done()
assert device.api.config.host == "2.3.4.5"
async def test_device_unavailable(hass):
"""Successful setup."""
entry = MockConfigEntry(
domain=device.DOMAIN, data=ENTRY_CONFIG, options=ENTRY_OPTIONS
)
api = Mock()
api.vapix.get_param.return_value = "1234"
axis_device = device.AxisNetworkDevice(hass, entry)
hass.data[device.DOMAIN] = {axis_device.serial: axis_device}
with patch.object(device, "get_device", return_value=mock_coro(api)), patch.object(
device, "async_dispatcher_send"
) as mock_dispatcher:
await axis_device.async_setup()
await hass.async_block_till_done()
axis_device.async_connection_status_callback(status=False)
assert not axis_device.available
assert len(mock_dispatcher.mock_calls) == 1
device = await setup_axis_integration(hass)
device.async_connection_status_callback(status=False)
assert not device.available
async def test_device_reset(hass):
"""Successfully reset device."""
entry = MockConfigEntry(
domain=device.DOMAIN, data=ENTRY_CONFIG, options=ENTRY_OPTIONS
)
api = Mock()
api.vapix.get_param.return_value = "1234"
axis_device = device.AxisNetworkDevice(hass, entry)
hass.data[device.DOMAIN] = {axis_device.serial: axis_device}
with patch.object(device, "get_device", return_value=mock_coro(api)):
await axis_device.async_setup()
await hass.async_block_till_done()
await axis_device.async_reset()
assert len(api.stop.mock_calls) == 1
assert len(hass.states.async_all()) == 0
assert len(axis_device.listeners) == 0
device = await setup_axis_integration(hass)
result = await device.async_reset()
assert result is True
async def test_device_not_accessible():
async def test_device_not_accessible(hass):
"""Failed setup schedules a retry of setup."""
hass = Mock()
hass.data = dict()
entry = Mock()
entry.data = ENTRY_CONFIG
entry.options = ENTRY_OPTIONS
axis_device = device.AxisNetworkDevice(hass, entry)
with patch.object(
device, "get_device", side_effect=errors.CannotConnect
), pytest.raises(device.ConfigEntryNotReady):
await axis_device.async_setup()
assert not hass.helpers.event.async_call_later.mock_calls
axis.device, "get_device", side_effect=axis.errors.CannotConnect
), pytest.raises(axis.device.ConfigEntryNotReady):
await setup_axis_integration(hass)
assert hass.data[axis.DOMAIN] == {}
async def test_device_unknown_error():
async def test_device_unknown_error(hass):
"""Unknown errors are handled."""
hass = Mock()
entry = Mock()
entry.data = ENTRY_CONFIG
entry.options = ENTRY_OPTIONS
axis_device = device.AxisNetworkDevice(hass, entry)
with patch.object(device, "get_device", side_effect=Exception):
assert await axis_device.async_setup() is False
assert not hass.helpers.event.async_call_later.mock_calls
with patch.object(axis.device, "get_device", side_effect=Exception):
await setup_axis_integration(hass)
assert hass.data[axis.DOMAIN] == {}
async def test_new_event_sends_signal(hass):
@ -175,9 +182,9 @@ async def test_new_event_sends_signal(hass):
entry = Mock()
entry.data = ENTRY_CONFIG
axis_device = device.AxisNetworkDevice(hass, entry)
axis_device = axis.device.AxisNetworkDevice(hass, entry)
with patch.object(device, "async_dispatcher_send") as mock_dispatch_send:
with patch.object(axis.device, "async_dispatcher_send") as mock_dispatch_send:
axis_device.async_event_callback(action="add", event_id="event")
await hass.async_block_till_done()
@ -191,7 +198,7 @@ async def test_shutdown():
entry = Mock()
entry.data = ENTRY_CONFIG
axis_device = device.AxisNetworkDevice(hass, entry)
axis_device = axis.device.AxisNetworkDevice(hass, entry)
axis_device.api = Mock()
axis_device.shutdown(None)
@ -199,39 +206,25 @@ async def test_shutdown():
assert len(axis_device.api.stop.mock_calls) == 1
async def test_get_device(hass):
"""Successful call."""
with patch("axis.param_cgi.Params.update_brand", return_value=mock_coro()), patch(
"axis.param_cgi.Params.update_properties", return_value=mock_coro()
), patch("axis.port_cgi.Ports.update", return_value=mock_coro()):
assert await device.get_device(hass, DEVICE_DATA)
async def test_get_device_fails(hass):
"""Device unauthorized yields authentication required error."""
import axis
with patch(
"axis.param_cgi.Params.update_brand", side_effect=axis.Unauthorized
), pytest.raises(errors.AuthenticationRequired):
await device.get_device(hass, DEVICE_DATA)
"axis.param_cgi.Params.update_brand", side_effect=axislib.Unauthorized
), pytest.raises(axis.errors.AuthenticationRequired):
await axis.device.get_device(hass, DEVICE_DATA)
async def test_get_device_device_unavailable(hass):
"""Device unavailable yields cannot connect error."""
import axis
with patch(
"axis.param_cgi.Params.update_brand", side_effect=axis.RequestError
), pytest.raises(errors.CannotConnect):
await device.get_device(hass, DEVICE_DATA)
"axis.param_cgi.Params.update_brand", side_effect=axislib.RequestError
), pytest.raises(axis.errors.CannotConnect):
await axis.device.get_device(hass, DEVICE_DATA)
async def test_get_device_unknown_error(hass):
"""Device yield unknown error."""
import axis
with patch(
"axis.param_cgi.Params.update_brand", side_effect=axis.AxisException
), pytest.raises(errors.AuthenticationRequired):
await device.get_device(hass, DEVICE_DATA)
"axis.param_cgi.Params.update_brand", side_effect=axislib.AxisException
), pytest.raises(axis.errors.AuthenticationRequired):
await axis.device.get_device(hass, DEVICE_DATA)