UniFi Protect test refactoring (#63486)

* UniFi Protect test refactoring

* More pylint fixes

* Use load_fixture helper

* yield to return where able
This commit is contained in:
Christopher Bailey 2022-01-05 13:29:59 -05:00 committed by GitHub
parent 8864492e35
commit d0d5222bf4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 419 additions and 109 deletions

View File

@ -1,81 +1,37 @@
"""Fixtures and test data for UniFi Protect methods.""" """Fixtures and test data for UniFi Protect methods."""
# pylint: disable=protected-access
from __future__ import annotations from __future__ import annotations
from dataclasses import dataclass from dataclasses import dataclass
from datetime import timedelta from datetime import timedelta
from ipaddress import IPv4Address from ipaddress import IPv4Address
import json import json
from pathlib import Path
from typing import Any, Callable from typing import Any, Callable
from unittest.mock import AsyncMock, Mock, patch from unittest.mock import AsyncMock, Mock, patch
import pytest import pytest
from pyunifiprotect.data import Camera, Light, Version, WSSubscriptionMessage from pyunifiprotect.data import Camera, Light, WSSubscriptionMessage
from pyunifiprotect.data.base import ProtectAdoptableDeviceModel from pyunifiprotect.data.base import ProtectAdoptableDeviceModel
from pyunifiprotect.data.devices import Viewer from pyunifiprotect.data.devices import Sensor, Viewer
from pyunifiprotect.data.nvr import DoorbellMessage, Liveview from pyunifiprotect.data.nvr import NVR, Liveview
from pyunifiprotect.data.types import DoorbellMessageType, ModelType
from homeassistant.components.unifiprotect.const import DOMAIN, MIN_REQUIRED_PROTECT_V from homeassistant.components.unifiprotect.const import DOMAIN
from homeassistant.const import Platform from homeassistant.const import Platform
from homeassistant.core import HomeAssistant, split_entity_id from homeassistant.core import HomeAssistant, split_entity_id
from homeassistant.helpers import entity_registry as er from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.entity import EntityDescription from homeassistant.helpers.entity import EntityDescription
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
from tests.common import MockConfigEntry, async_fire_time_changed from tests.common import MockConfigEntry, async_fire_time_changed, load_fixture
MAC_ADDR = "aa:bb:cc:dd:ee:ff" MAC_ADDR = "aa:bb:cc:dd:ee:ff"
@dataclass
class MockPortData:
"""Mock Port information."""
rtsp: int = 7441
rtsps: int = 7447
@dataclass
class MockDoorbellSettings:
"""Mock Port information."""
default_message_text = "Welcome"
all_messages = [
DoorbellMessage(
type=DoorbellMessageType.LEAVE_PACKAGE_AT_DOOR,
text=DoorbellMessageType.LEAVE_PACKAGE_AT_DOOR.value.replace("_", " "),
),
DoorbellMessage(
type=DoorbellMessageType.DO_NOT_DISTURB,
text=DoorbellMessageType.DO_NOT_DISTURB.value.replace("_", " "),
),
DoorbellMessage(
type=DoorbellMessageType.CUSTOM_MESSAGE,
text="Test",
),
]
@dataclass
class MockNvrData:
"""Mock for NVR."""
version: Version
mac: str
name: str
id: str
ports: MockPortData = MockPortData()
doorbell_settings = MockDoorbellSettings()
update_all_messages = Mock()
model: ModelType = ModelType.NVR
@dataclass @dataclass
class MockBootstrap: class MockBootstrap:
"""Mock for Bootstrap.""" """Mock for Bootstrap."""
nvr: MockNvrData nvr: NVR
cameras: dict[str, Any] cameras: dict[str, Any]
lights: dict[str, Any] lights: dict[str, Any]
sensors: dict[str, Any] sensors: dict[str, Any]
@ -99,28 +55,51 @@ class MockEntityFixture:
api: Mock api: Mock
MOCK_NVR_DATA = MockNvrData( @pytest.fixture(name="mock_nvr")
version=MIN_REQUIRED_PROTECT_V, mac=MAC_ADDR, name="UnifiProtect", id="test_id" def mock_nvr_fixture():
) """Mock UniFi Protect Camera device."""
MOCK_OLD_NVR_DATA = MockNvrData(
version=Version("1.19.0"), mac=MAC_ADDR, name="UnifiProtect", id="test_id"
)
MOCK_BOOTSTRAP = MockBootstrap( data = json.loads(load_fixture("sample_nvr.json", integration=DOMAIN))
nvr=MOCK_NVR_DATA, cameras={}, lights={}, sensors={}, viewers={}, liveviews={} nvr = NVR.from_unifi_dict(**data)
# disable pydantic validation so mocking can happen
NVR.__config__.validate_assignment = False
yield nvr
NVR.__config__.validate_assignment = True
@pytest.fixture(name="mock_old_nvr")
def mock_old_nvr_fixture():
"""Mock UniFi Protect Camera device."""
data = json.loads(load_fixture("sample_nvr.json", integration=DOMAIN))
data["version"] = "1.19.0"
return NVR.from_unifi_dict(**data)
@pytest.fixture(name="mock_bootstrap")
def mock_bootstrap_fixture(mock_nvr: NVR):
"""Mock Bootstrap fixture."""
return MockBootstrap(
nvr=mock_nvr, cameras={}, lights={}, sensors={}, viewers={}, liveviews={}
) )
@pytest.fixture @pytest.fixture
def mock_client(): def mock_client(mock_bootstrap: MockBootstrap):
"""Mock ProtectApiClient for testing.""" """Mock ProtectApiClient for testing."""
client = Mock() client = Mock()
client.bootstrap = MOCK_BOOTSTRAP client.bootstrap = mock_bootstrap
nvr = mock_bootstrap.nvr
nvr._api = client
client.base_url = "https://127.0.0.1" client.base_url = "https://127.0.0.1"
client.connection_host = IPv4Address("127.0.0.1") client.connection_host = IPv4Address("127.0.0.1")
client.get_nvr = AsyncMock(return_value=MOCK_NVR_DATA) client.get_nvr = AsyncMock(return_value=nvr)
client.update = AsyncMock(return_value=MOCK_BOOTSTRAP) client.update = AsyncMock(return_value=mock_bootstrap)
client.async_disconnect_ws = AsyncMock() client.async_disconnect_ws = AsyncMock()
def subscribe(ws_callback: Callable[[WSSubscriptionMessage], None]) -> Any: def subscribe(ws_callback: Callable[[WSSubscriptionMessage], None]) -> Any:
@ -162,44 +141,40 @@ def mock_entry(
def mock_liveview(): def mock_liveview():
"""Mock UniFi Protect Camera device.""" """Mock UniFi Protect Camera device."""
path = Path(__file__).parent / "sample_data" / "sample_liveview.json" data = json.loads(load_fixture("sample_liveview.json", integration=DOMAIN))
with open(path, encoding="utf-8") as json_file: return Liveview.from_unifi_dict(**data)
data = json.load(json_file)
yield Liveview.from_unifi_dict(**data)
@pytest.fixture @pytest.fixture
def mock_camera(): def mock_camera():
"""Mock UniFi Protect Camera device.""" """Mock UniFi Protect Camera device."""
path = Path(__file__).parent / "sample_data" / "sample_camera.json" data = json.loads(load_fixture("sample_camera.json", integration=DOMAIN))
with open(path, encoding="utf-8") as json_file: return Camera.from_unifi_dict(**data)
data = json.load(json_file)
yield Camera.from_unifi_dict(**data)
@pytest.fixture @pytest.fixture
def mock_light(): def mock_light():
"""Mock UniFi Protect Camera device.""" """Mock UniFi Protect Camera device."""
path = Path(__file__).parent / "sample_data" / "sample_light.json" data = json.loads(load_fixture("sample_light.json", integration=DOMAIN))
with open(path, encoding="utf-8") as json_file: return Light.from_unifi_dict(**data)
data = json.load(json_file)
yield Light.from_unifi_dict(**data)
@pytest.fixture @pytest.fixture
def mock_viewer(): def mock_viewer():
"""Mock UniFi Protect Viewport device.""" """Mock UniFi Protect Viewport device."""
path = Path(__file__).parent / "sample_data" / "sample_viewport.json" data = json.loads(load_fixture("sample_viewport.json", integration=DOMAIN))
with open(path, encoding="utf-8") as json_file: return Viewer.from_unifi_dict(**data)
data = json.load(json_file)
yield Viewer.from_unifi_dict(**data)
@pytest.fixture
def mock_sensor():
"""Mock UniFi Protect Sensor device."""
data = json.loads(load_fixture("sample_sensor.json", integration=DOMAIN))
return Sensor.from_unifi_dict(**data)
async def time_changed(hass: HomeAssistant, seconds: int) -> None: async def time_changed(hass: HomeAssistant, seconds: int) -> None:

View File

@ -0,0 +1,236 @@
{
"mac": "A1E00C826924",
"host": "192.168.216.198",
"name": "UnifiProtect",
"canAutoUpdate": true,
"isStatsGatheringEnabled": true,
"timezone": "America/New_York",
"version": "1.21.0-beta.2",
"ucoreVersion": "2.3.26",
"firmwareVersion": "2.3.10",
"uiVersion": null,
"hardwarePlatform": "al324",
"ports": {
"ump": 7449,
"http": 7080,
"https": 7443,
"rtsp": 7447,
"rtsps": 7441,
"rtmp": 1935,
"devicesWss": 7442,
"cameraHttps": 7444,
"cameraTcp": 7877,
"liveWs": 7445,
"liveWss": 7446,
"tcpStreams": 7448,
"playback": 7450,
"emsCLI": 7440,
"emsLiveFLV": 7550,
"cameraEvents": 7551,
"tcpBridge": 7888,
"ucore": 11081,
"discoveryClient": 0
},
"uptime": 1191516000,
"lastSeen": 1641269019283,
"isUpdating": false,
"lastUpdateAt": null,
"isStation": false,
"enableAutomaticBackups": true,
"enableStatsReporting": false,
"isSshEnabled": false,
"errorCode": null,
"releaseChannel": "beta",
"ssoChannel": null,
"hosts": [
"192.168.216.198"
],
"enableBridgeAutoAdoption": true,
"hardwareId": "baf4878d-df21-4427-9fbe-c2ef15301412",
"hardwareRevision": "113-03137-22",
"hostType": 59936,
"hostShortname": "UNVRPRO",
"isHardware": true,
"isWirelessUplinkEnabled": false,
"timeFormat": "24h",
"temperatureUnit": "C",
"recordingRetentionDurationMs": null,
"enableCrashReporting": true,
"disableAudio": false,
"analyticsData": "anonymous",
"anonymousDeviceId": "65257f7d-874c-498a-8f1b-00b2dd0a7ae1",
"cameraUtilization": 30,
"isRecycling": false,
"avgMotions": [
21.29,
14,
5.43,
2.29,
6.43,
7.43,
16.86,
17,
24.71,
36.86,
46.43,
47.57,
51.57,
52.71,
63.86,
80.86,
86.71,
91.71,
96.57,
71.14,
57,
53.71,
39.57,
21.29
],
"disableAutoLink": false,
"skipFirmwareUpdate": false,
"wifiSettings": {
"useThirdPartyWifi": false,
"ssid": null,
"password": null
},
"locationSettings": {
"isAway": true,
"isGeofencingEnabled": false,
"latitude": 41.4519,
"longitude": -81.921,
"radius": 200
},
"featureFlags": {
"beta": false,
"dev": false,
"notificationsV2": true
},
"systemInfo": {
"cpu": {
"averageLoad": 5,
"temperature": 70
},
"memory": {
"available": 6481504,
"free": 87080,
"total": 8163024
},
"storage": {
"available": 21796939214848,
"isRecycling": false,
"size": 31855989432320,
"type": "raid",
"used": 8459815895040,
"devices": [
{
"model": "ST16000VE000-2L2103",
"size": 16000900661248,
"healthy": true
},
{
"model": "ST16000VE000-2L2103",
"size": 16000900661248,
"healthy": true
},
{
"model": "ST16000VE000-2L2103",
"size": 16000900661248,
"healthy": true
}
]
},
"tmpfs": {
"available": 934204,
"total": 1048576,
"used": 114372,
"path": "/var/opt/unifi-protect/tmp"
}
},
"doorbellSettings": {
"defaultMessageText": "Welcome",
"defaultMessageResetTimeoutMs": 60000,
"customMessages": [
"Come In!",
"Use Other Door"
],
"allMessages": [
{
"type": "LEAVE_PACKAGE_AT_DOOR",
"text": "LEAVE PACKAGE AT DOOR"
},
{
"type": "DO_NOT_DISTURB",
"text": "DO NOT DISTURB"
},
{
"type": "CUSTOM_MESSAGE",
"text": "Test"
}
]
},
"smartDetectAgreement": {
"status": "agreed",
"lastUpdateAt": 1606964227734
},
"storageStats": {
"utilization": 26.61384533704469,
"capacity": 5706909122,
"remainingCapacity": 4188081155,
"recordingSpace": {
"total": 31787269955584,
"used": 8459814862848,
"available": 23327455092736
},
"storageDistribution": {
"recordingTypeDistributions": [
{
"recordingType": "rotating",
"size": 7736989099040,
"percentage": 91.47686438351941
},
{
"recordingType": "timelapse",
"size": 21474836480,
"percentage": 0.2539037704709915
},
{
"recordingType": "detections",
"size": 699400412128,
"percentage": 8.269231846009593
}
],
"resolutionDistributions": [
{
"resolution": "HD",
"size": 2896955441152,
"percentage": 9.113571077981481
},
{
"resolution": "4K",
"size": 5560908906496,
"percentage": 17.494138107066746
},
{
"resolution": "free",
"size": 23329405607936,
"percentage": 73.39229081495176
}
]
}
},
"id": "test_id",
"isAway": true,
"isSetup": true,
"network": "Ethernet",
"type": "UNVR-PRO",
"upSince": 1640077503063,
"isRecordingDisabled": false,
"isRecordingMotionOnly": false,
"maxCameraCapacity": {
"4K": 20,
"2K": 30,
"HD": 60
},
"modelKey": "nvr"
}

View File

@ -0,0 +1,92 @@
{
"mac": "26DBAFF133A4",
"connectionHost": "192.168.216.198",
"type": "UFP-SENSE",
"name": "Egdczv Urg",
"upSince": 1641256963255,
"uptime": null,
"lastSeen": 1641259127934,
"connectedSince": 1641259139255,
"state": "CONNECTED",
"hardwareRevision": 6,
"firmwareVersion": "1.0.2",
"latestFirmwareVersion": "1.0.2",
"firmwareBuild": null,
"isUpdating": false,
"isAdopting": false,
"isAdopted": true,
"isAdoptedByOther": false,
"isProvisioned": false,
"isRebooting": false,
"isSshEnabled": false,
"canAdopt": false,
"isAttemptingToConnect": false,
"isMotionDetected": false,
"mountType": "door",
"leakDetectedAt": null,
"tamperingDetectedAt": null,
"isOpened": true,
"openStatusChangedAt": 1641269036582,
"alarmTriggeredAt": null,
"motionDetectedAt": 1641269044824,
"wiredConnectionState": {
"phyRate": null
},
"stats": {
"light": {
"value": 0,
"status": "neutral"
},
"humidity": {
"value": 35,
"status": "neutral"
},
"temperature": {
"value": 17.23,
"status": "neutral"
}
},
"bluetoothConnectionState": {
"signalQuality": 15,
"signalStrength": -84
},
"batteryStatus": {
"percentage": 100,
"isLow": false
},
"alarmSettings": {
"isEnabled": false
},
"lightSettings": {
"isEnabled": true,
"lowThreshold": null,
"highThreshold": null,
"margin": 10
},
"motionSettings": {
"isEnabled": true,
"sensitivity": 100
},
"temperatureSettings": {
"isEnabled": true,
"lowThreshold": null,
"highThreshold": null,
"margin": 0.1
},
"humiditySettings": {
"isEnabled": true,
"lowThreshold": null,
"highThreshold": null,
"margin": 1
},
"ledSettings": {
"isEnabled": true
},
"bridge": "61b3f5c90050a703e700042a",
"camera": "2f9beb2e6f79af3c32c22d49",
"bridgeCandidates": [],
"id": "f6ecbe829f81cc79ad6e0c9a",
"isConnected": true,
"marketName": "UP Sense",
"modelKey": "sensor"
}

View File

@ -37,7 +37,7 @@ async def camera_fixture(
assert_entity_counts(hass, Platform.BUTTON, 1, 0) assert_entity_counts(hass, Platform.BUTTON, 1, 0)
yield (camera_obj, "button.test_camera_reboot_device") return (camera_obj, "button.test_camera_reboot_device")
async def test_button( async def test_button(

View File

@ -70,7 +70,7 @@ async def camera_fixture(
assert_entity_counts(hass, Platform.CAMERA, 2, 1) assert_entity_counts(hass, Platform.CAMERA, 2, 1)
yield (camera_obj, "camera.test_camera_high") return (camera_obj, "camera.test_camera_high")
def validate_default_camera_entity( def validate_default_camera_entity(

View File

@ -4,6 +4,7 @@ from __future__ import annotations
from unittest.mock import patch from unittest.mock import patch
from pyunifiprotect import NotAuthorized, NvrError from pyunifiprotect import NotAuthorized, NvrError
from pyunifiprotect.data.nvr import NVR
from homeassistant import config_entries from homeassistant import config_entries
from homeassistant.components.unifiprotect.const import ( from homeassistant.components.unifiprotect.const import (
@ -20,12 +21,12 @@ from homeassistant.data_entry_flow import (
) )
from homeassistant.helpers import device_registry as dr from homeassistant.helpers import device_registry as dr
from .conftest import MAC_ADDR, MOCK_NVR_DATA, MOCK_OLD_NVR_DATA from .conftest import MAC_ADDR
from tests.common import MockConfigEntry from tests.common import MockConfigEntry
async def test_form(hass: HomeAssistant) -> None: async def test_form(hass: HomeAssistant, mock_nvr: NVR) -> None:
"""Test we get the form.""" """Test we get the form."""
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER} DOMAIN, context={"source": config_entries.SOURCE_USER}
@ -35,7 +36,7 @@ async def test_form(hass: HomeAssistant) -> None:
with patch( with patch(
"homeassistant.components.unifiprotect.config_flow.ProtectApiClient.get_nvr", "homeassistant.components.unifiprotect.config_flow.ProtectApiClient.get_nvr",
return_value=MOCK_NVR_DATA, return_value=mock_nvr,
), patch( ), patch(
"homeassistant.components.unifiprotect.async_setup_entry", "homeassistant.components.unifiprotect.async_setup_entry",
return_value=True, return_value=True,
@ -63,7 +64,7 @@ async def test_form(hass: HomeAssistant) -> None:
assert len(mock_setup_entry.mock_calls) == 1 assert len(mock_setup_entry.mock_calls) == 1
async def test_form_version_too_old(hass: HomeAssistant) -> None: async def test_form_version_too_old(hass: HomeAssistant, mock_old_nvr: NVR) -> None:
"""Test we handle the version being too old.""" """Test we handle the version being too old."""
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER} DOMAIN, context={"source": config_entries.SOURCE_USER}
@ -71,7 +72,7 @@ async def test_form_version_too_old(hass: HomeAssistant) -> None:
with patch( with patch(
"homeassistant.components.unifiprotect.config_flow.ProtectApiClient.get_nvr", "homeassistant.components.unifiprotect.config_flow.ProtectApiClient.get_nvr",
return_value=MOCK_OLD_NVR_DATA, return_value=mock_old_nvr,
): ):
result2 = await hass.config_entries.flow.async_configure( result2 = await hass.config_entries.flow.async_configure(
result["flow_id"], result["flow_id"],
@ -132,7 +133,7 @@ async def test_form_cannot_connect(hass: HomeAssistant) -> None:
assert result2["errors"] == {"base": "cannot_connect"} assert result2["errors"] == {"base": "cannot_connect"}
async def test_form_reauth_auth(hass: HomeAssistant) -> None: async def test_form_reauth_auth(hass: HomeAssistant, mock_nvr: NVR) -> None:
"""Test we handle reauth auth.""" """Test we handle reauth auth."""
mock_config = MockConfigEntry( mock_config = MockConfigEntry(
domain=DOMAIN, domain=DOMAIN,
@ -176,7 +177,7 @@ async def test_form_reauth_auth(hass: HomeAssistant) -> None:
with patch( with patch(
"homeassistant.components.unifiprotect.config_flow.ProtectApiClient.get_nvr", "homeassistant.components.unifiprotect.config_flow.ProtectApiClient.get_nvr",
return_value=MOCK_NVR_DATA, return_value=mock_nvr,
): ):
result3 = await hass.config_entries.flow.async_configure( result3 = await hass.config_entries.flow.async_configure(
result2["flow_id"], result2["flow_id"],

View File

@ -4,12 +4,13 @@ from __future__ import annotations
from unittest.mock import AsyncMock from unittest.mock import AsyncMock
from pyunifiprotect import NotAuthorized, NvrError from pyunifiprotect import NotAuthorized, NvrError
from pyunifiprotect.data import NVR
from homeassistant.components.unifiprotect.const import CONF_DISABLE_RTSP from homeassistant.components.unifiprotect.const import CONF_DISABLE_RTSP
from homeassistant.config_entries import ConfigEntryState from homeassistant.config_entries import ConfigEntryState
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from .conftest import MOCK_OLD_NVR_DATA, MockEntityFixture from .conftest import MockEntityFixture
async def test_setup(hass: HomeAssistant, mock_entry: MockEntityFixture): async def test_setup(hass: HomeAssistant, mock_entry: MockEntityFixture):
@ -51,10 +52,12 @@ async def test_unload(hass: HomeAssistant, mock_entry: MockEntityFixture):
assert mock_entry.api.async_disconnect_ws.called assert mock_entry.api.async_disconnect_ws.called
async def test_setup_too_old(hass: HomeAssistant, mock_entry: MockEntityFixture): async def test_setup_too_old(
hass: HomeAssistant, mock_entry: MockEntityFixture, mock_old_nvr: NVR
):
"""Test setup of unifiprotect entry with too old of version of UniFi Protect.""" """Test setup of unifiprotect entry with too old of version of UniFi Protect."""
mock_entry.api.get_nvr.return_value = MOCK_OLD_NVR_DATA mock_entry.api.get_nvr.return_value = mock_old_nvr
await hass.config_entries.async_setup(mock_entry.entry.entry_id) await hass.config_entries.async_setup(mock_entry.entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()

View File

@ -200,10 +200,10 @@ async def test_number_setup_camera_missing_attr(
@pytest.mark.parametrize("description", LIGHT_NUMBERS) @pytest.mark.parametrize("description", LIGHT_NUMBERS)
async def test_switch_light_simple( async def test_number_light_simple(
hass: HomeAssistant, light: Light, description: ProtectNumberEntityDescription hass: HomeAssistant, light: Light, description: ProtectNumberEntityDescription
): ):
"""Tests all simple switches for lights.""" """Tests all simple numbers for lights."""
assert description.ufp_set_function is not None assert description.ufp_set_function is not None
@ -224,10 +224,10 @@ async def test_switch_light_simple(
@pytest.mark.parametrize("description", CAMERA_NUMBERS) @pytest.mark.parametrize("description", CAMERA_NUMBERS)
async def test_switch_camera_simple( async def test_number_camera_simple(
hass: HomeAssistant, camera: Camera, description: ProtectNumberEntityDescription hass: HomeAssistant, camera: Camera, description: ProtectNumberEntityDescription
): ):
"""Tests all simple switches for cameras.""" """Tests all simple numbers for cameras."""
assert description.ufp_set_function is not None assert description.ufp_set_function is not None

View File

@ -1,4 +1,4 @@
"""Test the UniFi Protect number platform.""" """Test the UniFi Protect select platform."""
# pylint: disable=protected-access # pylint: disable=protected-access
from __future__ import annotations from __future__ import annotations
@ -51,7 +51,7 @@ async def viewer_fixture(
mock_viewer: Viewer, mock_viewer: Viewer,
mock_liveview: Liveview, mock_liveview: Liveview,
): ):
"""Fixture for a single viewport for testing the number platform.""" """Fixture for a single viewport for testing the select platform."""
# disable pydantic validation so mocking can happen # disable pydantic validation so mocking can happen
Viewer.__config__.validate_assignment = False Viewer.__config__.validate_assignment = False
@ -81,7 +81,7 @@ async def viewer_fixture(
async def camera_fixture( async def camera_fixture(
hass: HomeAssistant, mock_entry: MockEntityFixture, mock_camera: Camera hass: HomeAssistant, mock_entry: MockEntityFixture, mock_camera: Camera
): ):
"""Fixture for a single camera for testing the switch platform.""" """Fixture for a single camera for testing the select platform."""
# disable pydantic validation so mocking can happen # disable pydantic validation so mocking can happen
Camera.__config__.validate_assignment = False Camera.__config__.validate_assignment = False
@ -119,7 +119,7 @@ async def light_fixture(
mock_light: Light, mock_light: Light,
camera: Camera, camera: Camera,
): ):
"""Fixture for a single light for testing the number platform.""" """Fixture for a single light for testing the select platform."""
# disable pydantic validation so mocking can happen # disable pydantic validation so mocking can happen
Light.__config__.validate_assignment = False Light.__config__.validate_assignment = False
@ -151,7 +151,7 @@ async def light_fixture(
async def camera_none_fixture( async def camera_none_fixture(
hass: HomeAssistant, mock_entry: MockEntityFixture, mock_camera: Camera hass: HomeAssistant, mock_entry: MockEntityFixture, mock_camera: Camera
): ):
"""Fixture for a single camera for testing the switch platform.""" """Fixture for a single camera for testing the select platform."""
# disable pydantic validation so mocking can happen # disable pydantic validation so mocking can happen
Camera.__config__.validate_assignment = False Camera.__config__.validate_assignment = False
@ -228,11 +228,11 @@ async def test_select_setup_viewer(
assert state.attributes[ATTR_ATTRIBUTION] == DEFAULT_ATTRIBUTION assert state.attributes[ATTR_ATTRIBUTION] == DEFAULT_ATTRIBUTION
async def test_number_setup_camera_all( async def test_select_setup_camera_all(
hass: HomeAssistant, hass: HomeAssistant,
camera: Camera, camera: Camera,
): ):
"""Test number entity setup for camera devices (all features).""" """Test select entity setup for camera devices (all features)."""
entity_registry = er.async_get(hass) entity_registry = er.async_get(hass)
expected_values = ("Always", "Auto", "Default Message (Welcome)") expected_values = ("Always", "Auto", "Default Message (Welcome)")
@ -252,11 +252,11 @@ async def test_number_setup_camera_all(
assert state.attributes[ATTR_ATTRIBUTION] == DEFAULT_ATTRIBUTION assert state.attributes[ATTR_ATTRIBUTION] == DEFAULT_ATTRIBUTION
async def test_number_setup_camera_none( async def test_select_setup_camera_none(
hass: HomeAssistant, hass: HomeAssistant,
camera_none: Camera, camera_none: Camera,
): ):
"""Test number entity setup for camera devices (no features).""" """Test select entity setup for camera devices (no features)."""
entity_registry = er.async_get(hass) entity_registry = er.async_get(hass)
expected_values = ("Always", "Auto", "Default Message (Welcome)") expected_values = ("Always", "Auto", "Default Message (Welcome)")
@ -332,6 +332,9 @@ async def test_select_update_doorbell_settings(
expected_length += 1 expected_length += 1
new_nvr = copy(mock_entry.api.bootstrap.nvr) new_nvr = copy(mock_entry.api.bootstrap.nvr)
new_nvr.__fields__["update_all_messages"] = Mock()
new_nvr.update_all_messages = Mock()
new_nvr.doorbell_settings.all_messages = [ new_nvr.doorbell_settings.all_messages = [
*new_nvr.doorbell_settings.all_messages, *new_nvr.doorbell_settings.all_messages,
DoorbellMessage( DoorbellMessage(
@ -615,7 +618,7 @@ async def test_select_service_doorbell_invalid(
blocking=True, blocking=True,
) )
camera.set_lcd_text.assert_not_called assert not camera.set_lcd_text.called
async def test_select_service_doorbell_success( async def test_select_service_doorbell_success(