Skip to content

Commit 8dc26d6

Browse files
committed
finish tests
1 parent 6cff6ea commit 8dc26d6

File tree

1 file changed

+202
-26
lines changed

1 file changed

+202
-26
lines changed

tests/components/onvif/test_config_flow.py

Lines changed: 202 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
from asyncio import Future
33

44
from asynctest import MagicMock, patch
5+
from onvif.exceptions import ONVIFError
6+
from zeep.exceptions import Fault
57

68
from homeassistant import config_entries, data_entry_flow
79
from homeassistant.components.onvif import config_flow
@@ -16,8 +18,27 @@
1618
PASSWORD = "12345"
1719
MAC = "aa:bb:cc:dd:ee"
1820

19-
20-
def setup_mock_onvif_device(mock_device, two_profiles=False):
21+
DISCOVERY = [
22+
{
23+
"EPR": URN,
24+
config_flow.CONF_NAME: NAME,
25+
config_flow.CONF_HOST: HOST,
26+
config_flow.CONF_PORT: PORT,
27+
"MAC": MAC,
28+
},
29+
{
30+
"EPR": "urn:uuid:987654321",
31+
config_flow.CONF_NAME: "TestCamera2",
32+
config_flow.CONF_HOST: "5.6.7.8",
33+
config_flow.CONF_PORT: PORT,
34+
"MAC": "ee:dd:cc:bb:aa",
35+
},
36+
]
37+
38+
39+
def setup_mock_onvif_device(
40+
mock_device, with_h264=True, two_profiles=False, with_interfaces=True
41+
):
2142
"""Prepare mock ONVIF device."""
2243
devicemgmt = MagicMock()
2344

@@ -26,12 +47,14 @@ def setup_mock_onvif_device(mock_device, two_profiles=False):
2647
interface.Info.HwAddress = MAC
2748

2849
devicemgmt.GetNetworkInterfaces.return_value = Future()
29-
devicemgmt.GetNetworkInterfaces.return_value.set_result([interface])
50+
devicemgmt.GetNetworkInterfaces.return_value.set_result(
51+
[interface] if with_interfaces else []
52+
)
3053

3154
media_service = MagicMock()
3255

3356
profile1 = MagicMock()
34-
profile1.VideoEncoderConfiguration.Encoding = "H264"
57+
profile1.VideoEncoderConfiguration.Encoding = "H264" if with_h264 else "MJPEG"
3558
profile2 = MagicMock()
3659
profile2.VideoEncoderConfiguration.Encoding = "H264" if two_profiles else "MJPEG"
3760

@@ -60,24 +83,35 @@ def mock_constructor(
6083
mock_device.side_effect = mock_constructor
6184

6285

63-
def setup_mock_discovery(mock_discovery, with_name=False, with_mac=False):
86+
def setup_mock_discovery(
87+
mock_discovery, with_name=False, with_mac=False, two_devices=False
88+
):
6489
"""Prepare mock discovery result."""
65-
service = MagicMock()
66-
service.getXAddrs = MagicMock(
67-
return_value=[f"http://{HOST}:{PORT}/onvif/device_service"]
68-
)
69-
service.getEPR = MagicMock(return_value=URN)
70-
scopes = []
71-
if with_name:
72-
scope = MagicMock()
73-
scope.getValue = MagicMock(return_value=f"onvif://www.onvif.org/name/{NAME}")
74-
scopes.append(scope)
75-
if with_mac:
76-
scope = MagicMock()
77-
scope.getValue = MagicMock(return_value=f"onvif://www.onvif.org/mac/{MAC}")
78-
scopes.append(scope)
79-
service.getScopes = MagicMock(return_value=scopes)
80-
mock_discovery.return_value = [service]
90+
services = []
91+
for item in DISCOVERY:
92+
service = MagicMock()
93+
service.getXAddrs = MagicMock(
94+
return_value=[
95+
f"http://{item[config_flow.CONF_HOST]}:{item[config_flow.CONF_PORT]}/onvif/device_service"
96+
]
97+
)
98+
service.getEPR = MagicMock(return_value=item["EPR"])
99+
scopes = []
100+
if with_name:
101+
scope = MagicMock()
102+
scope.getValue = MagicMock(
103+
return_value=f"onvif://www.onvif.org/name/{item[config_flow.CONF_NAME]}"
104+
)
105+
scopes.append(scope)
106+
if with_mac:
107+
scope = MagicMock()
108+
scope.getValue = MagicMock(
109+
return_value=f"onvif://www.onvif.org/mac/{item['MAC']}"
110+
)
111+
scopes.append(scope)
112+
service.getScopes = MagicMock(return_value=scopes)
113+
services.append(service)
114+
mock_discovery.return_value = services
81115

82116

83117
def setup_mock_camera(mock_camera):
@@ -93,7 +127,7 @@ def mock_constructor(hass, config):
93127

94128

95129
async def setup_onvif_integration(
96-
hass, config=None, options=None, entry_id="1", source="user",
130+
hass, config=None, options=None, unique_id=MAC, entry_id="1", source="user",
97131
):
98132
"""Create an ONVIF config entry."""
99133
if not config:
@@ -113,7 +147,7 @@ async def setup_onvif_integration(
113147
connection_class=config_entries.CONN_CLASS_LOCAL_PUSH,
114148
options=options or {},
115149
entry_id=entry_id,
116-
unique_id=MAC,
150+
unique_id=unique_id,
117151
)
118152
config_entry.add_to_hass(hass)
119153

@@ -160,7 +194,7 @@ async def test_flow_discovered_devices(hass):
160194

161195
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
162196
assert result["step_id"] == "device"
163-
assert len(result["data_schema"].schema[config_flow.CONF_HOST].container) == 2
197+
assert len(result["data_schema"].schema[config_flow.CONF_HOST].container) == 3
164198

165199
result = await hass.config_entries.flow.async_configure(
166200
result["flow_id"], user_input={config_flow.CONF_HOST: f"{URN} ({HOST})"}
@@ -191,9 +225,60 @@ async def test_flow_discovered_devices(hass):
191225
}
192226

193227

228+
async def test_flow_discovered_devices_ignore_configured_manual_input(hass):
229+
"""Test that config flow discovery ignores configured devices."""
230+
await setup_onvif_integration(hass)
231+
232+
result = await hass.config_entries.flow.async_init(
233+
config_flow.DOMAIN, context={"source": "user"}
234+
)
235+
236+
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
237+
assert result["step_id"] == "user"
238+
239+
with patch(
240+
"homeassistant.components.onvif.config_flow.get_device"
241+
) as mock_device, patch(
242+
"homeassistant.components.onvif.config_flow.wsdiscovery"
243+
) as mock_discovery, patch(
244+
"homeassistant.components.onvif.camera.ONVIFHassCamera"
245+
) as mock_camera:
246+
setup_mock_onvif_device(mock_device)
247+
setup_mock_discovery(mock_discovery, with_mac=True)
248+
setup_mock_camera(mock_camera)
249+
250+
result = await hass.config_entries.flow.async_configure(
251+
result["flow_id"], user_input={}
252+
)
253+
254+
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
255+
assert result["step_id"] == "device"
256+
assert len(result["data_schema"].schema[config_flow.CONF_HOST].container) == 2
257+
258+
result = await hass.config_entries.flow.async_configure(
259+
result["flow_id"],
260+
user_input={config_flow.CONF_HOST: config_flow.CONF_MANUAL_INPUT},
261+
)
262+
263+
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
264+
assert result["step_id"] == "manual_input"
265+
266+
194267
async def test_flow_discovery_ignore_existing_and_abort(hass):
195268
"""Test that config flow discovery ignores setup devices."""
196269
await setup_onvif_integration(hass)
270+
await setup_onvif_integration(
271+
hass,
272+
config={
273+
config_flow.CONF_NAME: DISCOVERY[1]["EPR"],
274+
config_flow.CONF_HOST: DISCOVERY[1][config_flow.CONF_HOST],
275+
config_flow.CONF_PORT: DISCOVERY[1][config_flow.CONF_PORT],
276+
config_flow.CONF_USERNAME: "",
277+
config_flow.CONF_PASSWORD: "",
278+
},
279+
unique_id=DISCOVERY[1]["MAC"],
280+
entry_id="2",
281+
)
197282

198283
result = await hass.config_entries.flow.async_init(
199284
config_flow.DOMAIN, context={"source": "user"}
@@ -267,8 +352,7 @@ async def test_flow_manual_entry(hass):
267352
setup_mock_camera(mock_camera)
268353

269354
result = await hass.config_entries.flow.async_configure(
270-
result["flow_id"],
271-
user_input={config_flow.CONF_HOST: config_flow.CONF_MANUAL_INPUT},
355+
result["flow_id"], user_input={},
272356
)
273357

274358
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
@@ -308,6 +392,98 @@ async def test_flow_manual_entry(hass):
308392
}
309393

310394

395+
async def test_flow_import_no_mac(hass):
396+
"""Test that config flow fails when no MAC available."""
397+
with patch("homeassistant.components.onvif.config_flow.get_device") as mock_device:
398+
setup_mock_onvif_device(mock_device, with_interfaces=False)
399+
400+
result = await hass.config_entries.flow.async_init(
401+
config_flow.DOMAIN,
402+
context={"source": config_entries.SOURCE_IMPORT},
403+
data={
404+
config_flow.CONF_NAME: NAME,
405+
config_flow.CONF_HOST: HOST,
406+
config_flow.CONF_PORT: PORT,
407+
config_flow.CONF_USERNAME: USERNAME,
408+
config_flow.CONF_PASSWORD: PASSWORD,
409+
config_flow.CONF_PROFILE: [0],
410+
},
411+
)
412+
413+
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
414+
assert result["reason"] == "no_mac"
415+
416+
417+
async def test_flow_import_no_h264(hass):
418+
"""Test that config flow fails when no MAC available."""
419+
with patch("homeassistant.components.onvif.config_flow.get_device") as mock_device:
420+
setup_mock_onvif_device(mock_device, with_h264=False)
421+
422+
result = await hass.config_entries.flow.async_init(
423+
config_flow.DOMAIN,
424+
context={"source": config_entries.SOURCE_IMPORT},
425+
data={
426+
config_flow.CONF_NAME: NAME,
427+
config_flow.CONF_HOST: HOST,
428+
config_flow.CONF_PORT: PORT,
429+
config_flow.CONF_USERNAME: USERNAME,
430+
config_flow.CONF_PASSWORD: PASSWORD,
431+
},
432+
)
433+
434+
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
435+
assert result["reason"] == "no_h264"
436+
437+
438+
async def test_flow_import_onvif_api_error(hass):
439+
"""Test that config flow fails when ONVIF API fails."""
440+
with patch("homeassistant.components.onvif.config_flow.get_device") as mock_device:
441+
setup_mock_onvif_device(mock_device)
442+
mock_device.create_devicemgmt_service = MagicMock(
443+
side_effect=ONVIFError("Could not get device mgmt service")
444+
)
445+
446+
result = await hass.config_entries.flow.async_init(
447+
config_flow.DOMAIN,
448+
context={"source": config_entries.SOURCE_IMPORT},
449+
data={
450+
config_flow.CONF_NAME: NAME,
451+
config_flow.CONF_HOST: HOST,
452+
config_flow.CONF_PORT: PORT,
453+
config_flow.CONF_USERNAME: USERNAME,
454+
config_flow.CONF_PASSWORD: PASSWORD,
455+
},
456+
)
457+
458+
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
459+
assert result["reason"] == "onvif_error"
460+
461+
462+
async def test_flow_import_onvif_auth_error(hass):
463+
"""Test that config flow fails when ONVIF API fails."""
464+
with patch("homeassistant.components.onvif.config_flow.get_device") as mock_device:
465+
setup_mock_onvif_device(mock_device)
466+
mock_device.create_devicemgmt_service = MagicMock(
467+
side_effect=Fault("Auth Error")
468+
)
469+
470+
result = await hass.config_entries.flow.async_init(
471+
config_flow.DOMAIN,
472+
context={"source": config_entries.SOURCE_IMPORT},
473+
data={
474+
config_flow.CONF_NAME: NAME,
475+
config_flow.CONF_HOST: HOST,
476+
config_flow.CONF_PORT: PORT,
477+
config_flow.CONF_USERNAME: USERNAME,
478+
config_flow.CONF_PASSWORD: PASSWORD,
479+
},
480+
)
481+
482+
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
483+
assert result["step_id"] == "auth"
484+
assert result["errors"]["base"] == "connection_failed"
485+
486+
311487
async def test_option_flow(hass):
312488
"""Test config flow options."""
313489
entry = await setup_onvif_integration(hass)

0 commit comments

Comments
 (0)