From 5bb6272dfa98c118465a0ea6aa02992d4e8f67ca Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 26 Jul 2024 09:55:14 -0500 Subject: [PATCH] Add test coverage for doorbird events (#122617) --- homeassistant/components/doorbird/view.py | 11 +----- tests/components/doorbird/__init__.py | 25 ++++++++++++- tests/components/doorbird/conftest.py | 18 ++++++++- .../doorbird/fixtures/favorites.json | 12 ++++++ tests/components/doorbird/test_button.py | 2 +- tests/components/doorbird/test_event.py | 37 +++++++++++++++++++ 6 files changed, 91 insertions(+), 14 deletions(-) create mode 100644 tests/components/doorbird/fixtures/favorites.json create mode 100644 tests/components/doorbird/test_event.py diff --git a/homeassistant/components/doorbird/view.py b/homeassistant/components/doorbird/view.py index 77b84bf4f3b..71e9d33b681 100644 --- a/homeassistant/components/doorbird/view.py +++ b/homeassistant/components/doorbird/view.py @@ -25,19 +25,12 @@ class DoorBirdRequestView(HomeAssistantView): """Respond to requests from the device.""" hass = request.app[KEY_HASS] token: str | None = request.query.get("token") - if ( - token is None - or (door_station := get_door_station_by_token(hass, token)) is None - ): + if not token or not (door_station := get_door_station_by_token(hass, token)): return web.Response( status=HTTPStatus.UNAUTHORIZED, text="Invalid token provided." ) - if door_station: - event_data = door_station.get_event_data(event) - else: - event_data = {} - + event_data = door_station.get_event_data(event) # # This integration uses a multiple different events. # It would be a major breaking change to change this to diff --git a/tests/components/doorbird/__init__.py b/tests/components/doorbird/__init__.py index c342fac20e9..515b9441c1d 100644 --- a/tests/components/doorbird/__init__.py +++ b/tests/components/doorbird/__init__.py @@ -6,7 +6,15 @@ from unittest.mock import AsyncMock, MagicMock, Mock import aiohttp from doorbirdpy import DoorBird, DoorBirdScheduleEntry -from homeassistant.const import CONF_HOST, CONF_NAME, CONF_PASSWORD, CONF_USERNAME +from homeassistant import config_entries +from homeassistant.components.doorbird.const import API_URL +from homeassistant.const import ( + CONF_HOST, + CONF_NAME, + CONF_PASSWORD, + CONF_TOKEN, + CONF_USERNAME, +) VALID_CONFIG = { CONF_HOST: "1.2.3.4", @@ -39,6 +47,7 @@ def get_mock_doorbird_api( 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, ) -> DoorBird: """Return a mock DoorBirdAPI object with return values.""" @@ -48,9 +57,10 @@ def get_mock_doorbird_api( ) type(doorbirdapi_mock).favorites = AsyncMock( side_effect=favorites_side_effect, - return_value={"http": {"x": {"value": "http://webhook"}}}, + 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).schedule = AsyncMock(return_value=schedule) type(doorbirdapi_mock).energize_relay = AsyncMock(return_value=True) type(doorbirdapi_mock).turn_light_on = AsyncMock(return_value=True) @@ -59,3 +69,14 @@ def get_mock_doorbird_api( side_effect=mock_unauthorized_exception() ) return doorbirdapi_mock + + +async def mock_webhook_call( + config_entry: config_entries.ConfigEntry, + aiohttp_client: aiohttp.ClientSession, + event: str, +) -> None: + """Mock the webhook call.""" + token = config_entry.data.get(CONF_TOKEN, config_entry.entry_id) + response = await aiohttp_client.get(f"{API_URL}/{event}?token={token}") + response.raise_for_status() diff --git a/tests/components/doorbird/conftest.py b/tests/components/doorbird/conftest.py index f98fcf0eac8..cd3e410624d 100644 --- a/tests/components/doorbird/conftest.py +++ b/tests/components/doorbird/conftest.py @@ -9,7 +9,12 @@ from unittest.mock import MagicMock, patch from doorbirdpy import DoorBird, DoorBirdScheduleEntry import pytest -from homeassistant.components.doorbird.const import CONF_EVENTS, DOMAIN +from homeassistant.components.doorbird.const import ( + CONF_EVENTS, + DEFAULT_DOORBELL_EVENT, + DEFAULT_MOTION_EVENT, + DOMAIN, +) from homeassistant.core import HomeAssistant from . import VALID_CONFIG, get_mock_doorbird_api @@ -41,6 +46,12 @@ def doorbird_schedule() -> list[DoorBirdScheduleEntry]: ) +@pytest.fixture(scope="session") +def doorbird_favorites() -> dict[str, dict[str, Any]]: + """Return a loaded DoorBird favorites fixture.""" + return load_json_value_fixture("favorites.json", "doorbird") + + @pytest.fixture def doorbird_api( doorbird_info: dict[str, Any], doorbird_schedule: dict[str, Any] @@ -72,6 +83,7 @@ async def doorbird_mocker( hass: HomeAssistant, doorbird_info: dict[str, Any], doorbird_schedule: dict[str, Any], + doorbird_favorites: dict[str, dict[str, Any]], ) -> DoorbirdMockerType: """Create a MockDoorbirdEntry.""" @@ -81,6 +93,7 @@ async def doorbird_mocker( 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, ) -> MockDoorbirdEntry: """Create a MockDoorbirdEntry from defaults or specific values.""" @@ -88,12 +101,13 @@ async def doorbird_mocker( domain=DOMAIN, unique_id="1CCAE3AAAAAA", data=VALID_CONFIG, - options={CONF_EVENTS: ["event1", "event2", "event3"]}, + options={CONF_EVENTS: [DEFAULT_DOORBELL_EVENT, DEFAULT_MOTION_EVENT]}, ) api = api or get_mock_doorbird_api( info=info or doorbird_info, info_side_effect=info_side_effect, schedule=schedule or doorbird_schedule, + favorites=favorites or doorbird_favorites, favorites_side_effect=favorites_side_effect, ) entry.add_to_hass(hass) diff --git a/tests/components/doorbird/fixtures/favorites.json b/tests/components/doorbird/fixtures/favorites.json new file mode 100644 index 00000000000..c56f79c0300 --- /dev/null +++ b/tests/components/doorbird/fixtures/favorites.json @@ -0,0 +1,12 @@ +{ + "http": { + "0": { + "title": "Home Assistant (mydoorbird_doorbell)", + "value": "http://127.0.0.1:8123/api/doorbird/mydoorbird_doorbell?token=01J2F4B97Y7P1SARXEJ6W07EKD" + }, + "1": { + "title": "Home Assistant (mydoorbird_motion)", + "value": "http://127.0.0.1:8123/api/doorbird/mydoorbird_motion?token=01J2F4B97Y7P1SARXEJ6W07EKD" + } + } +} diff --git a/tests/components/doorbird/test_button.py b/tests/components/doorbird/test_button.py index fc10362a077..2131e3d6133 100644 --- a/tests/components/doorbird/test_button.py +++ b/tests/components/doorbird/test_button.py @@ -49,4 +49,4 @@ async def test_reset_favorites_button( DOMAIN, SERVICE_PRESS, {ATTR_ENTITY_ID: reset_entity_id}, blocking=True ) assert hass.states.get(reset_entity_id).state != STATE_UNKNOWN - assert doorbird_entry.api.delete_favorite.call_count == 1 + assert doorbird_entry.api.delete_favorite.call_count == 2 diff --git a/tests/components/doorbird/test_event.py b/tests/components/doorbird/test_event.py new file mode 100644 index 00000000000..11e0f3a306d --- /dev/null +++ b/tests/components/doorbird/test_event.py @@ -0,0 +1,37 @@ +"""Test DoorBird events.""" + +from homeassistant.const import STATE_UNKNOWN +from homeassistant.core import HomeAssistant + +from . import mock_webhook_call +from .conftest import DoorbirdMockerType + +from tests.typing import ClientSessionGenerator + + +async def test_doorbell_ring_event( + hass: HomeAssistant, + hass_client: ClientSessionGenerator, + doorbird_mocker: DoorbirdMockerType, +) -> None: + """Test a doorbell ring event.""" + doorbird_entry = await doorbird_mocker() + relay_1_entity_id = "event.mydoorbird_doorbell" + assert hass.states.get(relay_1_entity_id).state == STATE_UNKNOWN + client = await hass_client() + await mock_webhook_call(doorbird_entry.entry, client, "mydoorbird_doorbell") + assert hass.states.get(relay_1_entity_id).state != STATE_UNKNOWN + + +async def test_motion_event( + hass: HomeAssistant, + hass_client: ClientSessionGenerator, + doorbird_mocker: DoorbirdMockerType, +) -> None: + """Test a doorbell motion event.""" + doorbird_entry = await doorbird_mocker() + relay_1_entity_id = "event.mydoorbird_motion" + assert hass.states.get(relay_1_entity_id).state == STATE_UNKNOWN + client = await hass_client() + await mock_webhook_call(doorbird_entry.entry, client, "mydoorbird_motion") + assert hass.states.get(relay_1_entity_id).state != STATE_UNKNOWN