- The integration already has a reload listener installed once it is setup. We should not reload from the config flow since they compete
770 lines
24 KiB
Python
770 lines
24 KiB
Python
"""Test the UniFi Protect config flow."""
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import asdict
|
|
import socket
|
|
from unittest.mock import patch
|
|
|
|
import pytest
|
|
from pyunifiprotect import NotAuthorized, NvrError
|
|
from pyunifiprotect.data.nvr import NVR
|
|
|
|
from homeassistant import config_entries
|
|
from homeassistant.components import dhcp, ssdp
|
|
from homeassistant.components.unifiprotect.const import (
|
|
CONF_ALL_UPDATES,
|
|
CONF_DISABLE_RTSP,
|
|
CONF_OVERRIDE_CHOST,
|
|
DOMAIN,
|
|
)
|
|
from homeassistant.const import CONF_HOST
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.data_entry_flow import (
|
|
RESULT_TYPE_ABORT,
|
|
RESULT_TYPE_CREATE_ENTRY,
|
|
RESULT_TYPE_FORM,
|
|
)
|
|
from homeassistant.helpers import device_registry as dr
|
|
|
|
from . import (
|
|
DEVICE_HOSTNAME,
|
|
DEVICE_IP_ADDRESS,
|
|
DEVICE_MAC_ADDRESS,
|
|
DIRECT_CONNECT_DOMAIN,
|
|
UNIFI_DISCOVERY,
|
|
UNIFI_DISCOVERY_PARTIAL,
|
|
_patch_discovery,
|
|
)
|
|
from .conftest import MAC_ADDR
|
|
|
|
from tests.common import MockConfigEntry
|
|
|
|
DHCP_DISCOVERY = dhcp.DhcpServiceInfo(
|
|
hostname=DEVICE_HOSTNAME,
|
|
ip=DEVICE_IP_ADDRESS,
|
|
macaddress=DEVICE_MAC_ADDRESS,
|
|
)
|
|
SSDP_DISCOVERY = (
|
|
ssdp.SsdpServiceInfo(
|
|
ssdp_usn="mock_usn",
|
|
ssdp_st="mock_st",
|
|
ssdp_location=f"http://{DEVICE_IP_ADDRESS}:41417/rootDesc.xml",
|
|
upnp={
|
|
"friendlyName": "UniFi Dream Machine",
|
|
"modelDescription": "UniFi Dream Machine Pro",
|
|
"serialNumber": DEVICE_MAC_ADDRESS,
|
|
},
|
|
),
|
|
)
|
|
|
|
UNIFI_DISCOVERY_DICT = asdict(UNIFI_DISCOVERY)
|
|
UNIFI_DISCOVERY_DICT_PARTIAL = asdict(UNIFI_DISCOVERY_PARTIAL)
|
|
|
|
|
|
async def test_form(hass: HomeAssistant, mock_nvr: NVR) -> None:
|
|
"""Test we get the form."""
|
|
result = await hass.config_entries.flow.async_init(
|
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
|
)
|
|
assert result["type"] == RESULT_TYPE_FORM
|
|
assert not result["errors"]
|
|
|
|
with patch(
|
|
"homeassistant.components.unifiprotect.config_flow.ProtectApiClient.get_nvr",
|
|
return_value=mock_nvr,
|
|
), patch(
|
|
"homeassistant.components.unifiprotect.async_setup_entry",
|
|
return_value=True,
|
|
) as mock_setup_entry:
|
|
result2 = await hass.config_entries.flow.async_configure(
|
|
result["flow_id"],
|
|
{
|
|
"host": "1.1.1.1",
|
|
"username": "test-username",
|
|
"password": "test-password",
|
|
},
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert result2["type"] == RESULT_TYPE_CREATE_ENTRY
|
|
assert result2["title"] == "UnifiProtect"
|
|
assert result2["data"] == {
|
|
"host": "1.1.1.1",
|
|
"username": "test-username",
|
|
"password": "test-password",
|
|
"id": "UnifiProtect",
|
|
"port": 443,
|
|
"verify_ssl": False,
|
|
}
|
|
assert len(mock_setup_entry.mock_calls) == 1
|
|
|
|
|
|
async def test_form_version_too_old(hass: HomeAssistant, mock_old_nvr: NVR) -> None:
|
|
"""Test we handle the version being too old."""
|
|
result = await hass.config_entries.flow.async_init(
|
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
|
)
|
|
|
|
with patch(
|
|
"homeassistant.components.unifiprotect.config_flow.ProtectApiClient.get_nvr",
|
|
return_value=mock_old_nvr,
|
|
):
|
|
result2 = await hass.config_entries.flow.async_configure(
|
|
result["flow_id"],
|
|
{
|
|
"host": "1.1.1.1",
|
|
"username": "test-username",
|
|
"password": "test-password",
|
|
},
|
|
)
|
|
|
|
assert result2["type"] == RESULT_TYPE_FORM
|
|
assert result2["errors"] == {"base": "protect_version"}
|
|
|
|
|
|
async def test_form_invalid_auth(hass: HomeAssistant) -> None:
|
|
"""Test we handle invalid auth."""
|
|
result = await hass.config_entries.flow.async_init(
|
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
|
)
|
|
|
|
with patch(
|
|
"homeassistant.components.unifiprotect.config_flow.ProtectApiClient.get_nvr",
|
|
side_effect=NotAuthorized,
|
|
):
|
|
result2 = await hass.config_entries.flow.async_configure(
|
|
result["flow_id"],
|
|
{
|
|
"host": "1.1.1.1",
|
|
"username": "test-username",
|
|
"password": "test-password",
|
|
},
|
|
)
|
|
|
|
assert result2["type"] == RESULT_TYPE_FORM
|
|
assert result2["errors"] == {"password": "invalid_auth"}
|
|
|
|
|
|
async def test_form_cannot_connect(hass: HomeAssistant) -> None:
|
|
"""Test we handle cannot connect error."""
|
|
result = await hass.config_entries.flow.async_init(
|
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
|
)
|
|
|
|
with patch(
|
|
"homeassistant.components.unifiprotect.config_flow.ProtectApiClient.get_nvr",
|
|
side_effect=NvrError,
|
|
):
|
|
result2 = await hass.config_entries.flow.async_configure(
|
|
result["flow_id"],
|
|
{
|
|
"host": "1.1.1.1",
|
|
"username": "test-username",
|
|
"password": "test-password",
|
|
},
|
|
)
|
|
|
|
assert result2["type"] == RESULT_TYPE_FORM
|
|
assert result2["errors"] == {"base": "cannot_connect"}
|
|
|
|
|
|
async def test_form_reauth_auth(hass: HomeAssistant, mock_nvr: NVR) -> None:
|
|
"""Test we handle reauth auth."""
|
|
mock_config = MockConfigEntry(
|
|
domain=DOMAIN,
|
|
data={
|
|
"host": "1.1.1.1",
|
|
"username": "test-username",
|
|
"password": "test-password",
|
|
"id": "UnifiProtect",
|
|
"port": 443,
|
|
"verify_ssl": False,
|
|
},
|
|
unique_id=dr.format_mac(MAC_ADDR),
|
|
)
|
|
mock_config.add_to_hass(hass)
|
|
|
|
result = await hass.config_entries.flow.async_init(
|
|
DOMAIN,
|
|
context={
|
|
"source": config_entries.SOURCE_REAUTH,
|
|
"entry_id": mock_config.entry_id,
|
|
},
|
|
)
|
|
assert result["type"] == RESULT_TYPE_FORM
|
|
assert not result["errors"]
|
|
|
|
with patch(
|
|
"homeassistant.components.unifiprotect.config_flow.ProtectApiClient.get_nvr",
|
|
side_effect=NotAuthorized,
|
|
):
|
|
result2 = await hass.config_entries.flow.async_configure(
|
|
result["flow_id"],
|
|
{
|
|
"username": "test-username",
|
|
"password": "test-password",
|
|
},
|
|
)
|
|
|
|
assert result2["type"] == RESULT_TYPE_FORM
|
|
assert result2["errors"] == {"password": "invalid_auth"}
|
|
assert result2["step_id"] == "reauth_confirm"
|
|
|
|
with patch(
|
|
"homeassistant.components.unifiprotect.config_flow.ProtectApiClient.get_nvr",
|
|
return_value=mock_nvr,
|
|
):
|
|
result3 = await hass.config_entries.flow.async_configure(
|
|
result2["flow_id"],
|
|
{
|
|
"username": "test-username",
|
|
"password": "test-password",
|
|
},
|
|
)
|
|
|
|
assert result3["type"] == RESULT_TYPE_ABORT
|
|
assert result3["reason"] == "reauth_successful"
|
|
|
|
|
|
async def test_form_options(hass: HomeAssistant, mock_client) -> None:
|
|
"""Test we handle options flows."""
|
|
mock_config = MockConfigEntry(
|
|
domain=DOMAIN,
|
|
data={
|
|
"host": "1.1.1.1",
|
|
"username": "test-username",
|
|
"password": "test-password",
|
|
"id": "UnifiProtect",
|
|
"port": 443,
|
|
"verify_ssl": False,
|
|
},
|
|
version=2,
|
|
unique_id=dr.format_mac(MAC_ADDR),
|
|
)
|
|
mock_config.add_to_hass(hass)
|
|
|
|
with _patch_discovery(), patch(
|
|
"homeassistant.components.unifiprotect.ProtectApiClient"
|
|
) as mock_api:
|
|
mock_api.return_value = mock_client
|
|
|
|
await hass.config_entries.async_setup(mock_config.entry_id)
|
|
await hass.async_block_till_done()
|
|
assert mock_config.state == config_entries.ConfigEntryState.LOADED
|
|
|
|
result = await hass.config_entries.options.async_init(mock_config.entry_id)
|
|
assert result["type"] == RESULT_TYPE_FORM
|
|
assert not result["errors"]
|
|
assert result["step_id"] == "init"
|
|
|
|
result2 = await hass.config_entries.options.async_configure(
|
|
result["flow_id"],
|
|
{CONF_DISABLE_RTSP: True, CONF_ALL_UPDATES: True, CONF_OVERRIDE_CHOST: True},
|
|
)
|
|
|
|
assert result2["type"] == RESULT_TYPE_CREATE_ENTRY
|
|
assert result2["data"] == {
|
|
"all_updates": True,
|
|
"disable_rtsp": True,
|
|
"override_connection_host": True,
|
|
}
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"source, data",
|
|
[
|
|
(config_entries.SOURCE_DHCP, DHCP_DISCOVERY),
|
|
(config_entries.SOURCE_SSDP, SSDP_DISCOVERY),
|
|
],
|
|
)
|
|
async def test_discovered_by_ssdp_or_dhcp(
|
|
hass: HomeAssistant, source: str, data: dhcp.DhcpServiceInfo | ssdp.SsdpServiceInfo
|
|
) -> None:
|
|
"""Test we handoff to unifi-discovery when discovered via ssdp or dhcp."""
|
|
|
|
with _patch_discovery():
|
|
result = await hass.config_entries.flow.async_init(
|
|
DOMAIN,
|
|
context={"source": source},
|
|
data=data,
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert result["type"] == RESULT_TYPE_ABORT
|
|
assert result["reason"] == "discovery_started"
|
|
|
|
|
|
async def test_discovered_by_unifi_discovery_direct_connect(
|
|
hass: HomeAssistant, mock_nvr: NVR
|
|
) -> None:
|
|
"""Test a discovery from unifi-discovery."""
|
|
|
|
with _patch_discovery():
|
|
result = await hass.config_entries.flow.async_init(
|
|
DOMAIN,
|
|
context={"source": config_entries.SOURCE_INTEGRATION_DISCOVERY},
|
|
data=UNIFI_DISCOVERY_DICT,
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert result["type"] == RESULT_TYPE_FORM
|
|
assert result["step_id"] == "discovery_confirm"
|
|
flows = hass.config_entries.flow.async_progress_by_handler(DOMAIN)
|
|
assert flows[0]["context"]["title_placeholders"] == {
|
|
"ip_address": DEVICE_IP_ADDRESS,
|
|
"name": DEVICE_HOSTNAME,
|
|
}
|
|
|
|
assert not result["errors"]
|
|
|
|
with patch(
|
|
"homeassistant.components.unifiprotect.config_flow.ProtectApiClient.get_nvr",
|
|
return_value=mock_nvr,
|
|
), patch(
|
|
"homeassistant.components.unifiprotect.async_setup_entry",
|
|
return_value=True,
|
|
) as mock_setup_entry:
|
|
result2 = await hass.config_entries.flow.async_configure(
|
|
result["flow_id"],
|
|
{
|
|
"username": "test-username",
|
|
"password": "test-password",
|
|
},
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert result2["type"] == RESULT_TYPE_CREATE_ENTRY
|
|
assert result2["title"] == "UnifiProtect"
|
|
assert result2["data"] == {
|
|
"host": DIRECT_CONNECT_DOMAIN,
|
|
"username": "test-username",
|
|
"password": "test-password",
|
|
"id": "UnifiProtect",
|
|
"port": 443,
|
|
"verify_ssl": True,
|
|
}
|
|
assert len(mock_setup_entry.mock_calls) == 1
|
|
|
|
|
|
async def test_discovered_by_unifi_discovery_direct_connect_updated(
|
|
hass: HomeAssistant, mock_nvr: NVR
|
|
) -> None:
|
|
"""Test a discovery from unifi-discovery updates the direct connect host."""
|
|
mock_config = MockConfigEntry(
|
|
domain=DOMAIN,
|
|
data={
|
|
"host": "y.ui.direct",
|
|
"username": "test-username",
|
|
"password": "test-password",
|
|
"id": "UnifiProtect",
|
|
"port": 443,
|
|
"verify_ssl": True,
|
|
},
|
|
version=2,
|
|
unique_id=DEVICE_MAC_ADDRESS.replace(":", "").upper(),
|
|
)
|
|
mock_config.add_to_hass(hass)
|
|
|
|
with _patch_discovery():
|
|
result = await hass.config_entries.flow.async_init(
|
|
DOMAIN,
|
|
context={"source": config_entries.SOURCE_INTEGRATION_DISCOVERY},
|
|
data=UNIFI_DISCOVERY_DICT,
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert result["type"] == RESULT_TYPE_ABORT
|
|
assert result["reason"] == "already_configured"
|
|
assert mock_config.data[CONF_HOST] == DIRECT_CONNECT_DOMAIN
|
|
|
|
|
|
async def test_discovered_by_unifi_discovery_direct_connect_updated_but_not_using_direct_connect(
|
|
hass: HomeAssistant, mock_nvr: NVR
|
|
) -> None:
|
|
"""Test a discovery from unifi-discovery updates the host but not direct connect if its not in use."""
|
|
mock_config = MockConfigEntry(
|
|
domain=DOMAIN,
|
|
data={
|
|
"host": "1.2.2.2",
|
|
"username": "test-username",
|
|
"password": "test-password",
|
|
"id": "UnifiProtect",
|
|
"port": 443,
|
|
"verify_ssl": False,
|
|
},
|
|
version=2,
|
|
unique_id=DEVICE_MAC_ADDRESS.replace(":", "").upper(),
|
|
)
|
|
mock_config.add_to_hass(hass)
|
|
|
|
with _patch_discovery():
|
|
result = await hass.config_entries.flow.async_init(
|
|
DOMAIN,
|
|
context={"source": config_entries.SOURCE_INTEGRATION_DISCOVERY},
|
|
data=UNIFI_DISCOVERY_DICT,
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert result["type"] == RESULT_TYPE_ABORT
|
|
assert result["reason"] == "already_configured"
|
|
assert mock_config.data[CONF_HOST] == "127.0.0.1"
|
|
|
|
|
|
async def test_discovered_host_not_updated_if_existing_is_a_hostname(
|
|
hass: HomeAssistant, mock_nvr: NVR
|
|
) -> None:
|
|
"""Test we only update the host if its an ip address from discovery."""
|
|
mock_config = MockConfigEntry(
|
|
domain=DOMAIN,
|
|
data={
|
|
"host": "a.hostname",
|
|
"username": "test-username",
|
|
"password": "test-password",
|
|
"id": "UnifiProtect",
|
|
"port": 443,
|
|
"verify_ssl": True,
|
|
},
|
|
unique_id=DEVICE_MAC_ADDRESS.upper().replace(":", ""),
|
|
)
|
|
mock_config.add_to_hass(hass)
|
|
|
|
with _patch_discovery():
|
|
result = await hass.config_entries.flow.async_init(
|
|
DOMAIN,
|
|
context={"source": config_entries.SOURCE_INTEGRATION_DISCOVERY},
|
|
data=UNIFI_DISCOVERY_DICT,
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert result["type"] == RESULT_TYPE_ABORT
|
|
assert result["reason"] == "already_configured"
|
|
assert mock_config.data[CONF_HOST] == "a.hostname"
|
|
|
|
|
|
async def test_discovered_by_unifi_discovery(
|
|
hass: HomeAssistant, mock_nvr: NVR
|
|
) -> None:
|
|
"""Test a discovery from unifi-discovery."""
|
|
|
|
with _patch_discovery():
|
|
result = await hass.config_entries.flow.async_init(
|
|
DOMAIN,
|
|
context={"source": config_entries.SOURCE_INTEGRATION_DISCOVERY},
|
|
data=UNIFI_DISCOVERY_DICT,
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert result["type"] == RESULT_TYPE_FORM
|
|
assert result["step_id"] == "discovery_confirm"
|
|
flows = hass.config_entries.flow.async_progress_by_handler(DOMAIN)
|
|
assert flows[0]["context"]["title_placeholders"] == {
|
|
"ip_address": DEVICE_IP_ADDRESS,
|
|
"name": DEVICE_HOSTNAME,
|
|
}
|
|
|
|
assert not result["errors"]
|
|
|
|
with patch(
|
|
"homeassistant.components.unifiprotect.config_flow.ProtectApiClient.get_nvr",
|
|
side_effect=[NotAuthorized, mock_nvr],
|
|
), patch(
|
|
"homeassistant.components.unifiprotect.async_setup_entry",
|
|
return_value=True,
|
|
) as mock_setup_entry:
|
|
result2 = await hass.config_entries.flow.async_configure(
|
|
result["flow_id"],
|
|
{
|
|
"username": "test-username",
|
|
"password": "test-password",
|
|
},
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert result2["type"] == RESULT_TYPE_CREATE_ENTRY
|
|
assert result2["title"] == "UnifiProtect"
|
|
assert result2["data"] == {
|
|
"host": DEVICE_IP_ADDRESS,
|
|
"username": "test-username",
|
|
"password": "test-password",
|
|
"id": "UnifiProtect",
|
|
"port": 443,
|
|
"verify_ssl": False,
|
|
}
|
|
assert len(mock_setup_entry.mock_calls) == 1
|
|
|
|
|
|
async def test_discovered_by_unifi_discovery_partial(
|
|
hass: HomeAssistant, mock_nvr: NVR
|
|
) -> None:
|
|
"""Test a discovery from unifi-discovery partial."""
|
|
|
|
with _patch_discovery():
|
|
result = await hass.config_entries.flow.async_init(
|
|
DOMAIN,
|
|
context={"source": config_entries.SOURCE_INTEGRATION_DISCOVERY},
|
|
data=UNIFI_DISCOVERY_DICT_PARTIAL,
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert result["type"] == RESULT_TYPE_FORM
|
|
assert result["step_id"] == "discovery_confirm"
|
|
flows = hass.config_entries.flow.async_progress_by_handler(DOMAIN)
|
|
assert flows[0]["context"]["title_placeholders"] == {
|
|
"ip_address": DEVICE_IP_ADDRESS,
|
|
"name": "NVR DDEEFF",
|
|
}
|
|
|
|
assert not result["errors"]
|
|
|
|
with patch(
|
|
"homeassistant.components.unifiprotect.config_flow.ProtectApiClient.get_nvr",
|
|
return_value=mock_nvr,
|
|
), patch(
|
|
"homeassistant.components.unifiprotect.async_setup_entry",
|
|
return_value=True,
|
|
) as mock_setup_entry:
|
|
result2 = await hass.config_entries.flow.async_configure(
|
|
result["flow_id"],
|
|
{
|
|
"username": "test-username",
|
|
"password": "test-password",
|
|
},
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert result2["type"] == RESULT_TYPE_CREATE_ENTRY
|
|
assert result2["title"] == "UnifiProtect"
|
|
assert result2["data"] == {
|
|
"host": DEVICE_IP_ADDRESS,
|
|
"username": "test-username",
|
|
"password": "test-password",
|
|
"id": "UnifiProtect",
|
|
"port": 443,
|
|
"verify_ssl": False,
|
|
}
|
|
assert len(mock_setup_entry.mock_calls) == 1
|
|
|
|
|
|
async def test_discovered_by_unifi_discovery_direct_connect_on_different_interface(
|
|
hass: HomeAssistant, mock_nvr: NVR
|
|
) -> None:
|
|
"""Test a discovery from unifi-discovery from an alternate interface."""
|
|
mock_config = MockConfigEntry(
|
|
domain=DOMAIN,
|
|
data={
|
|
"host": DIRECT_CONNECT_DOMAIN,
|
|
"username": "test-username",
|
|
"password": "test-password",
|
|
"id": "UnifiProtect",
|
|
"port": 443,
|
|
"verify_ssl": True,
|
|
},
|
|
unique_id="FFFFFFAAAAAA",
|
|
)
|
|
mock_config.add_to_hass(hass)
|
|
|
|
with _patch_discovery():
|
|
result = await hass.config_entries.flow.async_init(
|
|
DOMAIN,
|
|
context={"source": config_entries.SOURCE_INTEGRATION_DISCOVERY},
|
|
data=UNIFI_DISCOVERY_DICT,
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert result["type"] == RESULT_TYPE_ABORT
|
|
assert result["reason"] == "already_configured"
|
|
|
|
|
|
async def test_discovered_by_unifi_discovery_direct_connect_on_different_interface_ip_matches(
|
|
hass: HomeAssistant, mock_nvr: NVR
|
|
) -> None:
|
|
"""Test a discovery from unifi-discovery from an alternate interface when the ip matches."""
|
|
mock_config = MockConfigEntry(
|
|
domain=DOMAIN,
|
|
data={
|
|
"host": "127.0.0.1",
|
|
"username": "test-username",
|
|
"password": "test-password",
|
|
"id": "UnifiProtect",
|
|
"port": 443,
|
|
"verify_ssl": True,
|
|
},
|
|
unique_id="FFFFFFAAAAAA",
|
|
)
|
|
mock_config.add_to_hass(hass)
|
|
|
|
with _patch_discovery():
|
|
result = await hass.config_entries.flow.async_init(
|
|
DOMAIN,
|
|
context={"source": config_entries.SOURCE_INTEGRATION_DISCOVERY},
|
|
data=UNIFI_DISCOVERY_DICT,
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert result["type"] == RESULT_TYPE_ABORT
|
|
assert result["reason"] == "already_configured"
|
|
|
|
|
|
async def test_discovered_by_unifi_discovery_direct_connect_on_different_interface_resolver(
|
|
hass: HomeAssistant, mock_nvr: NVR
|
|
) -> None:
|
|
"""Test a discovery from unifi-discovery from an alternate interface when direct connect domain resolves to host ip."""
|
|
mock_config = MockConfigEntry(
|
|
domain=DOMAIN,
|
|
data={
|
|
"host": "y.ui.direct",
|
|
"username": "test-username",
|
|
"password": "test-password",
|
|
"id": "UnifiProtect",
|
|
"port": 443,
|
|
"verify_ssl": True,
|
|
},
|
|
unique_id="FFFFFFAAAAAA",
|
|
)
|
|
mock_config.add_to_hass(hass)
|
|
|
|
other_ip_dict = UNIFI_DISCOVERY_DICT.copy()
|
|
other_ip_dict["source_ip"] = "127.0.0.1"
|
|
other_ip_dict["direct_connect_domain"] = "nomatchsameip.ui.direct"
|
|
|
|
with _patch_discovery(), patch.object(
|
|
hass.loop,
|
|
"getaddrinfo",
|
|
return_value=[(socket.AF_INET, None, None, None, ("127.0.0.1", 443))],
|
|
):
|
|
result = await hass.config_entries.flow.async_init(
|
|
DOMAIN,
|
|
context={"source": config_entries.SOURCE_INTEGRATION_DISCOVERY},
|
|
data=other_ip_dict,
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert result["type"] == RESULT_TYPE_ABORT
|
|
assert result["reason"] == "already_configured"
|
|
|
|
|
|
async def test_discovered_by_unifi_discovery_direct_connect_on_different_interface_resolver_fails(
|
|
hass: HomeAssistant, mock_nvr: NVR
|
|
) -> None:
|
|
"""Test we can still configure if the resolver fails."""
|
|
mock_config = MockConfigEntry(
|
|
domain=DOMAIN,
|
|
data={
|
|
"host": "y.ui.direct",
|
|
"username": "test-username",
|
|
"password": "test-password",
|
|
"id": "UnifiProtect",
|
|
"port": 443,
|
|
"verify_ssl": True,
|
|
},
|
|
unique_id="FFFFFFAAAAAA",
|
|
)
|
|
mock_config.add_to_hass(hass)
|
|
|
|
other_ip_dict = UNIFI_DISCOVERY_DICT.copy()
|
|
other_ip_dict["source_ip"] = "127.0.0.2"
|
|
other_ip_dict["direct_connect_domain"] = "nomatchsameip.ui.direct"
|
|
|
|
with _patch_discovery(), patch.object(
|
|
hass.loop, "getaddrinfo", side_effect=OSError
|
|
):
|
|
result = await hass.config_entries.flow.async_init(
|
|
DOMAIN,
|
|
context={"source": config_entries.SOURCE_INTEGRATION_DISCOVERY},
|
|
data=other_ip_dict,
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert result["type"] == RESULT_TYPE_FORM
|
|
assert result["step_id"] == "discovery_confirm"
|
|
flows = hass.config_entries.flow.async_progress_by_handler(DOMAIN)
|
|
assert flows[0]["context"]["title_placeholders"] == {
|
|
"ip_address": "127.0.0.2",
|
|
"name": "unvr",
|
|
}
|
|
|
|
assert not result["errors"]
|
|
|
|
with patch(
|
|
"homeassistant.components.unifiprotect.config_flow.ProtectApiClient.get_nvr",
|
|
return_value=mock_nvr,
|
|
), patch(
|
|
"homeassistant.components.unifiprotect.async_setup_entry",
|
|
return_value=True,
|
|
) as mock_setup_entry:
|
|
result2 = await hass.config_entries.flow.async_configure(
|
|
result["flow_id"],
|
|
{
|
|
"username": "test-username",
|
|
"password": "test-password",
|
|
},
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert result2["type"] == RESULT_TYPE_CREATE_ENTRY
|
|
assert result2["title"] == "UnifiProtect"
|
|
assert result2["data"] == {
|
|
"host": "nomatchsameip.ui.direct",
|
|
"username": "test-username",
|
|
"password": "test-password",
|
|
"id": "UnifiProtect",
|
|
"port": 443,
|
|
"verify_ssl": True,
|
|
}
|
|
assert len(mock_setup_entry.mock_calls) == 1
|
|
|
|
|
|
async def test_discovered_by_unifi_discovery_direct_connect_on_different_interface_resolver_no_result(
|
|
hass: HomeAssistant, mock_nvr: NVR
|
|
) -> None:
|
|
"""Test a discovery from unifi-discovery from an alternate interface when direct connect domain resolve has no result."""
|
|
mock_config = MockConfigEntry(
|
|
domain=DOMAIN,
|
|
data={
|
|
"host": "y.ui.direct",
|
|
"username": "test-username",
|
|
"password": "test-password",
|
|
"id": "UnifiProtect",
|
|
"port": 443,
|
|
"verify_ssl": True,
|
|
},
|
|
unique_id="FFFFFFAAAAAA",
|
|
)
|
|
mock_config.add_to_hass(hass)
|
|
|
|
other_ip_dict = UNIFI_DISCOVERY_DICT.copy()
|
|
other_ip_dict["source_ip"] = "127.0.0.2"
|
|
other_ip_dict["direct_connect_domain"] = "y.ui.direct"
|
|
|
|
with _patch_discovery(), patch.object(hass.loop, "getaddrinfo", return_value=[]):
|
|
result = await hass.config_entries.flow.async_init(
|
|
DOMAIN,
|
|
context={"source": config_entries.SOURCE_INTEGRATION_DISCOVERY},
|
|
data=other_ip_dict,
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert result["type"] == RESULT_TYPE_ABORT
|
|
assert result["reason"] == "already_configured"
|
|
|
|
|
|
async def test_discovery_can_be_ignored(hass: HomeAssistant, mock_nvr: NVR) -> None:
|
|
"""Test a discovery can be ignored."""
|
|
mock_config = MockConfigEntry(
|
|
domain=DOMAIN,
|
|
data={},
|
|
unique_id=DEVICE_MAC_ADDRESS.upper().replace(":", ""),
|
|
source=config_entries.SOURCE_IGNORE,
|
|
)
|
|
mock_config.add_to_hass(hass)
|
|
with _patch_discovery():
|
|
result = await hass.config_entries.flow.async_init(
|
|
DOMAIN,
|
|
context={"source": config_entries.SOURCE_INTEGRATION_DISCOVERY},
|
|
data=UNIFI_DISCOVERY_DICT,
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert result["type"] == RESULT_TYPE_ABORT
|
|
assert result["reason"] == "already_configured"
|