core/tests/components/ring/device_mocks.py

177 lines
5.8 KiB
Python

"""Module for ring device mocks.
Creates a MagicMock for all device families, i.e. chimes, doorbells, stickup_cams and other.
Each device entry in the devices.json will have a MagicMock instead of the RingObject.
Mocks the api calls on the devices such as history() and health().
"""
from datetime import datetime
from unittest.mock import AsyncMock, MagicMock
from ring_doorbell import (
RingCapability,
RingChime,
RingDoorBell,
RingOther,
RingStickUpCam,
)
from homeassistant.components.ring.const import DOMAIN
from homeassistant.util import dt as dt_util
from tests.common import load_json_value_fixture
DEVICES_FIXTURE = load_json_value_fixture("devices.json", DOMAIN)
DOORBOT_HISTORY = load_json_value_fixture("doorbot_history.json", DOMAIN)
INTERCOM_HISTORY = load_json_value_fixture("intercom_history.json", DOMAIN)
DOORBOT_HEALTH = load_json_value_fixture("doorbot_health_attrs.json", DOMAIN)
CHIME_HEALTH = load_json_value_fixture("chime_health_attrs.json", DOMAIN)
FRONT_DOOR_DEVICE_ID = 987654
INGRESS_DEVICE_ID = 185036587
FRONT_DEVICE_ID = 765432
def get_mock_devices():
"""Return list of mock devices keyed by device_type."""
devices = {}
for device_family, device_class in DEVICE_TYPES.items():
devices[device_family] = [
_mocked_ring_device(
device, device_family, device_class, DEVICE_CAPABILITIES[device_class]
)
for device in DEVICES_FIXTURE[device_family]
]
return devices
def get_devices_data():
"""Return devices raw json used by the diagnostics module."""
return {
device_type: {obj["id"]: obj for obj in devices}
for device_type, devices in DEVICES_FIXTURE.items()
}
DEVICE_TYPES = {
"doorbots": RingDoorBell,
"authorized_doorbots": RingDoorBell,
"stickup_cams": RingStickUpCam,
"chimes": RingChime,
"other": RingOther,
}
DEVICE_CAPABILITIES = {
RingDoorBell: [
RingCapability.BATTERY,
RingCapability.VOLUME,
RingCapability.MOTION_DETECTION,
RingCapability.VIDEO,
RingCapability.DING,
RingCapability.HISTORY,
],
RingStickUpCam: [
RingCapability.BATTERY,
RingCapability.VOLUME,
RingCapability.MOTION_DETECTION,
RingCapability.VIDEO,
RingCapability.HISTORY,
RingCapability.SIREN,
RingCapability.LIGHT,
],
RingChime: [RingCapability.VOLUME],
RingOther: [RingCapability.OPEN, RingCapability.HISTORY, RingCapability.DING],
}
def _mocked_ring_device(device_dict, device_family, device_class, capabilities):
"""Return a mocked device."""
mock_device = MagicMock(spec=device_class, name=f"Mocked {device_family!s}")
def has_capability(capability):
return (
capability in capabilities
if isinstance(capability, RingCapability)
else RingCapability.from_name(capability) in capabilities
)
def update_health_data(fixture):
mock_device.configure_mock(
wifi_signal_category=fixture["device_health"].get("latest_signal_category"),
wifi_signal_strength=fixture["device_health"].get("latest_signal_strength"),
)
def update_history_data(fixture):
for entry in fixture: # Mimic the api date parsing
if isinstance(entry["created_at"], str):
dt_at = datetime.strptime(entry["created_at"], "%Y-%m-%dT%H:%M:%S.%f%z")
entry["created_at"] = dt_util.as_utc(dt_at)
mock_device.configure_mock(last_history=fixture) # Set last_history
return fixture
# Configure the device attributes
mock_device.configure_mock(**device_dict)
# Configure the Properties on the device
mock_device.configure_mock(
model=device_family,
device_api_id=device_dict["id"],
name=device_dict["description"],
wifi_signal_category=None,
wifi_signal_strength=None,
family=device_family,
)
# Configure common methods
mock_device.has_capability.side_effect = has_capability
mock_device.async_update_health_data.side_effect = lambda: update_health_data(
DOORBOT_HEALTH if device_family != "chimes" else CHIME_HEALTH
)
# Configure methods based on capability
if has_capability(RingCapability.HISTORY):
mock_device.configure_mock(last_history=[])
mock_device.async_history.side_effect = lambda *_, **__: update_history_data(
DOORBOT_HISTORY if device_family != "other" else INTERCOM_HISTORY
)
if has_capability(RingCapability.VIDEO):
mock_device.async_recording_url = AsyncMock(return_value="http://dummy.url")
if has_capability(RingCapability.MOTION_DETECTION):
mock_device.configure_mock(
motion_detection=device_dict["settings"].get("motion_detection_enabled"),
)
if has_capability(RingCapability.LIGHT):
mock_device.configure_mock(lights=device_dict.get("led_status"))
if has_capability(RingCapability.VOLUME):
mock_device.configure_mock(
volume=device_dict["settings"].get(
"doorbell_volume", device_dict["settings"].get("volume")
)
)
if has_capability(RingCapability.SIREN):
mock_device.configure_mock(
siren=device_dict["siren_status"].get("seconds_remaining")
)
if has_capability(RingCapability.BATTERY):
mock_device.configure_mock(
battery_life=min(
100, device_dict.get("battery_life", device_dict.get("battery_life2"))
)
)
if device_family == "other":
mock_device.configure_mock(
doorbell_volume=device_dict["settings"].get("doorbell_volume"),
mic_volume=device_dict["settings"].get("mic_volume"),
voice_volume=device_dict["settings"].get("voice_volume"),
)
return mock_device