Fix doorbird models are missing the schedule API (#123033)
* Fix doorbird models are missing the schedule API fixes #122997 * cover
This commit is contained in:
parent
d87366b1e7
commit
a624ada8d6
4 changed files with 37 additions and 18 deletions
|
@ -5,9 +5,11 @@ from __future__ import annotations
|
|||
from collections import defaultdict
|
||||
from dataclasses import dataclass
|
||||
from functools import cached_property
|
||||
from http import HTTPStatus
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
from aiohttp import ClientResponseError
|
||||
from doorbirdpy import (
|
||||
DoorBird,
|
||||
DoorBirdScheduleEntry,
|
||||
|
@ -170,15 +172,21 @@ class ConfiguredDoorBird:
|
|||
) -> DoorbirdEventConfig:
|
||||
"""Get events and unconfigured favorites from http favorites."""
|
||||
device = self.device
|
||||
schedule = await device.schedule()
|
||||
events: list[DoorbirdEvent] = []
|
||||
unconfigured_favorites: defaultdict[str, list[str]] = defaultdict(list)
|
||||
try:
|
||||
schedule = await device.schedule()
|
||||
except ClientResponseError as ex:
|
||||
if ex.status == HTTPStatus.NOT_FOUND:
|
||||
# D301 models do not support schedules
|
||||
return DoorbirdEventConfig(events, [], unconfigured_favorites)
|
||||
raise
|
||||
favorite_input_type = {
|
||||
output.param: entry.input
|
||||
for entry in schedule
|
||||
for output in entry.output
|
||||
if output.event == HTTP_EVENT_TYPE
|
||||
}
|
||||
events: list[DoorbirdEvent] = []
|
||||
unconfigured_favorites: defaultdict[str, list[str]] = defaultdict(list)
|
||||
default_event_types = {
|
||||
self._get_event_name(event): event_type
|
||||
for event, event_type in DEFAULT_EVENT_TYPES
|
||||
|
|
|
@ -47,31 +47,30 @@ def get_mock_doorbird_api(
|
|||
info: dict[str, Any] | None = None,
|
||||
info_side_effect: Exception | None = None,
|
||||
schedule: list[DoorBirdScheduleEntry] | None = None,
|
||||
schedule_side_effect: Exception | None = None,
|
||||
favorites: dict[str, dict[str, Any]] | None = None,
|
||||
favorites_side_effect: Exception | None = None,
|
||||
change_schedule: tuple[bool, int] | None = None,
|
||||
) -> DoorBird:
|
||||
"""Return a mock DoorBirdAPI object with return values."""
|
||||
doorbirdapi_mock = MagicMock(spec_set=DoorBird)
|
||||
type(doorbirdapi_mock).info = AsyncMock(
|
||||
side_effect=info_side_effect, return_value=info
|
||||
api_mock_type = type(doorbirdapi_mock)
|
||||
api_mock_type.info = AsyncMock(side_effect=info_side_effect, return_value=info)
|
||||
api_mock_type.favorites = AsyncMock(
|
||||
side_effect=favorites_side_effect, return_value=favorites
|
||||
)
|
||||
type(doorbirdapi_mock).favorites = AsyncMock(
|
||||
side_effect=favorites_side_effect,
|
||||
return_value=favorites,
|
||||
)
|
||||
type(doorbirdapi_mock).change_favorite = AsyncMock(return_value=True)
|
||||
type(doorbirdapi_mock).change_schedule = AsyncMock(
|
||||
api_mock_type.change_favorite = AsyncMock(return_value=True)
|
||||
api_mock_type.change_schedule = AsyncMock(
|
||||
return_value=change_schedule or (True, 200)
|
||||
)
|
||||
type(doorbirdapi_mock).schedule = AsyncMock(return_value=schedule)
|
||||
type(doorbirdapi_mock).energize_relay = AsyncMock(return_value=True)
|
||||
type(doorbirdapi_mock).turn_light_on = AsyncMock(return_value=True)
|
||||
type(doorbirdapi_mock).delete_favorite = AsyncMock(return_value=True)
|
||||
type(doorbirdapi_mock).get_image = AsyncMock(return_value=b"image")
|
||||
type(doorbirdapi_mock).doorbell_state = AsyncMock(
|
||||
side_effect=mock_unauthorized_exception()
|
||||
api_mock_type.schedule = AsyncMock(
|
||||
return_value=schedule, side_effect=schedule_side_effect
|
||||
)
|
||||
api_mock_type.energize_relay = AsyncMock(return_value=True)
|
||||
api_mock_type.turn_light_on = AsyncMock(return_value=True)
|
||||
api_mock_type.delete_favorite = AsyncMock(return_value=True)
|
||||
api_mock_type.get_image = AsyncMock(return_value=b"image")
|
||||
api_mock_type.doorbell_state = AsyncMock(side_effect=mock_unauthorized_exception())
|
||||
return doorbirdapi_mock
|
||||
|
||||
|
||||
|
|
|
@ -102,6 +102,7 @@ async def doorbird_mocker(
|
|||
info: dict[str, Any] | None = None,
|
||||
info_side_effect: Exception | None = None,
|
||||
schedule: list[DoorBirdScheduleEntry] | None = None,
|
||||
schedule_side_effect: Exception | None = None,
|
||||
favorites: dict[str, dict[str, Any]] | None = None,
|
||||
favorites_side_effect: Exception | None = None,
|
||||
options: dict[str, Any] | None = None,
|
||||
|
@ -118,6 +119,7 @@ async def doorbird_mocker(
|
|||
info=info or doorbird_info,
|
||||
info_side_effect=info_side_effect,
|
||||
schedule=schedule or doorbird_schedule,
|
||||
schedule_side_effect=schedule_side_effect,
|
||||
favorites=favorites or doorbird_favorites,
|
||||
favorites_side_effect=favorites_side_effect,
|
||||
change_schedule=change_schedule,
|
||||
|
|
|
@ -56,6 +56,16 @@ async def test_http_favorites_request_fails(
|
|||
assert doorbird_entry.entry.state is ConfigEntryState.SETUP_RETRY
|
||||
|
||||
|
||||
async def test_http_schedule_api_missing(
|
||||
doorbird_mocker: DoorbirdMockerType,
|
||||
) -> None:
|
||||
"""Test missing the schedule API is non-fatal as not all models support it."""
|
||||
doorbird_entry = await doorbird_mocker(
|
||||
schedule_side_effect=mock_not_found_exception()
|
||||
)
|
||||
assert doorbird_entry.entry.state is ConfigEntryState.LOADED
|
||||
|
||||
|
||||
async def test_events_changed(
|
||||
hass: HomeAssistant,
|
||||
doorbird_mocker: DoorbirdMockerType,
|
||||
|
|
Loading…
Add table
Reference in a new issue