core/tests/components/ring/test_sensor.py

231 lines
7.3 KiB
Python
Raw Normal View History

"""The tests for the Ring sensor platform."""
import logging
from unittest.mock import Mock, patch
from freezegun.api import FrozenDateTimeFactory
import pytest
from ring_doorbell import Ring
from syrupy.assertion import SnapshotAssertion
from homeassistant.components.ring.const import DOMAIN, SCAN_INTERVAL
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from homeassistant.setup import async_setup_component
from .common import MockConfigEntry, setup_platform
from .device_mocks import (
DOWNSTAIRS_DEVICE_ID,
FRONT_DEVICE_ID,
FRONT_DOOR_DEVICE_ID,
INGRESS_DEVICE_ID,
INTERNAL_DEVICE_ID,
)
from tests.common import async_fire_time_changed, snapshot_platform
@pytest.fixture
def create_deprecated_and_disabled_sensor_entities(
hass: HomeAssistant,
mock_config_entry: ConfigEntry,
entity_registry: er.EntityRegistry,
):
"""Create the entity so it is not ignored by the deprecation check."""
mock_config_entry.add_to_hass(hass)
def create_entry(
device_name,
description,
device_id,
):
unique_id = f"{device_id}-{description}"
entity_registry.async_get_or_create(
domain=SENSOR_DOMAIN,
platform=DOMAIN,
unique_id=unique_id,
suggested_object_id=f"{device_name}_{description}",
config_entry=mock_config_entry,
)
# Deprecated
create_entry("downstairs", "volume", DOWNSTAIRS_DEVICE_ID)
create_entry("front_door", "volume", FRONT_DEVICE_ID)
create_entry("ingress", "doorbell_volume", INGRESS_DEVICE_ID)
create_entry("ingress", "mic_volume", INGRESS_DEVICE_ID)
create_entry("ingress", "voice_volume", INGRESS_DEVICE_ID)
# Disabled
for desc in ("wifi_signal_category", "wifi_signal_strength"):
create_entry("downstairs", desc, DOWNSTAIRS_DEVICE_ID)
create_entry("front", desc, FRONT_DEVICE_ID)
create_entry("ingress", desc, INGRESS_DEVICE_ID)
create_entry("front_door", desc, FRONT_DOOR_DEVICE_ID)
create_entry("internal", desc, INTERNAL_DEVICE_ID)
async def test_states(
hass: HomeAssistant,
mock_ring_client: Mock,
mock_config_entry: MockConfigEntry,
entity_registry: er.EntityRegistry,
snapshot: SnapshotAssertion,
create_deprecated_and_disabled_sensor_entities,
) -> None:
"""Test states."""
mock_config_entry.add_to_hass(hass)
await setup_platform(hass, Platform.SENSOR)
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
@pytest.mark.parametrize(
("device_id", "device_name", "sensor_name", "expected_value"),
[
(987654, "front_door", "wifi_signal_category", "good"),
(987654, "front_door", "wifi_signal_strength", "-58"),
(123456, "downstairs", "wifi_signal_category", "good"),
(123456, "downstairs", "wifi_signal_strength", "-39"),
(765432, "front", "wifi_signal_category", "good"),
(765432, "front", "wifi_signal_strength", "-58"),
],
ids=[
"doorbell-category",
"doorbell-strength",
"chime-category",
"chime-strength",
"stickup_cam-category",
"stickup_cam-strength",
],
)
async def test_health_sensor(
hass: HomeAssistant,
mock_ring_client,
freezer: FrozenDateTimeFactory,
entity_registry: er.EntityRegistry,
device_id,
device_name,
sensor_name,
expected_value,
) -> None:
"""Test the Ring health sensors."""
entity_id = f"sensor.{device_name}_{sensor_name}"
# Enable the sensor as the health sensors are disabled by default
entity_entry = entity_registry.async_get_or_create(
"sensor",
"ring",
f"{device_id}-{sensor_name}",
suggested_object_id=f"{device_name}_{sensor_name}",
disabled_by=None,
)
assert entity_entry.disabled is False
assert entity_entry.entity_id == entity_id
await setup_platform(hass, "sensor")
await hass.async_block_till_done()
sensor_state = hass.states.get(entity_id)
assert sensor_state is not None
assert sensor_state.state == "unknown"
freezer.tick(SCAN_INTERVAL)
async_fire_time_changed(hass)
await hass.async_block_till_done(wait_background_tasks=True)
sensor_state = hass.states.get(entity_id)
assert sensor_state is not None
assert sensor_state.state == expected_value
@pytest.mark.parametrize(
("device_id", "device_name", "sensor_name", "expected_value"),
[
(
FRONT_DOOR_DEVICE_ID,
"front_door",
"last_motion",
"2017-03-05T15:03:40+00:00",
),
(FRONT_DOOR_DEVICE_ID, "front_door", "last_ding", "2018-03-05T15:03:40+00:00"),
(
FRONT_DOOR_DEVICE_ID,
"front_door",
"last_activity",
"2018-03-05T15:03:40+00:00",
),
(FRONT_DEVICE_ID, "front", "last_motion", "2017-03-05T15:03:40+00:00"),
(INGRESS_DEVICE_ID, "ingress", "last_activity", "2024-02-02T11:21:24+00:00"),
],
ids=[
"doorbell-motion",
"doorbell-ding",
"doorbell-activity",
"stickup_cam-motion",
"other-activity",
],
)
async def test_history_sensor(
hass: HomeAssistant,
mock_ring_client: Ring,
mock_config_entry: ConfigEntry,
entity_registry: er.EntityRegistry,
freezer: FrozenDateTimeFactory,
device_id: int,
device_name: str,
sensor_name: str,
expected_value: str,
) -> None:
"""Test the Ring sensors."""
# Create the entity so it is not ignored by the deprecation check
mock_config_entry.add_to_hass(hass)
entity_id = f"sensor.{device_name}_{sensor_name}"
unique_id = f"{device_id}-{sensor_name}"
entity_registry.async_get_or_create(
domain=SENSOR_DOMAIN,
platform=DOMAIN,
unique_id=unique_id,
suggested_object_id=f"{device_name}_{sensor_name}",
config_entry=mock_config_entry,
)
with patch("homeassistant.components.ring.PLATFORMS", [Platform.SENSOR]):
assert await async_setup_component(hass, DOMAIN, {})
entity_id = f"sensor.{device_name}_{sensor_name}"
sensor_state = hass.states.get(entity_id)
assert sensor_state is not None
assert sensor_state.state == "unknown"
freezer.tick(SCAN_INTERVAL)
async_fire_time_changed(hass)
await hass.async_block_till_done(wait_background_tasks=True)
sensor_state = hass.states.get(entity_id)
assert sensor_state is not None
assert sensor_state.state == expected_value
async def test_only_chime_devices(
hass: HomeAssistant,
mock_ring_client,
mock_ring_devices,
freezer: FrozenDateTimeFactory,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Tests the update service works correctly if only chimes are returned."""
await hass.config.async_set_time_zone("UTC")
freezer.move_to("2021-01-09 12:00:00+00:00")
mock_ring_devices.all_devices = mock_ring_devices.chimes
await setup_platform(hass, Platform.SENSOR)
await hass.async_block_till_done()
caplog.set_level(logging.DEBUG)
caplog.clear()
freezer.tick(SCAN_INTERVAL)
async_fire_time_changed(hass)
await hass.async_block_till_done()
assert "UnboundLocalError" not in caplog.text # For issue #109210