From 13ebc6fb0e6cc4c9a5d96524bd2648c58fdd59ee Mon Sep 17 00:00:00 2001 From: G Johansson Date: Wed, 29 May 2024 10:34:20 +0200 Subject: [PATCH] Add more tests to Yale Smart Alarm (#116501) --- .coveragerc | 3 - tests/components/yale_smart_alarm/conftest.py | 56 +-- .../snapshots/test_alarm_control_panel.ambr | 51 +++ .../snapshots/test_binary_sensor.ambr | 330 ++++++++++++++++++ .../snapshots/test_button.ambr | 47 +++ .../yale_smart_alarm/snapshots/test_lock.ambr | 289 +++++++++++++++ .../test_alarm_control_panel.py | 29 ++ .../yale_smart_alarm/test_binary_sensor.py | 29 ++ .../yale_smart_alarm/test_button.py | 58 +++ .../components/yale_smart_alarm/test_lock.py | 178 ++++++++++ 10 files changed, 1043 insertions(+), 27 deletions(-) create mode 100644 tests/components/yale_smart_alarm/snapshots/test_alarm_control_panel.ambr create mode 100644 tests/components/yale_smart_alarm/snapshots/test_binary_sensor.ambr create mode 100644 tests/components/yale_smart_alarm/snapshots/test_button.ambr create mode 100644 tests/components/yale_smart_alarm/snapshots/test_lock.ambr create mode 100644 tests/components/yale_smart_alarm/test_alarm_control_panel.py create mode 100644 tests/components/yale_smart_alarm/test_binary_sensor.py create mode 100644 tests/components/yale_smart_alarm/test_button.py create mode 100644 tests/components/yale_smart_alarm/test_lock.py diff --git a/.coveragerc b/.coveragerc index 410f138867f..4e78ea6a3e4 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1656,10 +1656,7 @@ omit = homeassistant/components/xs1/* homeassistant/components/yale_smart_alarm/__init__.py homeassistant/components/yale_smart_alarm/alarm_control_panel.py - homeassistant/components/yale_smart_alarm/binary_sensor.py - homeassistant/components/yale_smart_alarm/button.py homeassistant/components/yale_smart_alarm/entity.py - homeassistant/components/yale_smart_alarm/lock.py homeassistant/components/yalexs_ble/__init__.py homeassistant/components/yalexs_ble/binary_sensor.py homeassistant/components/yalexs_ble/entity.py diff --git a/tests/components/yale_smart_alarm/conftest.py b/tests/components/yale_smart_alarm/conftest.py index 211367a2922..9583df5faa6 100644 --- a/tests/components/yale_smart_alarm/conftest.py +++ b/tests/components/yale_smart_alarm/conftest.py @@ -9,8 +9,9 @@ from unittest.mock import Mock, patch import pytest from yalesmartalarmclient.const import YALE_STATE_ARM_FULL -from homeassistant.components.yale_smart_alarm.const import DOMAIN +from homeassistant.components.yale_smart_alarm.const import DOMAIN, PLATFORMS from homeassistant.config_entries import SOURCE_USER +from homeassistant.const import Platform from homeassistant.core import HomeAssistant from tests.common import MockConfigEntry, load_fixture @@ -24,36 +25,43 @@ ENTRY_CONFIG = { OPTIONS_CONFIG = {"lock_code_digits": 6} +@pytest.fixture(name="load_platforms") +async def patch_platform_constant() -> list[Platform]: + """Return list of platforms to load.""" + return PLATFORMS + + @pytest.fixture async def load_config_entry( - hass: HomeAssistant, load_json: dict[str, Any] + hass: HomeAssistant, load_json: dict[str, Any], load_platforms: list[Platform] ) -> tuple[MockConfigEntry, Mock]: """Set up the Yale Smart Living integration in Home Assistant.""" - config_entry = MockConfigEntry( - domain=DOMAIN, - source=SOURCE_USER, - data=ENTRY_CONFIG, - options=OPTIONS_CONFIG, - entry_id="1", - unique_id="username", - version=1, - ) + with patch("homeassistant.components.yale_smart_alarm.PLATFORMS", load_platforms): + config_entry = MockConfigEntry( + domain=DOMAIN, + source=SOURCE_USER, + data=ENTRY_CONFIG, + options=OPTIONS_CONFIG, + entry_id="1", + unique_id="username", + version=1, + ) - config_entry.add_to_hass(hass) + config_entry.add_to_hass(hass) - with patch( - "homeassistant.components.yale_smart_alarm.coordinator.YaleSmartAlarmClient", - autospec=True, - ) as mock_client_class: - client = mock_client_class.return_value - client.auth = None - client.lock_api = None - client.get_all.return_value = load_json - client.get_armed_status.return_value = YALE_STATE_ARM_FULL - await hass.config_entries.async_setup(config_entry.entry_id) - await hass.async_block_till_done() + with patch( + "homeassistant.components.yale_smart_alarm.coordinator.YaleSmartAlarmClient", + autospec=True, + ) as mock_client_class: + client = mock_client_class.return_value + client.auth = Mock() + client.lock_api = Mock() + client.get_all.return_value = load_json + client.get_armed_status.return_value = YALE_STATE_ARM_FULL + await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() - return (config_entry, client) + return (config_entry, client) @pytest.fixture(name="load_json", scope="package") diff --git a/tests/components/yale_smart_alarm/snapshots/test_alarm_control_panel.ambr b/tests/components/yale_smart_alarm/snapshots/test_alarm_control_panel.ambr new file mode 100644 index 00000000000..749e62252f3 --- /dev/null +++ b/tests/components/yale_smart_alarm/snapshots/test_alarm_control_panel.ambr @@ -0,0 +1,51 @@ +# serializer version: 1 +# name: test_alarm_control_panel[load_platforms0][alarm_control_panel.yale_smart_alarm-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'alarm_control_panel', + 'entity_category': None, + 'entity_id': 'alarm_control_panel.yale_smart_alarm', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': None, + 'platform': 'yale_smart_alarm', + 'previous_unique_id': None, + 'supported_features': , + 'translation_key': None, + 'unique_id': '1', + 'unit_of_measurement': None, + }) +# --- +# name: test_alarm_control_panel[load_platforms0][alarm_control_panel.yale_smart_alarm-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'changed_by': None, + 'code_arm_required': False, + 'code_format': None, + 'friendly_name': 'Yale Smart Alarm', + 'supported_features': , + }), + 'context': , + 'entity_id': 'alarm_control_panel.yale_smart_alarm', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'armed_away', + }) +# --- diff --git a/tests/components/yale_smart_alarm/snapshots/test_binary_sensor.ambr b/tests/components/yale_smart_alarm/snapshots/test_binary_sensor.ambr new file mode 100644 index 00000000000..7bb144e8d2a --- /dev/null +++ b/tests/components/yale_smart_alarm/snapshots/test_binary_sensor.ambr @@ -0,0 +1,330 @@ +# serializer version: 1 +# name: test_binary_sensor[load_platforms0][binary_sensor.device4_door-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': None, + 'entity_id': 'binary_sensor.device4_door', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Door', + 'platform': 'yale_smart_alarm', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': 'RF4', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensor[load_platforms0][binary_sensor.device4_door-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'door', + 'friendly_name': 'Device4 Door', + }), + 'context': , + 'entity_id': 'binary_sensor.device4_door', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_binary_sensor[load_platforms0][binary_sensor.device5_door-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': None, + 'entity_id': 'binary_sensor.device5_door', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Door', + 'platform': 'yale_smart_alarm', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': 'RF5', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensor[load_platforms0][binary_sensor.device5_door-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'door', + 'friendly_name': 'Device5 Door', + }), + 'context': , + 'entity_id': 'binary_sensor.device5_door', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'on', + }) +# --- +# name: test_binary_sensor[load_platforms0][binary_sensor.device6_door-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': None, + 'entity_id': 'binary_sensor.device6_door', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Door', + 'platform': 'yale_smart_alarm', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': 'RF6', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensor[load_platforms0][binary_sensor.device6_door-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'door', + 'friendly_name': 'Device6 Door', + }), + 'context': , + 'entity_id': 'binary_sensor.device6_door', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_binary_sensor[load_platforms0][binary_sensor.yale_smart_alarm_battery-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.yale_smart_alarm_battery', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Battery', + 'platform': 'yale_smart_alarm', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'battery', + 'unique_id': '1-battery', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensor[load_platforms0][binary_sensor.yale_smart_alarm_battery-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'problem', + 'friendly_name': 'Yale Smart Alarm Battery', + }), + 'context': , + 'entity_id': 'binary_sensor.yale_smart_alarm_battery', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_binary_sensor[load_platforms0][binary_sensor.yale_smart_alarm_jam-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.yale_smart_alarm_jam', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Jam', + 'platform': 'yale_smart_alarm', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'jam', + 'unique_id': '1-jam', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensor[load_platforms0][binary_sensor.yale_smart_alarm_jam-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'problem', + 'friendly_name': 'Yale Smart Alarm Jam', + }), + 'context': , + 'entity_id': 'binary_sensor.yale_smart_alarm_jam', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_binary_sensor[load_platforms0][binary_sensor.yale_smart_alarm_power_loss-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.yale_smart_alarm_power_loss', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Power loss', + 'platform': 'yale_smart_alarm', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'power_loss', + 'unique_id': '1-acfail', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensor[load_platforms0][binary_sensor.yale_smart_alarm_power_loss-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'problem', + 'friendly_name': 'Yale Smart Alarm Power loss', + }), + 'context': , + 'entity_id': 'binary_sensor.yale_smart_alarm_power_loss', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_binary_sensor[load_platforms0][binary_sensor.yale_smart_alarm_tamper-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.yale_smart_alarm_tamper', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Tamper', + 'platform': 'yale_smart_alarm', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'tamper', + 'unique_id': '1-tamper', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensor[load_platforms0][binary_sensor.yale_smart_alarm_tamper-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'problem', + 'friendly_name': 'Yale Smart Alarm Tamper', + }), + 'context': , + 'entity_id': 'binary_sensor.yale_smart_alarm_tamper', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- diff --git a/tests/components/yale_smart_alarm/snapshots/test_button.ambr b/tests/components/yale_smart_alarm/snapshots/test_button.ambr new file mode 100644 index 00000000000..8abceb0affa --- /dev/null +++ b/tests/components/yale_smart_alarm/snapshots/test_button.ambr @@ -0,0 +1,47 @@ +# serializer version: 1 +# name: test_button[load_platforms0][button.yale_smart_alarm_panic_button-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'button', + 'entity_category': None, + 'entity_id': 'button.yale_smart_alarm_panic_button', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Panic button', + 'platform': 'yale_smart_alarm', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'panic', + 'unique_id': 'yale_smart_alarm-panic', + 'unit_of_measurement': None, + }) +# --- +# name: test_button[load_platforms0][button.yale_smart_alarm_panic_button-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Yale Smart Alarm Panic button', + }), + 'context': , + 'entity_id': 'button.yale_smart_alarm_panic_button', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '2024-04-29T18:00:00.612351+00:00', + }) +# --- diff --git a/tests/components/yale_smart_alarm/snapshots/test_lock.ambr b/tests/components/yale_smart_alarm/snapshots/test_lock.ambr new file mode 100644 index 00000000000..da9c11e01d2 --- /dev/null +++ b/tests/components/yale_smart_alarm/snapshots/test_lock.ambr @@ -0,0 +1,289 @@ +# serializer version: 1 +# name: test_lock[load_platforms0][lock.device1-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'lock', + 'entity_category': None, + 'entity_id': 'lock.device1', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': None, + 'platform': 'yale_smart_alarm', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': '1111', + 'unit_of_measurement': None, + }) +# --- +# name: test_lock[load_platforms0][lock.device1-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'code_format': '^\\d{6}$', + 'friendly_name': 'Device1', + 'supported_features': , + }), + 'context': , + 'entity_id': 'lock.device1', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'locked', + }) +# --- +# name: test_lock[load_platforms0][lock.device2-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'lock', + 'entity_category': None, + 'entity_id': 'lock.device2', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': None, + 'platform': 'yale_smart_alarm', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': '2222', + 'unit_of_measurement': None, + }) +# --- +# name: test_lock[load_platforms0][lock.device2-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'code_format': '^\\d{6}$', + 'friendly_name': 'Device2', + 'supported_features': , + }), + 'context': , + 'entity_id': 'lock.device2', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'unlocked', + }) +# --- +# name: test_lock[load_platforms0][lock.device3-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'lock', + 'entity_category': None, + 'entity_id': 'lock.device3', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': None, + 'platform': 'yale_smart_alarm', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': '3333', + 'unit_of_measurement': None, + }) +# --- +# name: test_lock[load_platforms0][lock.device3-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'code_format': '^\\d{6}$', + 'friendly_name': 'Device3', + 'supported_features': , + }), + 'context': , + 'entity_id': 'lock.device3', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'locked', + }) +# --- +# name: test_lock[load_platforms0][lock.device7-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'lock', + 'entity_category': None, + 'entity_id': 'lock.device7', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': None, + 'platform': 'yale_smart_alarm', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': '7777', + 'unit_of_measurement': None, + }) +# --- +# name: test_lock[load_platforms0][lock.device7-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'code_format': '^\\d{6}$', + 'friendly_name': 'Device7', + 'supported_features': , + }), + 'context': , + 'entity_id': 'lock.device7', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'unlocked', + }) +# --- +# name: test_lock[load_platforms0][lock.device8-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'lock', + 'entity_category': None, + 'entity_id': 'lock.device8', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': None, + 'platform': 'yale_smart_alarm', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': '8888', + 'unit_of_measurement': None, + }) +# --- +# name: test_lock[load_platforms0][lock.device8-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'code_format': '^\\d{6}$', + 'friendly_name': 'Device8', + 'supported_features': , + }), + 'context': , + 'entity_id': 'lock.device8', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'unlocked', + }) +# --- +# name: test_lock[load_platforms0][lock.device9-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'lock', + 'entity_category': None, + 'entity_id': 'lock.device9', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': None, + 'platform': 'yale_smart_alarm', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': '9999', + 'unit_of_measurement': None, + }) +# --- +# name: test_lock[load_platforms0][lock.device9-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'code_format': '^\\d{6}$', + 'friendly_name': 'Device9', + 'supported_features': , + }), + 'context': , + 'entity_id': 'lock.device9', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'unlocked', + }) +# --- diff --git a/tests/components/yale_smart_alarm/test_alarm_control_panel.py b/tests/components/yale_smart_alarm/test_alarm_control_panel.py new file mode 100644 index 00000000000..4e8330df071 --- /dev/null +++ b/tests/components/yale_smart_alarm/test_alarm_control_panel.py @@ -0,0 +1,29 @@ +"""The test for the Yale Smart ALarm alarm control panel platform.""" + +from __future__ import annotations + +from unittest.mock import Mock + +import pytest +from syrupy.assertion import SnapshotAssertion + +from homeassistant.const import Platform +from homeassistant.core import HomeAssistant +from homeassistant.helpers import entity_registry as er + +from tests.common import MockConfigEntry, snapshot_platform + + +@pytest.mark.parametrize( + "load_platforms", + [[Platform.ALARM_CONTROL_PANEL]], +) +async def test_alarm_control_panel( + hass: HomeAssistant, + load_config_entry: tuple[MockConfigEntry, Mock], + entity_registry: er.EntityRegistry, + snapshot: SnapshotAssertion, +) -> None: + """Test the Yale Smart Alarm alarm_control_panel.""" + entry = load_config_entry[0] + await snapshot_platform(hass, entity_registry, snapshot, entry.entry_id) diff --git a/tests/components/yale_smart_alarm/test_binary_sensor.py b/tests/components/yale_smart_alarm/test_binary_sensor.py new file mode 100644 index 00000000000..dc503a00e97 --- /dev/null +++ b/tests/components/yale_smart_alarm/test_binary_sensor.py @@ -0,0 +1,29 @@ +"""The test for the Yale Smart Alarm binary sensor platform.""" + +from __future__ import annotations + +from unittest.mock import Mock + +import pytest +from syrupy.assertion import SnapshotAssertion + +from homeassistant.const import Platform +from homeassistant.core import HomeAssistant +from homeassistant.helpers import entity_registry as er + +from tests.common import MockConfigEntry, snapshot_platform + + +@pytest.mark.parametrize( + "load_platforms", + [[Platform.BINARY_SENSOR]], +) +async def test_binary_sensor( + hass: HomeAssistant, + load_config_entry: tuple[MockConfigEntry, Mock], + entity_registry: er.EntityRegistry, + snapshot: SnapshotAssertion, +) -> None: + """Test the Yale Smart Alarm binary sensor.""" + entry = load_config_entry[0] + await snapshot_platform(hass, entity_registry, snapshot, entry.entry_id) diff --git a/tests/components/yale_smart_alarm/test_button.py b/tests/components/yale_smart_alarm/test_button.py new file mode 100644 index 00000000000..e6fed9d94ae --- /dev/null +++ b/tests/components/yale_smart_alarm/test_button.py @@ -0,0 +1,58 @@ +"""The test for the Yale Smart ALarm button platform.""" + +from __future__ import annotations + +from unittest.mock import Mock + +from freezegun import freeze_time +import pytest +from syrupy.assertion import SnapshotAssertion +from yalesmartalarmclient.exceptions import UnknownError + +from homeassistant.components.button import DOMAIN as BUTTON_DOMAIN +from homeassistant.components.button.const import SERVICE_PRESS +from homeassistant.const import ATTR_ENTITY_ID, Platform +from homeassistant.core import HomeAssistant +from homeassistant.exceptions import HomeAssistantError +from homeassistant.helpers import entity_registry as er + +from tests.common import MockConfigEntry, snapshot_platform + + +@freeze_time("2024-04-29T18:00:00.612351+00:00") +@pytest.mark.parametrize( + "load_platforms", + [[Platform.BUTTON]], +) +async def test_button( + hass: HomeAssistant, + load_config_entry: tuple[MockConfigEntry, Mock], + entity_registry: er.EntityRegistry, + snapshot: SnapshotAssertion, +) -> None: + """Test the Yale Smart Alarm button.""" + entry = load_config_entry[0] + client = load_config_entry[1] + client.trigger_panic_button = Mock(return_value=True) + await hass.services.async_call( + BUTTON_DOMAIN, + SERVICE_PRESS, + { + ATTR_ENTITY_ID: "button.yale_smart_alarm_panic_button", + }, + blocking=True, + ) + await snapshot_platform(hass, entity_registry, snapshot, entry.entry_id) + client.trigger_panic_button.assert_called_once() + client.trigger_panic_button.reset_mock() + client.trigger_panic_button = Mock(side_effect=UnknownError("test_side_effect")) + with pytest.raises(HomeAssistantError): + await hass.services.async_call( + BUTTON_DOMAIN, + SERVICE_PRESS, + { + ATTR_ENTITY_ID: "button.yale_smart_alarm_panic_button", + }, + blocking=True, + ) + client.trigger_panic_button.assert_called_once() diff --git a/tests/components/yale_smart_alarm/test_lock.py b/tests/components/yale_smart_alarm/test_lock.py new file mode 100644 index 00000000000..09ce8529084 --- /dev/null +++ b/tests/components/yale_smart_alarm/test_lock.py @@ -0,0 +1,178 @@ +"""The test for the Yale Smart ALarm lock platform.""" + +from __future__ import annotations + +from copy import deepcopy +from typing import Any +from unittest.mock import Mock + +import pytest +from syrupy.assertion import SnapshotAssertion +from yalesmartalarmclient.exceptions import UnknownError +from yalesmartalarmclient.lock import YaleDoorManAPI + +from homeassistant.components.lock import DOMAIN as LOCK_DOMAIN +from homeassistant.const import ( + ATTR_CODE, + ATTR_ENTITY_ID, + SERVICE_LOCK, + SERVICE_UNLOCK, + Platform, +) +from homeassistant.core import HomeAssistant +from homeassistant.exceptions import HomeAssistantError +from homeassistant.helpers import entity_registry as er + +from tests.common import MockConfigEntry, snapshot_platform + + +@pytest.mark.parametrize( + "load_platforms", + [[Platform.LOCK]], +) +async def test_lock( + hass: HomeAssistant, + load_config_entry: tuple[MockConfigEntry, Mock], + entity_registry: er.EntityRegistry, + snapshot: SnapshotAssertion, +) -> None: + """Test the Yale Smart Alarm lock.""" + entry = load_config_entry[0] + await snapshot_platform(hass, entity_registry, snapshot, entry.entry_id) + + +@pytest.mark.parametrize( + "load_platforms", + [[Platform.LOCK]], +) +async def test_lock_service_calls( + hass: HomeAssistant, + load_json: dict[str, Any], + load_config_entry: tuple[MockConfigEntry, Mock], + entity_registry: er.EntityRegistry, + snapshot: SnapshotAssertion, +) -> None: + """Test the Yale Smart Alarm lock.""" + + client = load_config_entry[1] + + data = deepcopy(load_json) + data["data"] = data.pop("DEVICES") + + client.auth.get_authenticated = Mock(return_value=data) + client.auth.post_authenticated = Mock(return_value={"code": "000"}) + client.lock_api = YaleDoorManAPI(client.auth) + + state = hass.states.get("lock.device1") + assert state.state == "locked" + + await hass.services.async_call( + LOCK_DOMAIN, + SERVICE_UNLOCK, + {ATTR_ENTITY_ID: "lock.device1", ATTR_CODE: "123456"}, + blocking=True, + ) + client.auth.post_authenticated.assert_called_once() + state = hass.states.get("lock.device1") + assert state.state == "unlocked" + client.auth.post_authenticated.reset_mock() + await hass.services.async_call( + LOCK_DOMAIN, + SERVICE_LOCK, + {ATTR_ENTITY_ID: "lock.device1", ATTR_CODE: "123456"}, + blocking=True, + ) + client.auth.post_authenticated.assert_called_once() + state = hass.states.get("lock.device1") + assert state.state == "locked" + + +@pytest.mark.parametrize( + "load_platforms", + [[Platform.LOCK]], +) +async def test_lock_service_call_fails( + hass: HomeAssistant, + load_json: dict[str, Any], + load_config_entry: tuple[MockConfigEntry, Mock], + entity_registry: er.EntityRegistry, + snapshot: SnapshotAssertion, +) -> None: + """Test the Yale Smart Alarm lock service call fails.""" + + client = load_config_entry[1] + + data = deepcopy(load_json) + data["data"] = data.pop("DEVICES") + + client.auth.get_authenticated = Mock(return_value=data) + client.auth.post_authenticated = Mock(side_effect=UnknownError("test_side_effect")) + client.lock_api = YaleDoorManAPI(client.auth) + + state = hass.states.get("lock.device1") + assert state.state == "locked" + + with pytest.raises( + HomeAssistantError, + match="Could not set lock for Device1: test_side_effect", + ): + await hass.services.async_call( + LOCK_DOMAIN, + SERVICE_UNLOCK, + {ATTR_ENTITY_ID: "lock.device1", ATTR_CODE: "123456"}, + blocking=True, + ) + client.auth.post_authenticated.assert_called_once() + state = hass.states.get("lock.device1") + assert state.state == "locked" + client.auth.post_authenticated.reset_mock() + with pytest.raises( + HomeAssistantError, + match="Could not set lock for Device1: test_side_effect", + ): + await hass.services.async_call( + LOCK_DOMAIN, + SERVICE_LOCK, + {ATTR_ENTITY_ID: "lock.device1", ATTR_CODE: "123456"}, + blocking=True, + ) + client.auth.post_authenticated.assert_called_once() + + +@pytest.mark.parametrize( + "load_platforms", + [[Platform.LOCK]], +) +async def test_lock_service_call_fails_with_incorrect_status( + hass: HomeAssistant, + load_json: dict[str, Any], + load_config_entry: tuple[MockConfigEntry, Mock], + entity_registry: er.EntityRegistry, + snapshot: SnapshotAssertion, +) -> None: + """Test the Yale Smart Alarm lock service call fails with incorrect return state.""" + + client = load_config_entry[1] + + data = deepcopy(load_json) + data["data"] = data.pop("DEVICES") + + client.auth.get_authenticated = Mock(return_value=data) + client.auth.post_authenticated = Mock(return_value={"code": "FFF"}) + client.lock_api = YaleDoorManAPI(client.auth) + + state = hass.states.get("lock.device1") + assert state.state == "locked" + + with pytest.raises( + HomeAssistantError, match="Could not set lock, check system ready for lock" + ): + await hass.services.async_call( + LOCK_DOMAIN, + SERVICE_UNLOCK, + {ATTR_ENTITY_ID: "lock.device1", ATTR_CODE: "123456"}, + blocking=True, + ) + client.auth.post_authenticated.assert_called_once() + state = hass.states.get("lock.device1") + assert state.state == "locked"