mirror of https://github.com/home-assistant/core
209 lines
7.0 KiB
Python
209 lines
7.0 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 functools import partial
|
|
from unittest.mock import AsyncMock, MagicMock
|
|
|
|
from ring_doorbell import (
|
|
RingCapability,
|
|
RingChime,
|
|
RingDoorBell,
|
|
RingOther,
|
|
RingStickUpCam,
|
|
)
|
|
from ring_doorbell.const import DOORBELL_EXISTING_TYPE
|
|
|
|
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
|
|
INTERNAL_DEVICE_ID = 345678
|
|
DOWNSTAIRS_DEVICE_ID = 123456
|
|
|
|
|
|
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"),
|
|
)
|
|
mock_device.async_set_motion_detection.side_effect = (
|
|
lambda i: mock_device.configure_mock(motion_detection=i)
|
|
)
|
|
|
|
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")
|
|
)
|
|
)
|
|
mock_device.async_set_volume.side_effect = lambda i: mock_device.configure_mock(
|
|
volume=i
|
|
)
|
|
|
|
if has_capability(RingCapability.SIREN):
|
|
mock_device.configure_mock(
|
|
siren=device_dict["siren_status"].get("seconds_remaining")
|
|
)
|
|
mock_device.async_set_siren.side_effect = lambda i: mock_device.configure_mock(
|
|
siren=i
|
|
)
|
|
|
|
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 == "doorbots":
|
|
mock_device.configure_mock(
|
|
existing_doorbell_type=DOORBELL_EXISTING_TYPE[
|
|
device_dict["settings"]["chime_settings"].get("type", 2)
|
|
]
|
|
)
|
|
mock_device.configure_mock(
|
|
existing_doorbell_type_enabled=device_dict["settings"][
|
|
"chime_settings"
|
|
].get("enable", False)
|
|
)
|
|
mock_device.async_set_existing_doorbell_type_enabled.side_effect = (
|
|
lambda i: mock_device.configure_mock(existing_doorbell_type_enabled=i)
|
|
)
|
|
|
|
if device_family == "other":
|
|
for prop in ("doorbell_volume", "mic_volume", "voice_volume"):
|
|
mock_device.configure_mock(
|
|
**{
|
|
prop: device_dict["settings"].get(prop),
|
|
f"async_set_{prop}.side_effect": partial(
|
|
setattr, mock_device, prop
|
|
),
|
|
}
|
|
)
|
|
|
|
return mock_device
|