691 lines
19 KiB
Python
691 lines
19 KiB
Python
"""Test the UniFi Protect select platform."""
|
|
# pylint: disable=protected-access
|
|
from __future__ import annotations
|
|
|
|
from copy import copy
|
|
from datetime import timedelta
|
|
from unittest.mock import AsyncMock, Mock, patch
|
|
|
|
import pytest
|
|
from pyunifiprotect.data import Camera, Light
|
|
from pyunifiprotect.data.devices import LCDMessage, Viewer
|
|
from pyunifiprotect.data.nvr import DoorbellMessage, Liveview
|
|
from pyunifiprotect.data.types import (
|
|
DoorbellMessageType,
|
|
IRLEDMode,
|
|
LightModeEnableType,
|
|
LightModeType,
|
|
RecordingMode,
|
|
)
|
|
|
|
from homeassistant.components.select.const import ATTR_OPTIONS
|
|
from homeassistant.components.unifiprotect.const import (
|
|
ATTR_DURATION,
|
|
ATTR_MESSAGE,
|
|
DEFAULT_ATTRIBUTION,
|
|
)
|
|
from homeassistant.components.unifiprotect.select import (
|
|
CAMERA_SELECTS,
|
|
LIGHT_MODE_OFF,
|
|
LIGHT_SELECTS,
|
|
SERVICE_SET_DOORBELL_MESSAGE,
|
|
VIEWER_SELECTS,
|
|
)
|
|
from homeassistant.const import ATTR_ATTRIBUTION, ATTR_ENTITY_ID, ATTR_OPTION, Platform
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.exceptions import HomeAssistantError
|
|
from homeassistant.helpers import entity_registry as er
|
|
from homeassistant.util.dt import utcnow
|
|
|
|
from .conftest import (
|
|
MockEntityFixture,
|
|
assert_entity_counts,
|
|
ids_from_device_description,
|
|
)
|
|
|
|
|
|
@pytest.fixture(name="viewer")
|
|
async def viewer_fixture(
|
|
hass: HomeAssistant,
|
|
mock_entry: MockEntityFixture,
|
|
mock_viewer: Viewer,
|
|
mock_liveview: Liveview,
|
|
):
|
|
"""Fixture for a single viewport for testing the select platform."""
|
|
|
|
# disable pydantic validation so mocking can happen
|
|
Viewer.__config__.validate_assignment = False
|
|
|
|
viewer_obj = mock_viewer.copy(deep=True)
|
|
viewer_obj._api = mock_entry.api
|
|
viewer_obj.name = "Test Viewer"
|
|
viewer_obj.liveview_id = mock_liveview.id
|
|
|
|
mock_entry.api.bootstrap.reset_objects()
|
|
mock_entry.api.bootstrap.viewers = {
|
|
viewer_obj.id: viewer_obj,
|
|
}
|
|
mock_entry.api.bootstrap.liveviews = {mock_liveview.id: mock_liveview}
|
|
|
|
await hass.config_entries.async_setup(mock_entry.entry.entry_id)
|
|
await hass.async_block_till_done()
|
|
|
|
assert_entity_counts(hass, Platform.SELECT, 1, 1)
|
|
|
|
yield viewer_obj
|
|
|
|
Viewer.__config__.validate_assignment = True
|
|
|
|
|
|
@pytest.fixture(name="camera")
|
|
async def camera_fixture(
|
|
hass: HomeAssistant, mock_entry: MockEntityFixture, mock_camera: Camera
|
|
):
|
|
"""Fixture for a single camera for testing the select platform."""
|
|
|
|
# disable pydantic validation so mocking can happen
|
|
Camera.__config__.validate_assignment = False
|
|
|
|
camera_obj = mock_camera.copy(deep=True)
|
|
camera_obj._api = mock_entry.api
|
|
camera_obj.channels[0]._api = mock_entry.api
|
|
camera_obj.channels[1]._api = mock_entry.api
|
|
camera_obj.channels[2]._api = mock_entry.api
|
|
camera_obj.name = "Test Camera"
|
|
camera_obj.feature_flags.has_lcd_screen = True
|
|
camera_obj.feature_flags.has_chime = True
|
|
camera_obj.recording_settings.mode = RecordingMode.ALWAYS
|
|
camera_obj.isp_settings.ir_led_mode = IRLEDMode.AUTO
|
|
camera_obj.lcd_message = None
|
|
camera_obj.chime_duration = 0
|
|
|
|
mock_entry.api.bootstrap.reset_objects()
|
|
mock_entry.api.bootstrap.cameras = {
|
|
camera_obj.id: camera_obj,
|
|
}
|
|
|
|
await hass.config_entries.async_setup(mock_entry.entry.entry_id)
|
|
await hass.async_block_till_done()
|
|
|
|
assert_entity_counts(hass, Platform.SELECT, 4, 4)
|
|
|
|
yield camera_obj
|
|
|
|
Camera.__config__.validate_assignment = True
|
|
|
|
|
|
@pytest.fixture(name="light")
|
|
async def light_fixture(
|
|
hass: HomeAssistant,
|
|
mock_entry: MockEntityFixture,
|
|
mock_light: Light,
|
|
camera: Camera,
|
|
):
|
|
"""Fixture for a single light for testing the select platform."""
|
|
|
|
# disable pydantic validation so mocking can happen
|
|
Light.__config__.validate_assignment = False
|
|
|
|
light_obj = mock_light.copy(deep=True)
|
|
light_obj._api = mock_entry.api
|
|
light_obj.name = "Test Light"
|
|
light_obj.camera_id = None
|
|
light_obj.light_mode_settings.mode = LightModeType.MOTION
|
|
light_obj.light_mode_settings.enable_at = LightModeEnableType.DARK
|
|
|
|
mock_entry.api.bootstrap.reset_objects()
|
|
mock_entry.api.bootstrap.cameras = {camera.id: camera}
|
|
mock_entry.api.bootstrap.lights = {
|
|
light_obj.id: light_obj,
|
|
}
|
|
|
|
await hass.config_entries.async_reload(mock_entry.entry.entry_id)
|
|
await hass.async_block_till_done()
|
|
|
|
assert_entity_counts(hass, Platform.SELECT, 6, 6)
|
|
|
|
yield light_obj
|
|
|
|
Light.__config__.validate_assignment = True
|
|
|
|
|
|
@pytest.fixture(name="camera_none")
|
|
async def camera_none_fixture(
|
|
hass: HomeAssistant, mock_entry: MockEntityFixture, mock_camera: Camera
|
|
):
|
|
"""Fixture for a single camera for testing the select platform."""
|
|
|
|
# disable pydantic validation so mocking can happen
|
|
Camera.__config__.validate_assignment = False
|
|
|
|
camera_obj = mock_camera.copy(deep=True)
|
|
camera_obj._api = mock_entry.api
|
|
camera_obj.channels[0]._api = mock_entry.api
|
|
camera_obj.channels[1]._api = mock_entry.api
|
|
camera_obj.channels[2]._api = mock_entry.api
|
|
camera_obj.name = "Test Camera"
|
|
camera_obj.feature_flags.has_lcd_screen = False
|
|
camera_obj.feature_flags.has_chime = False
|
|
camera_obj.recording_settings.mode = RecordingMode.ALWAYS
|
|
camera_obj.isp_settings.ir_led_mode = IRLEDMode.AUTO
|
|
|
|
mock_entry.api.bootstrap.reset_objects()
|
|
mock_entry.api.bootstrap.cameras = {
|
|
camera_obj.id: camera_obj,
|
|
}
|
|
|
|
await hass.config_entries.async_setup(mock_entry.entry.entry_id)
|
|
await hass.async_block_till_done()
|
|
|
|
assert_entity_counts(hass, Platform.SELECT, 2, 2)
|
|
|
|
yield camera_obj
|
|
|
|
Camera.__config__.validate_assignment = True
|
|
|
|
|
|
async def test_select_setup_light(
|
|
hass: HomeAssistant,
|
|
light: Light,
|
|
):
|
|
"""Test select entity setup for light devices."""
|
|
|
|
entity_registry = er.async_get(hass)
|
|
expected_values = ("On Motion - When Dark", "Not Paired")
|
|
|
|
for index, description in enumerate(LIGHT_SELECTS):
|
|
unique_id, entity_id = ids_from_device_description(
|
|
Platform.SELECT, 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 == expected_values[index]
|
|
assert state.attributes[ATTR_ATTRIBUTION] == DEFAULT_ATTRIBUTION
|
|
|
|
|
|
async def test_select_setup_viewer(
|
|
hass: HomeAssistant,
|
|
viewer: Viewer,
|
|
):
|
|
"""Test select entity setup for light devices."""
|
|
|
|
entity_registry = er.async_get(hass)
|
|
description = VIEWER_SELECTS[0]
|
|
|
|
unique_id, entity_id = ids_from_device_description(
|
|
Platform.SELECT, viewer, 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 == viewer.liveview.name
|
|
assert state.attributes[ATTR_ATTRIBUTION] == DEFAULT_ATTRIBUTION
|
|
|
|
|
|
async def test_select_setup_camera_all(
|
|
hass: HomeAssistant,
|
|
camera: Camera,
|
|
):
|
|
"""Test select entity setup for camera devices (all features)."""
|
|
|
|
entity_registry = er.async_get(hass)
|
|
expected_values = ("Always", "Auto", "Default Message (Welcome)", "None")
|
|
|
|
for index, description in enumerate(CAMERA_SELECTS):
|
|
unique_id, entity_id = ids_from_device_description(
|
|
Platform.SELECT, 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 == expected_values[index]
|
|
assert state.attributes[ATTR_ATTRIBUTION] == DEFAULT_ATTRIBUTION
|
|
|
|
|
|
async def test_select_setup_camera_none(
|
|
hass: HomeAssistant,
|
|
camera_none: Camera,
|
|
):
|
|
"""Test select entity setup for camera devices (no features)."""
|
|
|
|
entity_registry = er.async_get(hass)
|
|
expected_values = ("Always", "Auto", "Default Message (Welcome)")
|
|
|
|
for index, description in enumerate(CAMERA_SELECTS):
|
|
if index == 2:
|
|
return
|
|
|
|
unique_id, entity_id = ids_from_device_description(
|
|
Platform.SELECT, camera_none, 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 == expected_values[index]
|
|
assert state.attributes[ATTR_ATTRIBUTION] == DEFAULT_ATTRIBUTION
|
|
|
|
|
|
async def test_select_update_liveview(
|
|
hass: HomeAssistant,
|
|
mock_entry: MockEntityFixture,
|
|
viewer: Viewer,
|
|
mock_liveview: Liveview,
|
|
):
|
|
"""Test select entity update (new Liveview)."""
|
|
|
|
_, entity_id = ids_from_device_description(
|
|
Platform.SELECT, viewer, VIEWER_SELECTS[0]
|
|
)
|
|
|
|
state = hass.states.get(entity_id)
|
|
assert state
|
|
expected_options = state.attributes[ATTR_OPTIONS]
|
|
|
|
new_bootstrap = copy(mock_entry.api.bootstrap)
|
|
new_liveview = copy(mock_liveview)
|
|
new_liveview.id = "test_id"
|
|
|
|
mock_msg = Mock()
|
|
mock_msg.changed_data = {}
|
|
mock_msg.new_obj = new_liveview
|
|
|
|
new_bootstrap.liveviews = {**new_bootstrap.liveviews, new_liveview.id: new_liveview}
|
|
mock_entry.api.bootstrap = new_bootstrap
|
|
mock_entry.api.ws_subscription(mock_msg)
|
|
await hass.async_block_till_done()
|
|
|
|
state = hass.states.get(entity_id)
|
|
assert state
|
|
assert state.attributes[ATTR_OPTIONS] == expected_options
|
|
|
|
|
|
async def test_select_update_doorbell_settings(
|
|
hass: HomeAssistant, mock_entry: MockEntityFixture, camera: Camera
|
|
):
|
|
"""Test select entity update (new Doorbell Message)."""
|
|
|
|
expected_length = (
|
|
len(mock_entry.api.bootstrap.nvr.doorbell_settings.all_messages) + 1
|
|
)
|
|
|
|
_, entity_id = ids_from_device_description(
|
|
Platform.SELECT, camera, CAMERA_SELECTS[2]
|
|
)
|
|
|
|
state = hass.states.get(entity_id)
|
|
assert state
|
|
assert len(state.attributes[ATTR_OPTIONS]) == expected_length
|
|
|
|
expected_length += 1
|
|
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,
|
|
DoorbellMessage(
|
|
type=DoorbellMessageType.CUSTOM_MESSAGE,
|
|
text="Test2",
|
|
),
|
|
]
|
|
|
|
mock_msg = Mock()
|
|
mock_msg.changed_data = {"doorbell_settings": {}}
|
|
mock_msg.new_obj = new_nvr
|
|
|
|
mock_entry.api.bootstrap.nvr = new_nvr
|
|
mock_entry.api.ws_subscription(mock_msg)
|
|
await hass.async_block_till_done()
|
|
|
|
new_nvr.update_all_messages.assert_called_once()
|
|
|
|
state = hass.states.get(entity_id)
|
|
assert state
|
|
assert len(state.attributes[ATTR_OPTIONS]) == expected_length
|
|
|
|
|
|
async def test_select_update_doorbell_message(
|
|
hass: HomeAssistant,
|
|
mock_entry: MockEntityFixture,
|
|
camera: Camera,
|
|
):
|
|
"""Test select entity update (change doorbell message)."""
|
|
|
|
_, entity_id = ids_from_device_description(
|
|
Platform.SELECT, camera, CAMERA_SELECTS[2]
|
|
)
|
|
|
|
state = hass.states.get(entity_id)
|
|
assert state
|
|
assert state.state == "Default Message (Welcome)"
|
|
|
|
new_bootstrap = copy(mock_entry.api.bootstrap)
|
|
new_camera = camera.copy()
|
|
new_camera.lcd_message = LCDMessage(
|
|
type=DoorbellMessageType.CUSTOM_MESSAGE, text="Test"
|
|
)
|
|
|
|
mock_msg = Mock()
|
|
mock_msg.changed_data = {}
|
|
mock_msg.new_obj = new_camera
|
|
|
|
new_bootstrap.cameras = {new_camera.id: new_camera}
|
|
mock_entry.api.bootstrap = new_bootstrap
|
|
mock_entry.api.ws_subscription(mock_msg)
|
|
await hass.async_block_till_done()
|
|
|
|
state = hass.states.get(entity_id)
|
|
assert state
|
|
assert state.state == "Test"
|
|
|
|
|
|
async def test_select_set_option_light_motion(
|
|
hass: HomeAssistant,
|
|
light: Light,
|
|
):
|
|
"""Test Light Mode select."""
|
|
_, entity_id = ids_from_device_description(Platform.SELECT, light, LIGHT_SELECTS[0])
|
|
|
|
light.__fields__["set_light_settings"] = Mock()
|
|
light.set_light_settings = AsyncMock()
|
|
|
|
await hass.services.async_call(
|
|
"select",
|
|
"select_option",
|
|
{ATTR_ENTITY_ID: entity_id, ATTR_OPTION: LIGHT_MODE_OFF},
|
|
blocking=True,
|
|
)
|
|
|
|
light.set_light_settings.assert_called_once_with(
|
|
LightModeType.MANUAL, enable_at=None
|
|
)
|
|
|
|
|
|
async def test_select_set_option_light_camera(
|
|
hass: HomeAssistant,
|
|
light: Light,
|
|
):
|
|
"""Test Paired Camera select."""
|
|
_, entity_id = ids_from_device_description(Platform.SELECT, light, LIGHT_SELECTS[1])
|
|
|
|
light.__fields__["set_paired_camera"] = Mock()
|
|
light.set_paired_camera = AsyncMock()
|
|
|
|
camera = list(light.api.bootstrap.cameras.values())[0]
|
|
|
|
await hass.services.async_call(
|
|
"select",
|
|
"select_option",
|
|
{ATTR_ENTITY_ID: entity_id, ATTR_OPTION: camera.name},
|
|
blocking=True,
|
|
)
|
|
|
|
light.set_paired_camera.assert_called_once_with(camera)
|
|
|
|
await hass.services.async_call(
|
|
"select",
|
|
"select_option",
|
|
{ATTR_ENTITY_ID: entity_id, ATTR_OPTION: "Not Paired"},
|
|
blocking=True,
|
|
)
|
|
|
|
light.set_paired_camera.assert_called_with(None)
|
|
|
|
|
|
async def test_select_set_option_camera_recording(
|
|
hass: HomeAssistant,
|
|
camera: Camera,
|
|
):
|
|
"""Test Recording Mode select."""
|
|
_, entity_id = ids_from_device_description(
|
|
Platform.SELECT, camera, CAMERA_SELECTS[0]
|
|
)
|
|
|
|
camera.__fields__["set_recording_mode"] = Mock()
|
|
camera.set_recording_mode = AsyncMock()
|
|
|
|
await hass.services.async_call(
|
|
"select",
|
|
"select_option",
|
|
{ATTR_ENTITY_ID: entity_id, ATTR_OPTION: "Never"},
|
|
blocking=True,
|
|
)
|
|
|
|
camera.set_recording_mode.assert_called_once_with(RecordingMode.NEVER)
|
|
|
|
|
|
async def test_select_set_option_camera_ir(
|
|
hass: HomeAssistant,
|
|
camera: Camera,
|
|
):
|
|
"""Test Infrared Mode select."""
|
|
_, entity_id = ids_from_device_description(
|
|
Platform.SELECT, camera, CAMERA_SELECTS[1]
|
|
)
|
|
|
|
camera.__fields__["set_ir_led_model"] = Mock()
|
|
camera.set_ir_led_model = AsyncMock()
|
|
|
|
await hass.services.async_call(
|
|
"select",
|
|
"select_option",
|
|
{ATTR_ENTITY_ID: entity_id, ATTR_OPTION: "Always Enable"},
|
|
blocking=True,
|
|
)
|
|
|
|
camera.set_ir_led_model.assert_called_once_with(IRLEDMode.ON)
|
|
|
|
|
|
async def test_select_set_option_camera_doorbell_custom(
|
|
hass: HomeAssistant,
|
|
camera: Camera,
|
|
):
|
|
"""Test Doorbell Text select (user defined message)."""
|
|
_, entity_id = ids_from_device_description(
|
|
Platform.SELECT, camera, CAMERA_SELECTS[2]
|
|
)
|
|
|
|
camera.__fields__["set_lcd_text"] = Mock()
|
|
camera.set_lcd_text = AsyncMock()
|
|
|
|
await hass.services.async_call(
|
|
"select",
|
|
"select_option",
|
|
{ATTR_ENTITY_ID: entity_id, ATTR_OPTION: "Test"},
|
|
blocking=True,
|
|
)
|
|
|
|
camera.set_lcd_text.assert_called_once_with(
|
|
DoorbellMessageType.CUSTOM_MESSAGE, text="Test"
|
|
)
|
|
|
|
|
|
async def test_select_set_option_camera_doorbell_unifi(
|
|
hass: HomeAssistant,
|
|
camera: Camera,
|
|
):
|
|
"""Test Doorbell Text select (unifi message)."""
|
|
_, entity_id = ids_from_device_description(
|
|
Platform.SELECT, camera, CAMERA_SELECTS[2]
|
|
)
|
|
|
|
camera.__fields__["set_lcd_text"] = Mock()
|
|
camera.set_lcd_text = AsyncMock()
|
|
|
|
await hass.services.async_call(
|
|
"select",
|
|
"select_option",
|
|
{
|
|
ATTR_ENTITY_ID: entity_id,
|
|
ATTR_OPTION: "LEAVE PACKAGE AT DOOR",
|
|
},
|
|
blocking=True,
|
|
)
|
|
|
|
camera.set_lcd_text.assert_called_once_with(
|
|
DoorbellMessageType.LEAVE_PACKAGE_AT_DOOR
|
|
)
|
|
|
|
await hass.services.async_call(
|
|
"select",
|
|
"select_option",
|
|
{
|
|
ATTR_ENTITY_ID: entity_id,
|
|
ATTR_OPTION: "Default Message (Welcome)",
|
|
},
|
|
blocking=True,
|
|
)
|
|
|
|
camera.set_lcd_text.assert_called_with(None)
|
|
|
|
|
|
async def test_select_set_option_camera_doorbell_default(
|
|
hass: HomeAssistant,
|
|
camera: Camera,
|
|
):
|
|
"""Test Doorbell Text select (default message)."""
|
|
_, entity_id = ids_from_device_description(
|
|
Platform.SELECT, camera, CAMERA_SELECTS[2]
|
|
)
|
|
|
|
camera.__fields__["set_lcd_text"] = Mock()
|
|
camera.set_lcd_text = AsyncMock()
|
|
|
|
await hass.services.async_call(
|
|
"select",
|
|
"select_option",
|
|
{
|
|
ATTR_ENTITY_ID: entity_id,
|
|
ATTR_OPTION: "Default Message (Welcome)",
|
|
},
|
|
blocking=True,
|
|
)
|
|
|
|
camera.set_lcd_text.assert_called_once_with(None)
|
|
|
|
|
|
async def test_select_set_option_viewer(
|
|
hass: HomeAssistant,
|
|
viewer: Viewer,
|
|
):
|
|
"""Test Liveview select."""
|
|
_, entity_id = ids_from_device_description(
|
|
Platform.SELECT, viewer, VIEWER_SELECTS[0]
|
|
)
|
|
|
|
viewer.__fields__["set_liveview"] = Mock()
|
|
viewer.set_liveview = AsyncMock()
|
|
|
|
liveview = list(viewer.api.bootstrap.liveviews.values())[0]
|
|
|
|
await hass.services.async_call(
|
|
"select",
|
|
"select_option",
|
|
{ATTR_ENTITY_ID: entity_id, ATTR_OPTION: liveview.name},
|
|
blocking=True,
|
|
)
|
|
|
|
viewer.set_liveview.assert_called_once_with(liveview)
|
|
|
|
|
|
async def test_select_service_doorbell_invalid(
|
|
hass: HomeAssistant,
|
|
camera: Camera,
|
|
):
|
|
"""Test Doorbell Text service (invalid)."""
|
|
_, entity_id = ids_from_device_description(
|
|
Platform.SELECT, camera, CAMERA_SELECTS[1]
|
|
)
|
|
|
|
camera.__fields__["set_lcd_text"] = Mock()
|
|
camera.set_lcd_text = AsyncMock()
|
|
|
|
with pytest.raises(HomeAssistantError):
|
|
await hass.services.async_call(
|
|
"unifiprotect",
|
|
SERVICE_SET_DOORBELL_MESSAGE,
|
|
{ATTR_ENTITY_ID: entity_id, ATTR_MESSAGE: "Test"},
|
|
blocking=True,
|
|
)
|
|
|
|
assert not camera.set_lcd_text.called
|
|
|
|
|
|
async def test_select_service_doorbell_success(
|
|
hass: HomeAssistant,
|
|
camera: Camera,
|
|
):
|
|
"""Test Doorbell Text service (success)."""
|
|
_, entity_id = ids_from_device_description(
|
|
Platform.SELECT, camera, CAMERA_SELECTS[2]
|
|
)
|
|
|
|
camera.__fields__["set_lcd_text"] = Mock()
|
|
camera.set_lcd_text = AsyncMock()
|
|
|
|
await hass.services.async_call(
|
|
"unifiprotect",
|
|
SERVICE_SET_DOORBELL_MESSAGE,
|
|
{
|
|
ATTR_ENTITY_ID: entity_id,
|
|
ATTR_MESSAGE: "Test",
|
|
},
|
|
blocking=True,
|
|
)
|
|
|
|
camera.set_lcd_text.assert_called_once_with(
|
|
DoorbellMessageType.CUSTOM_MESSAGE, "Test", reset_at=None
|
|
)
|
|
|
|
|
|
@patch("homeassistant.components.unifiprotect.select.utcnow")
|
|
async def test_select_service_doorbell_with_reset(
|
|
mock_now,
|
|
hass: HomeAssistant,
|
|
camera: Camera,
|
|
):
|
|
"""Test Doorbell Text service (success with reset time)."""
|
|
now = utcnow()
|
|
mock_now.return_value = now
|
|
|
|
_, entity_id = ids_from_device_description(
|
|
Platform.SELECT, camera, CAMERA_SELECTS[2]
|
|
)
|
|
|
|
camera.__fields__["set_lcd_text"] = Mock()
|
|
camera.set_lcd_text = AsyncMock()
|
|
|
|
await hass.services.async_call(
|
|
"unifiprotect",
|
|
SERVICE_SET_DOORBELL_MESSAGE,
|
|
{
|
|
ATTR_ENTITY_ID: entity_id,
|
|
ATTR_MESSAGE: "Test",
|
|
ATTR_DURATION: 60,
|
|
},
|
|
blocking=True,
|
|
)
|
|
|
|
camera.set_lcd_text.assert_called_once_with(
|
|
DoorbellMessageType.CUSTOM_MESSAGE,
|
|
"Test",
|
|
reset_at=now + timedelta(minutes=60),
|
|
)
|