2019-03-24 15:16:50 +00:00
""" Test Axis device. """
2020-01-02 23:02:59 +00:00
from copy import deepcopy
2020-05-25 21:13:34 +00:00
from unittest import mock
2021-01-13 13:03:54 +00:00
from unittest . mock import Mock , patch
2019-03-24 15:16:50 +00:00
2020-01-02 23:02:59 +00:00
import axis as axislib
2019-03-24 15:16:50 +00:00
import pytest
2021-01-13 13:03:54 +00:00
import respx
2019-03-24 15:16:50 +00:00
2021-11-30 20:15:34 +00:00
from homeassistant . components import axis , zeroconf
2022-03-29 09:11:58 +00:00
from homeassistant . components . axis . const import CONF_EVENTS , DOMAIN as AXIS_DOMAIN
2020-05-25 21:13:34 +00:00
from homeassistant . components . binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN
2020-10-22 07:29:53 +00:00
from homeassistant . config_entries import SOURCE_ZEROCONF
2020-05-14 08:49:27 +00:00
from homeassistant . const import (
CONF_HOST ,
2022-03-29 09:11:58 +00:00
CONF_MODEL ,
2020-05-14 08:49:27 +00:00
CONF_NAME ,
CONF_PASSWORD ,
CONF_PORT ,
CONF_USERNAME ,
2021-04-09 08:56:53 +00:00
STATE_OFF ,
2020-10-22 07:29:53 +00:00
STATE_ON ,
2021-04-09 08:56:53 +00:00
STATE_UNAVAILABLE ,
2020-05-14 08:49:27 +00:00
)
2021-10-22 09:09:50 +00:00
from homeassistant . helpers import device_registry as dr
2019-03-24 15:16:50 +00:00
2020-06-22 21:59:50 +00:00
from tests . common import MockConfigEntry , async_fire_mqtt_message
2020-01-03 12:27:14 +00:00
2021-01-16 00:01:14 +00:00
MAC = " 00408C123456 "
FORMATTED_MAC = " 00:40:8c:12:34:56 "
2020-01-02 23:02:59 +00:00
MODEL = " model "
NAME = " name "
2019-12-08 14:44:04 +00:00
2021-01-13 13:03:54 +00:00
DEFAULT_HOST = " 1.2.3.4 "
2020-06-04 12:25:50 +00:00
ENTRY_OPTIONS = { CONF_EVENTS : True }
2019-03-24 15:16:50 +00:00
ENTRY_CONFIG = {
2021-01-13 13:03:54 +00:00
CONF_HOST : DEFAULT_HOST ,
2020-06-01 16:45:38 +00:00
CONF_USERNAME : " root " ,
CONF_PASSWORD : " pass " ,
2020-05-14 08:49:27 +00:00
CONF_PORT : 80 ,
CONF_MODEL : MODEL ,
CONF_NAME : NAME ,
2019-03-24 15:16:50 +00:00
}
2020-05-31 18:00:15 +00:00
API_DISCOVERY_RESPONSE = {
2020-05-25 21:13:34 +00:00
" method " : " getApiList " ,
" apiVersion " : " 1.0 " ,
" data " : {
" apiList " : [
{ " id " : " api-discovery " , " version " : " 1.0 " , " name " : " API Discovery Service " } ,
{ " id " : " param-cgi " , " version " : " 1.0 " , " name " : " Legacy Parameter Handling " } ,
]
} ,
}
2020-05-31 18:00:15 +00:00
API_DISCOVERY_BASIC_DEVICE_INFO = {
" id " : " basic-device-info " ,
" version " : " 1.1 " ,
" name " : " Basic Device Information " ,
}
API_DISCOVERY_MQTT = { " id " : " mqtt-client " , " version " : " 1.0 " , " name " : " MQTT Client API " }
API_DISCOVERY_PORT_MANAGEMENT = {
" id " : " io-port-management " ,
" version " : " 1.0 " ,
" name " : " IO Port Management " ,
}
2020-09-06 21:26:06 +00:00
APPLICATIONS_LIST_RESPONSE = """ <reply result= " ok " >
< application Name = " vmd " NiceName = " AXIS Video Motion Detection " Vendor = " Axis Communications " Version = " 4.2-0 " ApplicationID = " 143440 " License = " None " Status = " Running " ConfigurationPage = " local/vmd/config.html " VendorHomePage = " http://www.axis.com " / >
< / reply > """
2020-05-31 18:00:15 +00:00
BASIC_DEVICE_INFO_RESPONSE = {
" apiVersion " : " 1.1 " ,
" data " : {
" propertyList " : {
" ProdNbr " : " M1065-LW " ,
" ProdType " : " Network Camera " ,
2021-01-16 00:01:14 +00:00
" SerialNumber " : MAC ,
2020-05-31 18:00:15 +00:00
" Version " : " 9.80.1 " ,
}
} ,
}
2020-06-18 21:27:08 +00:00
LIGHT_CONTROL_RESPONSE = {
" apiVersion " : " 1.1 " ,
" method " : " getLightInformation " ,
" data " : {
" items " : [
{
" lightID " : " led0 " ,
" lightType " : " IR " ,
" enabled " : True ,
" synchronizeDayNightMode " : True ,
" lightState " : False ,
" automaticIntensityMode " : False ,
" automaticAngleOfIlluminationMode " : False ,
" nrOfLEDs " : 1 ,
" error " : False ,
" errorInfo " : " " ,
}
]
} ,
}
2020-05-31 18:00:15 +00:00
MQTT_CLIENT_RESPONSE = {
" apiVersion " : " 1.0 " ,
" context " : " some context " ,
" method " : " getClientStatus " ,
" data " : { " status " : { " state " : " active " , " connectionStatus " : " Connected " } } ,
}
PORT_MANAGEMENT_RESPONSE = {
" apiVersion " : " 1.0 " ,
" method " : " getPorts " ,
" data " : {
" numberOfPorts " : 1 ,
" items " : [
{
" port " : " 0 " ,
" configurable " : False ,
" usage " : " " ,
" name " : " PIR sensor " ,
" direction " : " input " ,
" state " : " open " ,
" normalState " : " open " ,
}
] ,
} ,
}
2020-09-06 21:26:06 +00:00
VMD4_RESPONSE = {
" apiVersion " : " 1.4 " ,
" method " : " getConfiguration " ,
" context " : " Axis library " ,
" data " : {
" cameras " : [ { " id " : 1 , " rotation " : 0 , " active " : True } ] ,
" profiles " : [
{ " filters " : [ ] , " camera " : 1 , " triggers " : [ ] , " name " : " Profile 1 " , " uid " : 1 }
] ,
} ,
}
2020-05-31 18:00:15 +00:00
BRAND_RESPONSE = """ root.Brand.Brand=AXIS
2020-01-02 23:02:59 +00:00
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
"""
2021-01-13 13:03:54 +00:00
IMAGE_RESPONSE = """ root.Image.I0.Enabled=yes
root . Image . I0 . Name = View Area 1
root . Image . I0 . Source = 0
root . Image . I1 . Enabled = no
root . Image . I1 . Name = View Area 2
root . Image . I1 . Source = 0
"""
2020-05-31 18:00:15 +00:00
PORTS_RESPONSE = """ root.Input.NbrOfInputs=1
2020-01-02 23:02:59 +00:00
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
"""
2021-01-16 00:01:14 +00:00
PROPERTIES_RESPONSE = f """ root.Properties.API.HTTP.Version=3
2020-01-02 23:02:59 +00:00
root . Properties . API . Metadata . Metadata = yes
root . Properties . API . Metadata . Version = 1.0
2020-09-06 21:26:06 +00:00
root . Properties . EmbeddedDevelopment . Version = 2.16
2020-01-02 23:02:59 +00:00
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 = 1920 x1080 , 1280 x960 , 1280 x720 , 1024 x768 , 1024 x576 , 800 x600 , 640 x480 , 640 x360 , 352 x240 , 320 x240
root . Properties . Image . Rotation = 0 , 180
2021-01-16 00:01:14 +00:00
root . Properties . System . SerialNumber = { MAC }
2020-01-02 23:02:59 +00:00
"""
2021-01-13 13:03:54 +00:00
PTZ_RESPONSE = " "
2020-06-01 16:45:38 +00:00
STREAM_PROFILES_RESPONSE = """ root.StreamProfile.MaxGroups=26
root . StreamProfile . S0 . Description = profile_1_description
root . StreamProfile . S0 . Name = profile_1
root . StreamProfile . S0 . Parameters = videocodec = h264
root . StreamProfile . S1 . Description = profile_2_description
root . StreamProfile . S1 . Name = profile_2
root . StreamProfile . S1 . Parameters = videocodec = h265
"""
2021-01-13 13:03:54 +00:00
VIEW_AREAS_RESPONSE = { " apiVersion " : " 1.0 " , " method " : " list " , " data " : { " viewAreas " : [ ] } }
2020-01-02 23:02:59 +00:00
2021-01-13 13:03:54 +00:00
def mock_default_vapix_requests ( respx : respx , host : str = DEFAULT_HOST ) - > None :
""" Mock default Vapix requests responses. """
respx . post ( f " http:// { host } :80/axis-cgi/apidiscovery.cgi " ) . respond (
json = API_DISCOVERY_RESPONSE ,
)
respx . post ( f " http:// { host } :80/axis-cgi/basicdeviceinfo.cgi " ) . respond (
json = BASIC_DEVICE_INFO_RESPONSE ,
)
respx . post ( f " http:// { host } :80/axis-cgi/io/portmanagement.cgi " ) . respond (
json = PORT_MANAGEMENT_RESPONSE ,
)
respx . post ( f " http:// { host } :80/axis-cgi/lightcontrol.cgi " ) . respond (
json = LIGHT_CONTROL_RESPONSE ,
)
respx . post ( f " http:// { host } :80/axis-cgi/mqtt/client.cgi " ) . respond (
json = MQTT_CLIENT_RESPONSE ,
)
respx . post ( f " http:// { host } :80/axis-cgi/streamprofile.cgi " ) . respond (
json = STREAM_PROFILES_RESPONSE ,
)
respx . post ( f " http:// { host } :80/axis-cgi/viewarea/info.cgi " ) . respond (
json = VIEW_AREAS_RESPONSE
)
respx . get (
f " http:// { host } :80/axis-cgi/param.cgi?action=list&group=root.Brand "
) . respond (
text = BRAND_RESPONSE ,
headers = { " Content-Type " : " text/plain " } ,
)
respx . get (
f " http:// { host } :80/axis-cgi/param.cgi?action=list&group=root.Image "
) . respond (
text = IMAGE_RESPONSE ,
headers = { " Content-Type " : " text/plain " } ,
)
respx . get (
f " http:// { host } :80/axis-cgi/param.cgi?action=list&group=root.Input "
) . respond (
text = PORTS_RESPONSE ,
headers = { " Content-Type " : " text/plain " } ,
)
respx . get (
f " http:// { host } :80/axis-cgi/param.cgi?action=list&group=root.IOPort "
) . respond (
text = PORTS_RESPONSE ,
headers = { " Content-Type " : " text/plain " } ,
)
respx . get (
f " http:// { host } :80/axis-cgi/param.cgi?action=list&group=root.Output "
) . respond (
text = PORTS_RESPONSE ,
headers = { " Content-Type " : " text/plain " } ,
)
respx . get (
f " http:// { host } :80/axis-cgi/param.cgi?action=list&group=root.Properties "
) . respond (
text = PROPERTIES_RESPONSE ,
headers = { " Content-Type " : " text/plain " } ,
)
respx . get (
f " http:// { host } :80/axis-cgi/param.cgi?action=list&group=root.PTZ "
) . respond (
text = PTZ_RESPONSE ,
headers = { " Content-Type " : " text/plain " } ,
)
respx . get (
f " http:// { host } :80/axis-cgi/param.cgi?action=list&group=root.StreamProfile "
) . respond (
text = STREAM_PROFILES_RESPONSE ,
headers = { " Content-Type " : " text/plain " } ,
)
respx . post ( f " http:// { host } :80/axis-cgi/applications/list.cgi " ) . respond (
text = APPLICATIONS_LIST_RESPONSE ,
headers = { " Content-Type " : " text/xml " } ,
)
respx . post ( f " http:// { host } :80/local/vmd/control.cgi " ) . respond ( json = VMD4_RESPONSE )
2020-05-31 18:00:15 +00:00
2023-01-13 16:12:51 +00:00
async def setup_axis_integration (
hass , config = ENTRY_CONFIG , options = ENTRY_OPTIONS , entry_version = 3
) :
2020-01-02 23:02:59 +00:00
""" Create the Axis device. """
2020-01-03 12:27:14 +00:00
config_entry = MockConfigEntry (
2020-05-14 08:49:27 +00:00
domain = AXIS_DOMAIN ,
2020-01-02 23:02:59 +00:00
data = deepcopy ( config ) ,
options = deepcopy ( options ) ,
2023-01-13 16:12:51 +00:00
version = entry_version ,
2021-01-16 00:01:14 +00:00
unique_id = FORMATTED_MAC ,
2020-01-02 23:02:59 +00:00
)
2020-01-03 12:27:14 +00:00
config_entry . add_to_hass ( hass )
2021-04-09 08:56:53 +00:00
with respx . mock :
2021-01-13 13:03:54 +00:00
mock_default_vapix_requests ( respx )
2020-01-03 12:27:14 +00:00
await hass . config_entries . async_setup ( config_entry . entry_id )
2020-05-25 21:13:34 +00:00
await hass . async_block_till_done ( )
2019-03-24 15:16:50 +00:00
2020-10-22 07:29:53 +00:00
return config_entry
2019-03-24 15:16:50 +00:00
2020-01-02 23:02:59 +00:00
async def test_device_setup ( hass ) :
2019-04-02 18:13:11 +00:00
""" Successful setup. """
2020-01-02 23:02:59 +00:00
with patch (
" homeassistant.config_entries.ConfigEntries.async_forward_entry_setup " ,
return_value = True ,
) as forward_entry_setup :
2020-10-22 07:29:53 +00:00
config_entry = await setup_axis_integration ( hass )
2023-01-13 21:21:40 +00:00
device = hass . data [ AXIS_DOMAIN ] [ config_entry . entry_id ]
2020-01-02 23:02:59 +00:00
2020-05-31 18:00:15 +00:00
assert device . api . vapix . firmware_version == " 9.10.1 "
assert device . api . vapix . product_number == " M1065-LW "
assert device . api . vapix . product_type == " Network Camera "
2021-01-16 00:01:14 +00:00
assert device . api . vapix . serial_number == " 00408C123456 "
2020-05-31 18:00:15 +00:00
2020-06-18 21:27:08 +00:00
assert len ( forward_entry_setup . mock_calls ) == 4
2023-01-13 21:21:40 +00:00
assert forward_entry_setup . mock_calls [ 0 ] [ 1 ] == ( config_entry , " binary_sensor " )
assert forward_entry_setup . mock_calls [ 1 ] [ 1 ] == ( config_entry , " camera " )
assert forward_entry_setup . mock_calls [ 2 ] [ 1 ] == ( config_entry , " light " )
assert forward_entry_setup . mock_calls [ 3 ] [ 1 ] == ( config_entry , " switch " )
2020-01-02 23:02:59 +00:00
2020-05-14 08:49:27 +00:00
assert device . host == ENTRY_CONFIG [ CONF_HOST ]
assert device . model == ENTRY_CONFIG [ CONF_MODEL ]
assert device . name == ENTRY_CONFIG [ CONF_NAME ]
2021-01-16 00:01:14 +00:00
assert device . unique_id == FORMATTED_MAC
2020-01-02 23:02:59 +00:00
2021-10-22 09:09:50 +00:00
device_registry = dr . async_get ( hass )
device_entry = device_registry . async_get_device (
identifiers = { ( AXIS_DOMAIN , device . unique_id ) }
)
assert device_entry . configuration_url == device . api . config . url
2020-01-02 23:02:59 +00:00
2020-05-31 18:00:15 +00:00
async def test_device_info ( hass ) :
""" Verify other path of device information works. """
api_discovery = deepcopy ( API_DISCOVERY_RESPONSE )
api_discovery [ " data " ] [ " apiList " ] . append ( API_DISCOVERY_BASIC_DEVICE_INFO )
with patch . dict ( API_DISCOVERY_RESPONSE , api_discovery ) :
2020-10-22 07:29:53 +00:00
config_entry = await setup_axis_integration ( hass )
2023-01-13 21:21:40 +00:00
device = hass . data [ AXIS_DOMAIN ] [ config_entry . entry_id ]
2020-05-31 18:00:15 +00:00
assert device . api . vapix . firmware_version == " 9.80.1 "
assert device . api . vapix . product_number == " M1065-LW "
assert device . api . vapix . product_type == " Network Camera "
2021-01-16 00:01:14 +00:00
assert device . api . vapix . serial_number == " 00408C123456 "
2020-05-31 18:00:15 +00:00
2020-06-22 21:59:50 +00:00
async def test_device_support_mqtt ( hass , mqtt_mock ) :
2020-05-25 21:13:34 +00:00
""" Successful setup. """
2020-05-31 18:00:15 +00:00
api_discovery = deepcopy ( API_DISCOVERY_RESPONSE )
api_discovery [ " data " ] [ " apiList " ] . append ( API_DISCOVERY_MQTT )
2020-05-25 21:13:34 +00:00
2020-05-31 18:00:15 +00:00
with patch . dict ( API_DISCOVERY_RESPONSE , api_discovery ) :
await setup_axis_integration ( hass )
2020-05-25 21:13:34 +00:00
2020-06-22 21:59:50 +00:00
mqtt_mock . async_subscribe . assert_called_with ( f " { MAC } /# " , mock . ANY , 0 , " utf-8 " )
2020-05-25 21:13:34 +00:00
topic = f " { MAC } /event/tns:onvif/Device/tns:axis/Sensor/PIR/$source/sensor/0 "
message = b ' { " timestamp " : 1590258472044, " topic " : " onvif:Device/axis:Sensor/PIR " , " message " : { " source " : { " sensor " : " 0 " }, " key " : {} , " data " : { " state " : " 1 " }}} '
assert len ( hass . states . async_entity_ids ( BINARY_SENSOR_DOMAIN ) ) == 0
async_fire_mqtt_message ( hass , topic , message )
await hass . async_block_till_done ( )
assert len ( hass . states . async_entity_ids ( BINARY_SENSOR_DOMAIN ) ) == 1
2020-10-22 07:29:53 +00:00
pir = hass . states . get ( f " { BINARY_SENSOR_DOMAIN } . { NAME } _pir_0 " )
assert pir . state == STATE_ON
2020-05-25 21:13:34 +00:00
assert pir . name == f " { NAME } PIR 0 "
2020-01-02 23:02:59 +00:00
async def test_update_address ( hass ) :
""" Test update address works. """
2020-10-22 07:29:53 +00:00
config_entry = await setup_axis_integration ( hass )
2023-01-13 21:21:40 +00:00
device = hass . data [ AXIS_DOMAIN ] [ config_entry . entry_id ]
2020-01-02 23:02:59 +00:00
assert device . api . config . host == " 1.2.3.4 "
2021-01-13 13:03:54 +00:00
with patch (
2020-08-27 11:56:20 +00:00
" homeassistant.components.axis.async_setup_entry " ,
return_value = True ,
2021-01-13 13:03:54 +00:00
) as mock_setup_entry , respx . mock :
mock_default_vapix_requests ( respx , " 2.3.4.5 " )
2020-08-08 18:23:56 +00:00
await hass . config_entries . flow . async_init (
AXIS_DOMAIN ,
2021-11-30 20:15:34 +00:00
data = zeroconf . ZeroconfServiceInfo (
host = " 2.3.4.5 " ,
2022-02-11 22:46:17 +00:00
addresses = [ " 2.3.4.5 " ] ,
2021-11-30 20:15:34 +00:00
hostname = " mock_hostname " ,
name = " name " ,
port = 80 ,
properties = { " macaddress " : MAC } ,
type = " mock_type " ,
) ,
2020-10-22 07:29:53 +00:00
context = { " source " : SOURCE_ZEROCONF } ,
2020-08-08 18:23:56 +00:00
)
await hass . async_block_till_done ( )
2019-04-02 18:13:11 +00:00
2020-01-02 23:02:59 +00:00
assert device . api . config . host == " 2.3.4.5 "
2020-08-08 18:23:56 +00:00
assert len ( mock_setup_entry . mock_calls ) == 1
2019-04-02 18:13:11 +00:00
2021-04-09 08:56:53 +00:00
async def test_device_unavailable ( hass , mock_rtsp_event , mock_rtsp_signal_state ) :
2019-04-15 22:06:45 +00:00
""" Successful setup. """
2021-04-09 08:56:53 +00:00
await setup_axis_integration ( hass )
# Provide an entity that can be used to verify connection state on
mock_rtsp_event (
topic = " tns1:AudioSource/tnsaxis:TriggerLevel " ,
data_type = " triggered " ,
data_value = " 10 " ,
source_name = " channel " ,
source_idx = " 1 " ,
)
await hass . async_block_till_done ( )
assert hass . states . get ( f " { BINARY_SENSOR_DOMAIN } . { NAME } _sound_1 " ) . state == STATE_OFF
# Connection to device has failed
mock_rtsp_signal_state ( connected = False )
await hass . async_block_till_done ( )
assert (
hass . states . get ( f " { BINARY_SENSOR_DOMAIN } . { NAME } _sound_1 " ) . state
== STATE_UNAVAILABLE
)
# Connection to device has been restored
mock_rtsp_signal_state ( connected = True )
await hass . async_block_till_done ( )
assert hass . states . get ( f " { BINARY_SENSOR_DOMAIN } . { NAME } _sound_1 " ) . state == STATE_OFF
2019-04-15 22:06:45 +00:00
async def test_device_reset ( hass ) :
""" Successfully reset device. """
2020-10-22 07:29:53 +00:00
config_entry = await setup_axis_integration ( hass )
2023-01-13 21:21:40 +00:00
device = hass . data [ AXIS_DOMAIN ] [ config_entry . entry_id ]
2020-01-02 23:02:59 +00:00
result = await device . async_reset ( )
assert result is True
2019-04-15 22:06:45 +00:00
2020-01-02 23:02:59 +00:00
async def test_device_not_accessible ( hass ) :
2019-03-24 15:16:50 +00:00
""" Failed setup schedules a retry of setup. """
2022-07-28 09:41:03 +00:00
with patch . object ( axis , " get_axis_device " , side_effect = axis . errors . CannotConnect ) :
2020-01-02 23:02:59 +00:00
await setup_axis_integration ( hass )
2020-05-14 08:49:27 +00:00
assert hass . data [ AXIS_DOMAIN ] == { }
2019-03-24 15:16:50 +00:00
2021-01-21 11:56:04 +00:00
async def test_device_trigger_reauth_flow ( hass ) :
""" Failed authentication trigger a reauthentication flow. """
with patch . object (
2022-07-28 09:41:03 +00:00
axis , " get_axis_device " , side_effect = axis . errors . AuthenticationRequired
2021-01-21 11:56:04 +00:00
) , patch . object ( hass . config_entries . flow , " async_init " ) as mock_flow_init :
await setup_axis_integration ( hass )
mock_flow_init . assert_called_once ( )
assert hass . data [ AXIS_DOMAIN ] == { }
2020-01-02 23:02:59 +00:00
async def test_device_unknown_error ( hass ) :
2019-03-24 15:16:50 +00:00
""" Unknown errors are handled. """
2022-07-28 09:41:03 +00:00
with patch . object ( axis , " get_axis_device " , side_effect = Exception ) :
2020-01-02 23:02:59 +00:00
await setup_axis_integration ( hass )
2020-05-14 08:49:27 +00:00
assert hass . data [ AXIS_DOMAIN ] == { }
2019-03-24 15:16:50 +00:00
async def test_shutdown ( ) :
""" Successful shutdown. """
hass = Mock ( )
entry = Mock ( )
entry . data = ENTRY_CONFIG
2022-07-28 09:41:03 +00:00
axis_device = axis . device . AxisNetworkDevice ( hass , entry , Mock ( ) )
2019-03-24 15:16:50 +00:00
2020-10-20 07:31:04 +00:00
await axis_device . shutdown ( None )
2019-03-24 15:16:50 +00:00
2020-05-25 21:13:34 +00:00
assert len ( axis_device . api . stream . stop . mock_calls ) == 1
2019-03-24 15:16:50 +00:00
async def test_get_device_fails ( hass ) :
""" Device unauthorized yields authentication required error. """
2019-07-31 19:25:30 +00:00
with patch (
2023-01-02 17:14:14 +00:00
" axis.vapix.vapix.Vapix.request " , side_effect = axislib . Unauthorized
2020-01-02 23:02:59 +00:00
) , pytest . raises ( axis . errors . AuthenticationRequired ) :
2022-07-28 09:41:03 +00:00
await axis . device . get_axis_device ( hass , ENTRY_CONFIG )
2019-03-24 15:16:50 +00:00
async def test_get_device_device_unavailable ( hass ) :
""" Device unavailable yields cannot connect error. """
2019-07-31 19:25:30 +00:00
with patch (
2023-01-02 17:14:14 +00:00
" axis.vapix.vapix.Vapix.request " , side_effect = axislib . RequestError
2020-01-02 23:02:59 +00:00
) , pytest . raises ( axis . errors . CannotConnect ) :
2022-07-28 09:41:03 +00:00
await axis . device . get_axis_device ( hass , ENTRY_CONFIG )
2019-03-24 15:16:50 +00:00
async def test_get_device_unknown_error ( hass ) :
""" Device yield unknown error. """
2019-07-31 19:25:30 +00:00
with patch (
2023-01-02 17:14:14 +00:00
" axis.vapix.vapix.Vapix.request " , side_effect = axislib . AxisException
2020-01-02 23:02:59 +00:00
) , pytest . raises ( axis . errors . AuthenticationRequired ) :
2022-07-28 09:41:03 +00:00
await axis . device . get_axis_device ( hass , ENTRY_CONFIG )