core/tests/components/unifiprotect/test_number.py

243 lines
7.6 KiB
Python

"""Test the UniFi Protect number platform."""
from __future__ import annotations
from datetime import timedelta
from unittest.mock import AsyncMock, Mock
import pytest
from uiprotect.data import Camera, Doorlock, IRLEDMode, Light
from homeassistant.components.unifiprotect.const import DEFAULT_ATTRIBUTION
from homeassistant.components.unifiprotect.number import (
CAMERA_NUMBERS,
DOORLOCK_NUMBERS,
LIGHT_NUMBERS,
ProtectNumberEntityDescription,
)
from homeassistant.const import ATTR_ATTRIBUTION, ATTR_ENTITY_ID, Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from .utils import (
MockUFPFixture,
adopt_devices,
assert_entity_counts,
ids_from_device_description,
init_entry,
remove_entities,
)
async def test_number_sensor_camera_remove(
hass: HomeAssistant, ufp: MockUFPFixture, camera: Camera, unadopted_camera: Camera
) -> None:
"""Test removing and re-adding a camera device."""
await init_entry(hass, ufp, [camera, unadopted_camera])
assert_entity_counts(hass, Platform.NUMBER, 4, 4)
await remove_entities(hass, ufp, [camera, unadopted_camera])
assert_entity_counts(hass, Platform.NUMBER, 0, 0)
await adopt_devices(hass, ufp, [camera, unadopted_camera])
assert_entity_counts(hass, Platform.NUMBER, 4, 4)
async def test_number_sensor_light_remove(
hass: HomeAssistant, ufp: MockUFPFixture, light: Light
) -> None:
"""Test removing and re-adding a light device."""
await init_entry(hass, ufp, [light])
assert_entity_counts(hass, Platform.NUMBER, 2, 2)
await remove_entities(hass, ufp, [light])
assert_entity_counts(hass, Platform.NUMBER, 0, 0)
await adopt_devices(hass, ufp, [light])
assert_entity_counts(hass, Platform.NUMBER, 2, 2)
async def test_number_lock_remove(
hass: HomeAssistant, ufp: MockUFPFixture, doorlock: Doorlock
) -> None:
"""Test removing and re-adding a light device."""
await init_entry(hass, ufp, [doorlock])
assert_entity_counts(hass, Platform.NUMBER, 1, 1)
await remove_entities(hass, ufp, [doorlock])
assert_entity_counts(hass, Platform.NUMBER, 0, 0)
await adopt_devices(hass, ufp, [doorlock])
assert_entity_counts(hass, Platform.NUMBER, 1, 1)
async def test_number_setup_light(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
ufp: MockUFPFixture,
light: Light,
) -> None:
"""Test number entity setup for light devices."""
await init_entry(hass, ufp, [light])
assert_entity_counts(hass, Platform.NUMBER, 2, 2)
for description in LIGHT_NUMBERS:
unique_id, entity_id = ids_from_device_description(
Platform.NUMBER, light, description
)
entity = entity_registry.async_get(entity_id)
assert entity
assert entity.unique_id == unique_id
state = hass.states.get(entity_id)
assert state
assert state.state == "45"
assert state.attributes[ATTR_ATTRIBUTION] == DEFAULT_ATTRIBUTION
async def test_number_setup_camera_all(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
ufp: MockUFPFixture,
camera: Camera,
) -> None:
"""Test number entity setup for camera devices (all features)."""
camera.feature_flags.has_chime = True
camera.chime_duration = timedelta(seconds=1)
camera.feature_flags.has_led_ir = True
camera.isp_settings.icr_custom_value = 1
camera.isp_settings.ir_led_mode = IRLEDMode.CUSTOM
await init_entry(hass, ufp, [camera])
assert_entity_counts(hass, Platform.NUMBER, 5, 5)
for description in CAMERA_NUMBERS:
unique_id, entity_id = ids_from_device_description(
Platform.NUMBER, camera, description
)
entity = entity_registry.async_get(entity_id)
assert entity
assert entity.unique_id == unique_id
state = hass.states.get(entity_id)
assert state
assert state.state == "1"
assert state.attributes[ATTR_ATTRIBUTION] == DEFAULT_ATTRIBUTION
async def test_number_setup_camera_none(
hass: HomeAssistant, ufp: MockUFPFixture, camera: Camera
) -> None:
"""Test number entity setup for camera devices (no features)."""
camera.feature_flags.can_optical_zoom = False
camera.feature_flags.has_mic = False
# has_wdr is an the inverse of has HDR
camera.feature_flags.has_hdr = True
camera.feature_flags.has_led_ir = False
await init_entry(hass, ufp, [camera])
assert_entity_counts(hass, Platform.NUMBER, 0, 0)
async def test_number_setup_camera_missing_attr(
hass: HomeAssistant, ufp: MockUFPFixture, camera: Camera
) -> None:
"""Test number entity setup for camera devices (no features, bad attrs)."""
camera.feature_flags = None
await init_entry(hass, ufp, [camera])
assert_entity_counts(hass, Platform.NUMBER, 0, 0)
async def test_number_light_sensitivity(
hass: HomeAssistant, ufp: MockUFPFixture, light: Light
) -> None:
"""Test sensitivity number entity for lights."""
await init_entry(hass, ufp, [light])
assert_entity_counts(hass, Platform.NUMBER, 2, 2)
description = LIGHT_NUMBERS[0]
assert description.ufp_set_method is not None
light.__fields__["set_sensitivity"] = Mock(final=False)
light.set_sensitivity = AsyncMock()
_, entity_id = ids_from_device_description(Platform.NUMBER, light, description)
await hass.services.async_call(
"number", "set_value", {ATTR_ENTITY_ID: entity_id, "value": 15.0}, blocking=True
)
light.set_sensitivity.assert_called_once_with(15.0)
async def test_number_light_duration(
hass: HomeAssistant, ufp: MockUFPFixture, light: Light
) -> None:
"""Test auto-shutoff duration number entity for lights."""
await init_entry(hass, ufp, [light])
assert_entity_counts(hass, Platform.NUMBER, 2, 2)
description = LIGHT_NUMBERS[1]
light.__fields__["set_duration"] = Mock(final=False)
light.set_duration = AsyncMock()
_, entity_id = ids_from_device_description(Platform.NUMBER, light, description)
await hass.services.async_call(
"number", "set_value", {ATTR_ENTITY_ID: entity_id, "value": 15.0}, blocking=True
)
light.set_duration.assert_called_once_with(timedelta(seconds=15.0))
@pytest.mark.parametrize("description", CAMERA_NUMBERS)
async def test_number_camera_simple(
hass: HomeAssistant,
ufp: MockUFPFixture,
camera: Camera,
description: ProtectNumberEntityDescription,
) -> None:
"""Tests all simple numbers for cameras."""
await init_entry(hass, ufp, [camera])
assert_entity_counts(hass, Platform.NUMBER, 4, 4)
assert description.ufp_set_method is not None
camera.__fields__[description.ufp_set_method] = Mock(final=False)
setattr(camera, description.ufp_set_method, AsyncMock())
_, entity_id = ids_from_device_description(Platform.NUMBER, camera, description)
await hass.services.async_call(
"number", "set_value", {ATTR_ENTITY_ID: entity_id, "value": 1.0}, blocking=True
)
async def test_number_lock_auto_close(
hass: HomeAssistant, ufp: MockUFPFixture, doorlock: Doorlock
) -> None:
"""Test auto-lock timeout for locks."""
await init_entry(hass, ufp, [doorlock])
assert_entity_counts(hass, Platform.NUMBER, 1, 1)
description = DOORLOCK_NUMBERS[0]
doorlock.__fields__["set_auto_close_time"] = Mock(final=False)
doorlock.set_auto_close_time = AsyncMock()
_, entity_id = ids_from_device_description(Platform.NUMBER, doorlock, description)
await hass.services.async_call(
"number", "set_value", {ATTR_ENTITY_ID: entity_id, "value": 15.0}, blocking=True
)
doorlock.set_auto_close_time.assert_called_once_with(timedelta(seconds=15.0))