mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 21:27:38 +00:00
Axis improve coverage binary tests (#111758)
* Parametrize binary sensor tests * Add test coverage to the different *guard apps * Add object analytics tests
This commit is contained in:
parent
224f6dbdbb
commit
458391ee2b
@ -21,6 +21,8 @@ from homeassistant.const import (
|
|||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
API_DISCOVERY_RESPONSE,
|
API_DISCOVERY_RESPONSE,
|
||||||
|
APP_AOA_RESPONSE,
|
||||||
|
APP_VMD4_RESPONSE,
|
||||||
APPLICATIONS_LIST_RESPONSE,
|
APPLICATIONS_LIST_RESPONSE,
|
||||||
BASIC_DEVICE_INFO_RESPONSE,
|
BASIC_DEVICE_INFO_RESPONSE,
|
||||||
BRAND_RESPONSE,
|
BRAND_RESPONSE,
|
||||||
@ -36,7 +38,6 @@ from .const import (
|
|||||||
PTZ_RESPONSE,
|
PTZ_RESPONSE,
|
||||||
STREAM_PROFILES_RESPONSE,
|
STREAM_PROFILES_RESPONSE,
|
||||||
VIEW_AREAS_RESPONSE,
|
VIEW_AREAS_RESPONSE,
|
||||||
VMD4_RESPONSE,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
from tests.common import MockConfigEntry
|
from tests.common import MockConfigEntry
|
||||||
@ -105,88 +106,90 @@ def default_request_fixture(
|
|||||||
"""Mock default Vapix requests responses."""
|
"""Mock default Vapix requests responses."""
|
||||||
|
|
||||||
def __mock_default_requests(host):
|
def __mock_default_requests(host):
|
||||||
path = f"http://{host}:80"
|
respx_mock(base_url=f"http://{host}:80")
|
||||||
|
|
||||||
if host != DEFAULT_HOST:
|
if host != DEFAULT_HOST:
|
||||||
respx.post(f"{path}/axis-cgi/apidiscovery.cgi").respond(
|
respx.post("/axis-cgi/apidiscovery.cgi").respond(
|
||||||
json=API_DISCOVERY_RESPONSE,
|
json=API_DISCOVERY_RESPONSE,
|
||||||
)
|
)
|
||||||
respx.post(f"{path}/axis-cgi/basicdeviceinfo.cgi").respond(
|
respx.post("/axis-cgi/basicdeviceinfo.cgi").respond(
|
||||||
json=BASIC_DEVICE_INFO_RESPONSE,
|
json=BASIC_DEVICE_INFO_RESPONSE,
|
||||||
)
|
)
|
||||||
respx.post(f"{path}/axis-cgi/io/portmanagement.cgi").respond(
|
respx.post("/axis-cgi/io/portmanagement.cgi").respond(
|
||||||
json=port_management_payload,
|
json=port_management_payload,
|
||||||
)
|
)
|
||||||
respx.post(f"{path}/axis-cgi/mqtt/client.cgi").respond(
|
respx.post("/axis-cgi/mqtt/client.cgi").respond(
|
||||||
json=MQTT_CLIENT_RESPONSE,
|
json=MQTT_CLIENT_RESPONSE,
|
||||||
)
|
)
|
||||||
respx.post(f"{path}/axis-cgi/streamprofile.cgi").respond(
|
respx.post("/axis-cgi/streamprofile.cgi").respond(
|
||||||
json=STREAM_PROFILES_RESPONSE,
|
json=STREAM_PROFILES_RESPONSE,
|
||||||
)
|
)
|
||||||
respx.post(f"{path}/axis-cgi/viewarea/info.cgi").respond(
|
respx.post("/axis-cgi/viewarea/info.cgi").respond(json=VIEW_AREAS_RESPONSE)
|
||||||
json=VIEW_AREAS_RESPONSE
|
|
||||||
)
|
|
||||||
respx.post(
|
respx.post(
|
||||||
f"{path}/axis-cgi/param.cgi",
|
"/axis-cgi/param.cgi",
|
||||||
data={"action": "list", "group": "root.Brand"},
|
data={"action": "list", "group": "root.Brand"},
|
||||||
).respond(
|
).respond(
|
||||||
text=BRAND_RESPONSE,
|
text=BRAND_RESPONSE,
|
||||||
headers={"Content-Type": "text/plain"},
|
headers={"Content-Type": "text/plain"},
|
||||||
)
|
)
|
||||||
respx.post(
|
respx.post(
|
||||||
f"{path}/axis-cgi/param.cgi",
|
"/axis-cgi/param.cgi",
|
||||||
data={"action": "list", "group": "root.Image"},
|
data={"action": "list", "group": "root.Image"},
|
||||||
).respond(
|
).respond(
|
||||||
text=IMAGE_RESPONSE,
|
text=IMAGE_RESPONSE,
|
||||||
headers={"Content-Type": "text/plain"},
|
headers={"Content-Type": "text/plain"},
|
||||||
)
|
)
|
||||||
respx.post(
|
respx.post(
|
||||||
f"{path}/axis-cgi/param.cgi",
|
"/axis-cgi/param.cgi",
|
||||||
data={"action": "list", "group": "root.Input"},
|
data={"action": "list", "group": "root.Input"},
|
||||||
).respond(
|
).respond(
|
||||||
text=PORTS_RESPONSE,
|
text=PORTS_RESPONSE,
|
||||||
headers={"Content-Type": "text/plain"},
|
headers={"Content-Type": "text/plain"},
|
||||||
)
|
)
|
||||||
respx.post(
|
respx.post(
|
||||||
f"{path}/axis-cgi/param.cgi",
|
"/axis-cgi/param.cgi",
|
||||||
data={"action": "list", "group": "root.IOPort"},
|
data={"action": "list", "group": "root.IOPort"},
|
||||||
).respond(
|
).respond(
|
||||||
text=param_ports_payload,
|
text=param_ports_payload,
|
||||||
headers={"Content-Type": "text/plain"},
|
headers={"Content-Type": "text/plain"},
|
||||||
)
|
)
|
||||||
respx.post(
|
respx.post(
|
||||||
f"{path}/axis-cgi/param.cgi",
|
"/axis-cgi/param.cgi",
|
||||||
data={"action": "list", "group": "root.Output"},
|
data={"action": "list", "group": "root.Output"},
|
||||||
).respond(
|
).respond(
|
||||||
text=PORTS_RESPONSE,
|
text=PORTS_RESPONSE,
|
||||||
headers={"Content-Type": "text/plain"},
|
headers={"Content-Type": "text/plain"},
|
||||||
)
|
)
|
||||||
respx.post(
|
respx.post(
|
||||||
f"{path}/axis-cgi/param.cgi",
|
"/axis-cgi/param.cgi",
|
||||||
data={"action": "list", "group": "root.Properties"},
|
data={"action": "list", "group": "root.Properties"},
|
||||||
).respond(
|
).respond(
|
||||||
text=param_properties_payload,
|
text=param_properties_payload,
|
||||||
headers={"Content-Type": "text/plain"},
|
headers={"Content-Type": "text/plain"},
|
||||||
)
|
)
|
||||||
respx.post(
|
respx.post(
|
||||||
f"{path}/axis-cgi/param.cgi",
|
"/axis-cgi/param.cgi",
|
||||||
data={"action": "list", "group": "root.PTZ"},
|
data={"action": "list", "group": "root.PTZ"},
|
||||||
).respond(
|
).respond(
|
||||||
text=PTZ_RESPONSE,
|
text=PTZ_RESPONSE,
|
||||||
headers={"Content-Type": "text/plain"},
|
headers={"Content-Type": "text/plain"},
|
||||||
)
|
)
|
||||||
respx.post(
|
respx.post(
|
||||||
f"{path}/axis-cgi/param.cgi",
|
"/axis-cgi/param.cgi",
|
||||||
data={"action": "list", "group": "root.StreamProfile"},
|
data={"action": "list", "group": "root.StreamProfile"},
|
||||||
).respond(
|
).respond(
|
||||||
text=STREAM_PROFILES_RESPONSE,
|
text=STREAM_PROFILES_RESPONSE,
|
||||||
headers={"Content-Type": "text/plain"},
|
headers={"Content-Type": "text/plain"},
|
||||||
)
|
)
|
||||||
respx.post(f"{path}/axis-cgi/applications/list.cgi").respond(
|
respx.post("/axis-cgi/applications/list.cgi").respond(
|
||||||
text=APPLICATIONS_LIST_RESPONSE,
|
text=APPLICATIONS_LIST_RESPONSE,
|
||||||
headers={"Content-Type": "text/xml"},
|
headers={"Content-Type": "text/xml"},
|
||||||
)
|
)
|
||||||
respx.post(f"{path}/local/vmd/control.cgi").respond(json=VMD4_RESPONSE)
|
respx.post("/local/fenceguard/control.cgi").respond(json=APP_VMD4_RESPONSE)
|
||||||
|
respx.post("/local/loiteringguard/control.cgi").respond(json=APP_VMD4_RESPONSE)
|
||||||
|
respx.post("/local/motionguard/control.cgi").respond(json=APP_VMD4_RESPONSE)
|
||||||
|
respx.post("/local/vmd/control.cgi").respond(json=APP_VMD4_RESPONSE)
|
||||||
|
respx.post("/local/objectanalytics/control.cgi").respond(json=APP_AOA_RESPONSE)
|
||||||
|
|
||||||
return __mock_default_requests
|
return __mock_default_requests
|
||||||
|
|
||||||
|
@ -35,7 +35,11 @@ API_DISCOVERY_PORT_MANAGEMENT = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
APPLICATIONS_LIST_RESPONSE = """<reply result="ok">
|
APPLICATIONS_LIST_RESPONSE = """<reply result="ok">
|
||||||
|
<application Name="fenceguard" NiceName="AXIS Fence Guard" Vendor="Axis Communications" Version="2.2-6" ApplicationID="47775" License="None" Status="Running" ConfigurationPage="local/fenceguard/config.html" VendorHomePage="http://www.axis.com" LicenseName="Proprietary" />
|
||||||
|
<application Name="loiteringguard" NiceName="AXIS Loitering Guard" Vendor="Axis Communications" Version="2.2-6" ApplicationID="46775" License="None" Status="Running" ConfigurationPage="local/loiteringguard/config.html" VendorHomePage="http://www.axis.com" LicenseName="Proprietary" />
|
||||||
|
<application Name="motionguard" NiceName="AXIS Motion Guard" Vendor="Axis Communications" Version="2.2-6" ApplicationID="48170" License="None" Status="Running" ConfigurationPage="local/motionguard/config.html" VendorHomePage="http://www.axis.com" LicenseName="Proprietary" />
|
||||||
<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" />
|
<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" />
|
||||||
|
<application Name="objectanalytics" NiceName="AXIS Object Analytics" Vendor="Axis Communications" Version="1.0-0" ApplicationID="143440" License="None" Status="Running" ConfigurationPage="local/vmd/config.html" VendorHomePage="http://www.axis.com" />
|
||||||
</reply>"""
|
</reply>"""
|
||||||
|
|
||||||
BASIC_DEVICE_INFO_RESPONSE = {
|
BASIC_DEVICE_INFO_RESPONSE = {
|
||||||
@ -95,7 +99,7 @@ PORT_MANAGEMENT_RESPONSE = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
VMD4_RESPONSE = {
|
APP_VMD4_RESPONSE = {
|
||||||
"apiVersion": "1.4",
|
"apiVersion": "1.4",
|
||||||
"method": "getConfiguration",
|
"method": "getConfiguration",
|
||||||
"context": CONTEXT,
|
"context": CONTEXT,
|
||||||
@ -108,6 +112,46 @@ VMD4_RESPONSE = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
APP_AOA_RESPONSE = {
|
||||||
|
"apiVersion": "1.0",
|
||||||
|
"context": "Axis library",
|
||||||
|
"data": {
|
||||||
|
"devices": [{"id": 1, "rotation": 180, "type": "camera"}],
|
||||||
|
"metadataOverlay": [],
|
||||||
|
"perspectives": [],
|
||||||
|
"scenarios": [
|
||||||
|
{
|
||||||
|
"devices": [{"id": 1}],
|
||||||
|
"filters": [
|
||||||
|
{"distance": 5, "type": "distanceSwayingObject"},
|
||||||
|
{"time": 1, "type": "timeShortLivedLimit"},
|
||||||
|
{"height": 3, "type": "sizePercentage", "width": 3},
|
||||||
|
],
|
||||||
|
"id": 1,
|
||||||
|
"name": "Scenario 1",
|
||||||
|
"objectClassifications": [],
|
||||||
|
"perspectives": [],
|
||||||
|
"presets": [],
|
||||||
|
"triggers": [
|
||||||
|
{
|
||||||
|
"type": "includeArea",
|
||||||
|
"vertices": [
|
||||||
|
[-0.97, -0.97],
|
||||||
|
[-0.97, 0.97],
|
||||||
|
[0.97, 0.97],
|
||||||
|
[0.97, -0.97],
|
||||||
|
],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "motion",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"status": {},
|
||||||
|
},
|
||||||
|
"method": "getConfiguration",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
BRAND_RESPONSE = """root.Brand.Brand=AXIS
|
BRAND_RESPONSE = """root.Brand.Brand=AXIS
|
||||||
root.Brand.ProdFullName=AXIS M1065-LW Network Camera
|
root.Brand.ProdFullName=AXIS M1065-LW Network Camera
|
||||||
root.Brand.ProdNbr=M1065-LW
|
root.Brand.ProdNbr=M1065-LW
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
"""Axis binary sensor platform tests."""
|
"""Axis binary sensor platform tests."""
|
||||||
|
import pytest
|
||||||
|
|
||||||
from homeassistant.components.axis.const import DOMAIN as AXIS_DOMAIN
|
from homeassistant.components.axis.const import DOMAIN as AXIS_DOMAIN
|
||||||
from homeassistant.components.binary_sensor import (
|
from homeassistant.components.binary_sensor import (
|
||||||
DOMAIN as BINARY_SENSOR_DOMAIN,
|
DOMAIN as BINARY_SENSOR_DOMAIN,
|
||||||
@ -30,23 +32,10 @@ async def test_no_binary_sensors(hass: HomeAssistant, setup_config_entry) -> Non
|
|||||||
assert not hass.states.async_entity_ids(BINARY_SENSOR_DOMAIN)
|
assert not hass.states.async_entity_ids(BINARY_SENSOR_DOMAIN)
|
||||||
|
|
||||||
|
|
||||||
async def test_binary_sensors(
|
async def test_unsupported_binary_sensors(
|
||||||
hass: HomeAssistant, setup_config_entry, mock_rtsp_event
|
hass: HomeAssistant, setup_config_entry, mock_rtsp_event
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test that sensors are loaded properly."""
|
"""Test that unsupported sensors are not loaded."""
|
||||||
mock_rtsp_event(
|
|
||||||
topic="tns1:Device/tnsaxis:Sensor/PIR",
|
|
||||||
data_type="state",
|
|
||||||
data_value="0",
|
|
||||||
source_name="sensor",
|
|
||||||
source_idx="0",
|
|
||||||
)
|
|
||||||
mock_rtsp_event(
|
|
||||||
topic="tnsaxis:CameraApplicationPlatform/VMD/Camera1Profile1",
|
|
||||||
data_type="active",
|
|
||||||
data_value="1",
|
|
||||||
)
|
|
||||||
# Unsupported event
|
|
||||||
mock_rtsp_event(
|
mock_rtsp_event(
|
||||||
topic="tns1:PTZController/tnsaxis:PTZPresets/Channel_1",
|
topic="tns1:PTZController/tnsaxis:PTZPresets/Channel_1",
|
||||||
data_type="on_preset",
|
data_type="on_preset",
|
||||||
@ -56,14 +45,104 @@ async def test_binary_sensors(
|
|||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert len(hass.states.async_entity_ids(BINARY_SENSOR_DOMAIN)) == 2
|
assert len(hass.states.async_entity_ids(BINARY_SENSOR_DOMAIN)) == 0
|
||||||
|
|
||||||
pir = hass.states.get(f"{BINARY_SENSOR_DOMAIN}.{NAME}_pir_0")
|
|
||||||
assert pir.state == STATE_OFF
|
|
||||||
assert pir.name == f"{NAME} PIR 0"
|
|
||||||
assert pir.attributes["device_class"] == BinarySensorDeviceClass.MOTION
|
|
||||||
|
|
||||||
vmd4 = hass.states.get(f"{BINARY_SENSOR_DOMAIN}.{NAME}_vmd4_profile_1")
|
@pytest.mark.parametrize(
|
||||||
assert vmd4.state == STATE_ON
|
("event", "entity"),
|
||||||
assert vmd4.name == f"{NAME} VMD4 Profile 1"
|
[
|
||||||
assert vmd4.attributes["device_class"] == BinarySensorDeviceClass.MOTION
|
(
|
||||||
|
{
|
||||||
|
"topic": "tns1:Device/tnsaxis:Sensor/PIR",
|
||||||
|
"data_type": "state",
|
||||||
|
"data_value": "0",
|
||||||
|
"source_name": "sensor",
|
||||||
|
"source_idx": "0",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": f"{BINARY_SENSOR_DOMAIN}.{NAME}_pir_0",
|
||||||
|
"state": STATE_OFF,
|
||||||
|
"name": f"{NAME} PIR 0",
|
||||||
|
"device_class": BinarySensorDeviceClass.MOTION,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
{
|
||||||
|
"topic": "tnsaxis:CameraApplicationPlatform/FenceGuard/Camera1Profile1",
|
||||||
|
"data_type": "active",
|
||||||
|
"data_value": "1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": f"{BINARY_SENSOR_DOMAIN}.{NAME}_fence_guard_profile_1",
|
||||||
|
"state": STATE_ON,
|
||||||
|
"name": f"{NAME} Fence Guard Profile 1",
|
||||||
|
"device_class": BinarySensorDeviceClass.MOTION,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
{
|
||||||
|
"topic": "tnsaxis:CameraApplicationPlatform/MotionGuard/Camera1Profile1",
|
||||||
|
"data_type": "active",
|
||||||
|
"data_value": "1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": f"{BINARY_SENSOR_DOMAIN}.{NAME}_motion_guard_profile_1",
|
||||||
|
"state": STATE_ON,
|
||||||
|
"name": f"{NAME} Motion Guard Profile 1",
|
||||||
|
"device_class": BinarySensorDeviceClass.MOTION,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
{
|
||||||
|
"topic": "tnsaxis:CameraApplicationPlatform/LoiteringGuard/Camera1Profile1",
|
||||||
|
"data_type": "active",
|
||||||
|
"data_value": "1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": f"{BINARY_SENSOR_DOMAIN}.{NAME}_loitering_guard_profile_1",
|
||||||
|
"state": STATE_ON,
|
||||||
|
"name": f"{NAME} Loitering Guard Profile 1",
|
||||||
|
"device_class": BinarySensorDeviceClass.MOTION,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
{
|
||||||
|
"topic": "tnsaxis:CameraApplicationPlatform/VMD/Camera1Profile1",
|
||||||
|
"data_type": "active",
|
||||||
|
"data_value": "1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": f"{BINARY_SENSOR_DOMAIN}.{NAME}_vmd4_profile_1",
|
||||||
|
"state": STATE_ON,
|
||||||
|
"name": f"{NAME} VMD4 Profile 1",
|
||||||
|
"device_class": BinarySensorDeviceClass.MOTION,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
{
|
||||||
|
"topic": "tnsaxis:CameraApplicationPlatform/ObjectAnalytics/Device1Scenario1",
|
||||||
|
"data_type": "active",
|
||||||
|
"data_value": "1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": f"{BINARY_SENSOR_DOMAIN}.{NAME}_object_analytics_scenario_1",
|
||||||
|
"state": STATE_ON,
|
||||||
|
"name": f"{NAME} Object Analytics Scenario 1",
|
||||||
|
"device_class": BinarySensorDeviceClass.MOTION,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_binary_sensors(
|
||||||
|
hass: HomeAssistant, setup_config_entry, mock_rtsp_event, event, entity
|
||||||
|
) -> None:
|
||||||
|
"""Test that sensors are loaded properly."""
|
||||||
|
mock_rtsp_event(**event)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert len(hass.states.async_entity_ids(BINARY_SENSOR_DOMAIN)) == 1
|
||||||
|
|
||||||
|
state = hass.states.get(entity["id"])
|
||||||
|
assert state.state == entity["state"]
|
||||||
|
assert state.name == entity["name"]
|
||||||
|
assert state.attributes["device_class"] == entity["device_class"]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user