diff --git a/homeassistant/components/doorbird/device.py b/homeassistant/components/doorbird/device.py index 9bb3397d0ff..866251f3d28 100644 --- a/homeassistant/components/doorbird/device.py +++ b/homeassistant/components/doorbird/device.py @@ -103,9 +103,8 @@ class ConfiguredDoorBird: async def async_register_events(self) -> None: """Register events on device.""" if not self.door_station_events: - # User may not have permission to get the favorites + # The config entry might not have any events configured yet return - http_fav = await self._async_register_events() event_config = await self._async_get_event_config(http_fav) _LOGGER.debug("%s: Event config: %s", self.name, event_config) diff --git a/tests/components/doorbird/__init__.py b/tests/components/doorbird/__init__.py index 59ce6ecd958..41def92f121 100644 --- a/tests/components/doorbird/__init__.py +++ b/tests/components/doorbird/__init__.py @@ -49,6 +49,7 @@ def get_mock_doorbird_api( schedule: list[DoorBirdScheduleEntry] | 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) @@ -60,7 +61,9 @@ def get_mock_doorbird_api( return_value=favorites, ) type(doorbirdapi_mock).change_favorite = AsyncMock(return_value=True) - type(doorbirdapi_mock).change_schedule = AsyncMock(return_value=(True, 200)) + type(doorbirdapi_mock).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) diff --git a/tests/components/doorbird/conftest.py b/tests/components/doorbird/conftest.py index cd3e410624d..59ead250293 100644 --- a/tests/components/doorbird/conftest.py +++ b/tests/components/doorbird/conftest.py @@ -46,6 +46,14 @@ def doorbird_schedule() -> list[DoorBirdScheduleEntry]: ) +@pytest.fixture(scope="session") +def doorbird_schedule_wrong_param() -> list[DoorBirdScheduleEntry]: + """Return a loaded DoorBird schedule fixture with an incorrect param.""" + return DoorBirdScheduleEntry.parse_all( + load_json_value_fixture("schedule_wrong_param.json", "doorbird") + ) + + @pytest.fixture(scope="session") def doorbird_favorites() -> dict[str, dict[str, Any]]: """Return a loaded DoorBird favorites fixture.""" @@ -90,18 +98,21 @@ async def doorbird_mocker( async def _async_mock( entry: MockConfigEntry | None = None, api: DoorBird | None = None, + change_schedule: tuple[bool, int] | None = None, info: dict[str, Any] | None = None, info_side_effect: Exception | None = None, schedule: list[DoorBirdScheduleEntry] | None = None, favorites: dict[str, dict[str, Any]] | None = None, favorites_side_effect: Exception | None = None, + options: dict[str, Any] | None = None, ) -> MockDoorbirdEntry: """Create a MockDoorbirdEntry from defaults or specific values.""" entry = entry or MockConfigEntry( domain=DOMAIN, unique_id="1CCAE3AAAAAA", data=VALID_CONFIG, - options={CONF_EVENTS: [DEFAULT_DOORBELL_EVENT, DEFAULT_MOTION_EVENT]}, + options=options + or {CONF_EVENTS: [DEFAULT_DOORBELL_EVENT, DEFAULT_MOTION_EVENT]}, ) api = api or get_mock_doorbird_api( info=info or doorbird_info, @@ -109,6 +120,7 @@ async def doorbird_mocker( schedule=schedule or doorbird_schedule, favorites=favorites or doorbird_favorites, favorites_side_effect=favorites_side_effect, + change_schedule=change_schedule, ) entry.add_to_hass(hass) with patch_doorbird_api_entry_points(api): diff --git a/tests/components/doorbird/fixtures/schedule_wrong_param.json b/tests/components/doorbird/fixtures/schedule_wrong_param.json new file mode 100644 index 00000000000..724f19b1774 --- /dev/null +++ b/tests/components/doorbird/fixtures/schedule_wrong_param.json @@ -0,0 +1,67 @@ +[ + { + "input": "doorbell", + "param": "99", + "output": [ + { + "event": "notify", + "param": "", + "schedule": { + "weekdays": [ + { + "to": "107999", + "from": "108000" + } + ] + } + }, + { + "event": "http", + "param": "0", + "schedule": { + "weekdays": [ + { + "to": "107999", + "from": "108000" + } + ] + } + } + ] + }, + { + "input": "motion", + "param": "", + "output": [ + { + "event": "notify", + "param": "", + "schedule": { + "weekdays": [ + { + "to": "107999", + "from": "108000" + } + ] + } + }, + { + "event": "http", + "param": "5", + "schedule": { + "weekdays": [ + { + "to": "107999", + "from": "108000" + } + ] + } + } + ] + }, + { + "input": "relay", + "param": "1", + "output": [] + } +] diff --git a/tests/components/doorbird/test_device.py b/tests/components/doorbird/test_device.py new file mode 100644 index 00000000000..cf3beae5e68 --- /dev/null +++ b/tests/components/doorbird/test_device.py @@ -0,0 +1,59 @@ +"""Test DoorBird device.""" + +from copy import deepcopy +from http import HTTPStatus + +from doorbirdpy import DoorBirdScheduleEntry +import pytest + +from homeassistant.components.doorbird.const import CONF_EVENTS +from homeassistant.core import HomeAssistant + +from .conftest import DoorbirdMockerType + + +async def test_no_configured_events( + hass: HomeAssistant, + doorbird_mocker: DoorbirdMockerType, +) -> None: + """Test a doorbird with no events configured.""" + await doorbird_mocker(options={CONF_EVENTS: []}) + assert not hass.states.async_all("event") + + +async def test_change_schedule_success( + doorbird_mocker: DoorbirdMockerType, + doorbird_schedule_wrong_param: list[DoorBirdScheduleEntry], + caplog: pytest.LogCaptureFixture, +) -> None: + """Test a doorbird when change_schedule fails.""" + schedule_copy = deepcopy(doorbird_schedule_wrong_param) + mock_doorbird = await doorbird_mocker(schedule=schedule_copy) + assert "Unable to update schedule entry mydoorbird" not in caplog.text + assert mock_doorbird.api.change_schedule.call_count == 1 + new_schedule: list[DoorBirdScheduleEntry] = ( + mock_doorbird.api.change_schedule.call_args[0] + ) + # Ensure the attempt to update the schedule to fix the incorrect + # param is made + assert new_schedule[-1].output[-1].param == "1" + + +async def test_change_schedule_fails( + doorbird_mocker: DoorbirdMockerType, + doorbird_schedule_wrong_param: list[DoorBirdScheduleEntry], + caplog: pytest.LogCaptureFixture, +) -> None: + """Test a doorbird when change_schedule fails.""" + schedule_copy = deepcopy(doorbird_schedule_wrong_param) + mock_doorbird = await doorbird_mocker( + schedule=schedule_copy, change_schedule=(False, HTTPStatus.UNAUTHORIZED) + ) + assert "Unable to update schedule entry mydoorbird" in caplog.text + assert mock_doorbird.api.change_schedule.call_count == 1 + new_schedule: list[DoorBirdScheduleEntry] = ( + mock_doorbird.api.change_schedule.call_args[0] + ) + # Ensure the attempt to update the schedule to fix the incorrect + # param is made + assert new_schedule[-1].output[-1].param == "1"