From 1eb13b48a2c894b47d6d0b1f5fd45c1e55ae71f9 Mon Sep 17 00:00:00 2001 From: Richard Kroegel <42204099+rikroe@users.noreply.github.com> Date: Tue, 4 Jun 2024 15:08:15 +0200 Subject: [PATCH] Add tests for BMW binary_sensor and lock (#118436) * BMW: Add tests for binary_sensor & lock * Use entity_registry_enabled_by_default fixture * Update tests/components/bmw_connected_drive/test_binary_sensor.py Co-authored-by: epenet <6771947+epenet@users.noreply.github.com> * Move fixtures to decorator Co-authored-by: epenet <6771947+epenet@users.noreply.github.com> * Use fixture decorators if possible * Fix rebase * Spelling adjustments Co-authored-by: epenet <6771947+epenet@users.noreply.github.com> * Use snapshot_platform helper * Spelling * Remove comment --------- Co-authored-by: Richard Co-authored-by: epenet <6771947+epenet@users.noreply.github.com> --- .coveragerc | 5 - .../snapshots/test_binary_sensor.ambr | 1523 +++++++++++++++++ .../snapshots/test_lock.ambr | 205 +++ .../bmw_connected_drive/test_binary_sensor.py | 35 + .../bmw_connected_drive/test_lock.py | 139 ++ 5 files changed, 1902 insertions(+), 5 deletions(-) create mode 100644 tests/components/bmw_connected_drive/snapshots/test_binary_sensor.ambr create mode 100644 tests/components/bmw_connected_drive/snapshots/test_lock.ambr create mode 100644 tests/components/bmw_connected_drive/test_binary_sensor.py create mode 100644 tests/components/bmw_connected_drive/test_lock.py diff --git a/.coveragerc b/.coveragerc index e556d0aab85..034598d2044 100644 --- a/.coveragerc +++ b/.coveragerc @@ -149,12 +149,7 @@ omit = homeassistant/components/bloomsky/* homeassistant/components/bluesound/* homeassistant/components/bluetooth_tracker/* - homeassistant/components/bmw_connected_drive/__init__.py - homeassistant/components/bmw_connected_drive/binary_sensor.py - homeassistant/components/bmw_connected_drive/coordinator.py - homeassistant/components/bmw_connected_drive/lock.py homeassistant/components/bmw_connected_drive/notify.py - homeassistant/components/bmw_connected_drive/sensor.py homeassistant/components/bosch_shc/__init__.py homeassistant/components/bosch_shc/binary_sensor.py homeassistant/components/bosch_shc/cover.py diff --git a/tests/components/bmw_connected_drive/snapshots/test_binary_sensor.ambr b/tests/components/bmw_connected_drive/snapshots/test_binary_sensor.ambr new file mode 100644 index 00000000000..610e194c0e5 --- /dev/null +++ b/tests/components/bmw_connected_drive/snapshots/test_binary_sensor.ambr @@ -0,0 +1,1523 @@ +# serializer version: 1 +# name: test_entity_state_attrs[binary_sensor.i3_rex_charging_status-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.i3_rex_charging_status', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Charging status', + 'platform': 'bmw_connected_drive', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'charging_status', + 'unique_id': 'WBY00000000REXI01-charging_status', + 'unit_of_measurement': None, + }) +# --- +# name: test_entity_state_attrs[binary_sensor.i3_rex_charging_status-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by MyBMW', + 'device_class': 'battery_charging', + 'friendly_name': 'i3 (+ REX) Charging status', + }), + 'context': , + 'entity_id': 'binary_sensor.i3_rex_charging_status', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_entity_state_attrs[binary_sensor.i3_rex_check_control_messages-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.i3_rex_check_control_messages', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Check control messages', + 'platform': 'bmw_connected_drive', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'check_control_messages', + 'unique_id': 'WBY00000000REXI01-check_control_messages', + 'unit_of_measurement': None, + }) +# --- +# name: test_entity_state_attrs[binary_sensor.i3_rex_check_control_messages-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by MyBMW', + 'car': 'i3 (+ REX)', + 'device_class': 'problem', + 'friendly_name': 'i3 (+ REX) Check control messages', + 'vin': 'WBY00000000REXI01', + }), + 'context': , + 'entity_id': 'binary_sensor.i3_rex_check_control_messages', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_entity_state_attrs[binary_sensor.i3_rex_condition_based_services-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.i3_rex_condition_based_services', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Condition based services', + 'platform': 'bmw_connected_drive', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'condition_based_services', + 'unique_id': 'WBY00000000REXI01-condition_based_services', + 'unit_of_measurement': None, + }) +# --- +# name: test_entity_state_attrs[binary_sensor.i3_rex_condition_based_services-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by MyBMW', + 'brake_fluid': 'OK', + 'brake_fluid_date': '2022-10-01', + 'car': 'i3 (+ REX)', + 'device_class': 'problem', + 'friendly_name': 'i3 (+ REX) Condition based services', + 'vehicle_check': 'OK', + 'vehicle_check_date': '2023-05-01', + 'vehicle_tuv': 'OK', + 'vehicle_tuv_date': '2023-05-01', + 'vin': 'WBY00000000REXI01', + }), + 'context': , + 'entity_id': 'binary_sensor.i3_rex_condition_based_services', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_entity_state_attrs[binary_sensor.i3_rex_connection_status-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.i3_rex_connection_status', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Connection status', + 'platform': 'bmw_connected_drive', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'connection_status', + 'unique_id': 'WBY00000000REXI01-connection_status', + 'unit_of_measurement': None, + }) +# --- +# name: test_entity_state_attrs[binary_sensor.i3_rex_connection_status-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by MyBMW', + 'device_class': 'plug', + 'friendly_name': 'i3 (+ REX) Connection status', + }), + 'context': , + 'entity_id': 'binary_sensor.i3_rex_connection_status', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'on', + }) +# --- +# name: test_entity_state_attrs[binary_sensor.i3_rex_door_lock_state-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.i3_rex_door_lock_state', + '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 lock state', + 'platform': 'bmw_connected_drive', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'door_lock_state', + 'unique_id': 'WBY00000000REXI01-door_lock_state', + 'unit_of_measurement': None, + }) +# --- +# name: test_entity_state_attrs[binary_sensor.i3_rex_door_lock_state-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by MyBMW', + 'car': 'i3 (+ REX)', + 'device_class': 'lock', + 'door_lock_state': 'UNLOCKED', + 'friendly_name': 'i3 (+ REX) Door lock state', + 'vin': 'WBY00000000REXI01', + }), + 'context': , + 'entity_id': 'binary_sensor.i3_rex_door_lock_state', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'on', + }) +# --- +# name: test_entity_state_attrs[binary_sensor.i3_rex_lids-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.i3_rex_lids', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Lids', + 'platform': 'bmw_connected_drive', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'lids', + 'unique_id': 'WBY00000000REXI01-lids', + 'unit_of_measurement': None, + }) +# --- +# name: test_entity_state_attrs[binary_sensor.i3_rex_lids-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by MyBMW', + 'car': 'i3 (+ REX)', + 'device_class': 'opening', + 'friendly_name': 'i3 (+ REX) Lids', + 'hood': 'CLOSED', + 'leftFront': 'CLOSED', + 'leftRear': 'CLOSED', + 'rightFront': 'CLOSED', + 'rightRear': 'CLOSED', + 'sunRoof': 'CLOSED', + 'trunk': 'CLOSED', + 'vin': 'WBY00000000REXI01', + }), + 'context': , + 'entity_id': 'binary_sensor.i3_rex_lids', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_entity_state_attrs[binary_sensor.i3_rex_pre_entry_climatization-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.i3_rex_pre_entry_climatization', + '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': 'Pre entry climatization', + 'platform': 'bmw_connected_drive', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'is_pre_entry_climatization_enabled', + 'unique_id': 'WBY00000000REXI01-is_pre_entry_climatization_enabled', + 'unit_of_measurement': None, + }) +# --- +# name: test_entity_state_attrs[binary_sensor.i3_rex_pre_entry_climatization-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by MyBMW', + 'friendly_name': 'i3 (+ REX) Pre entry climatization', + }), + 'context': , + 'entity_id': 'binary_sensor.i3_rex_pre_entry_climatization', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_entity_state_attrs[binary_sensor.i3_rex_windows-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.i3_rex_windows', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Windows', + 'platform': 'bmw_connected_drive', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'windows', + 'unique_id': 'WBY00000000REXI01-windows', + 'unit_of_measurement': None, + }) +# --- +# name: test_entity_state_attrs[binary_sensor.i3_rex_windows-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by MyBMW', + 'car': 'i3 (+ REX)', + 'device_class': 'opening', + 'friendly_name': 'i3 (+ REX) Windows', + 'leftFront': 'CLOSED', + 'rightFront': 'CLOSED', + 'vin': 'WBY00000000REXI01', + }), + 'context': , + 'entity_id': 'binary_sensor.i3_rex_windows', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_entity_state_attrs[binary_sensor.i4_edrive40_charging_status-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.i4_edrive40_charging_status', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Charging status', + 'platform': 'bmw_connected_drive', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'charging_status', + 'unique_id': 'WBA00000000DEMO02-charging_status', + 'unit_of_measurement': None, + }) +# --- +# name: test_entity_state_attrs[binary_sensor.i4_edrive40_charging_status-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by MyBMW', + 'device_class': 'battery_charging', + 'friendly_name': 'i4 eDrive40 Charging status', + }), + 'context': , + 'entity_id': 'binary_sensor.i4_edrive40_charging_status', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_entity_state_attrs[binary_sensor.i4_edrive40_check_control_messages-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.i4_edrive40_check_control_messages', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Check control messages', + 'platform': 'bmw_connected_drive', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'check_control_messages', + 'unique_id': 'WBA00000000DEMO02-check_control_messages', + 'unit_of_measurement': None, + }) +# --- +# name: test_entity_state_attrs[binary_sensor.i4_edrive40_check_control_messages-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by MyBMW', + 'car': 'i4 eDrive40', + 'device_class': 'problem', + 'friendly_name': 'i4 eDrive40 Check control messages', + 'tire_pressure': 'LOW', + 'vin': 'WBA00000000DEMO02', + }), + 'context': , + 'entity_id': 'binary_sensor.i4_edrive40_check_control_messages', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_entity_state_attrs[binary_sensor.i4_edrive40_condition_based_services-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.i4_edrive40_condition_based_services', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Condition based services', + 'platform': 'bmw_connected_drive', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'condition_based_services', + 'unique_id': 'WBA00000000DEMO02-condition_based_services', + 'unit_of_measurement': None, + }) +# --- +# name: test_entity_state_attrs[binary_sensor.i4_edrive40_condition_based_services-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by MyBMW', + 'brake_fluid': 'OK', + 'brake_fluid_date': '2024-12-01', + 'brake_fluid_distance': '50000 km', + 'car': 'i4 eDrive40', + 'device_class': 'problem', + 'friendly_name': 'i4 eDrive40 Condition based services', + 'tire_wear_front': 'OK', + 'tire_wear_rear': 'OK', + 'vehicle_check': 'OK', + 'vehicle_check_date': '2024-12-01', + 'vehicle_check_distance': '50000 km', + 'vehicle_tuv': 'OK', + 'vehicle_tuv_date': '2024-12-01', + 'vehicle_tuv_distance': '50000 km', + 'vin': 'WBA00000000DEMO02', + }), + 'context': , + 'entity_id': 'binary_sensor.i4_edrive40_condition_based_services', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_entity_state_attrs[binary_sensor.i4_edrive40_connection_status-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.i4_edrive40_connection_status', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Connection status', + 'platform': 'bmw_connected_drive', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'connection_status', + 'unique_id': 'WBA00000000DEMO02-connection_status', + 'unit_of_measurement': None, + }) +# --- +# name: test_entity_state_attrs[binary_sensor.i4_edrive40_connection_status-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by MyBMW', + 'device_class': 'plug', + 'friendly_name': 'i4 eDrive40 Connection status', + }), + 'context': , + 'entity_id': 'binary_sensor.i4_edrive40_connection_status', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_entity_state_attrs[binary_sensor.i4_edrive40_door_lock_state-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.i4_edrive40_door_lock_state', + '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 lock state', + 'platform': 'bmw_connected_drive', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'door_lock_state', + 'unique_id': 'WBA00000000DEMO02-door_lock_state', + 'unit_of_measurement': None, + }) +# --- +# name: test_entity_state_attrs[binary_sensor.i4_edrive40_door_lock_state-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by MyBMW', + 'car': 'i4 eDrive40', + 'device_class': 'lock', + 'door_lock_state': 'LOCKED', + 'friendly_name': 'i4 eDrive40 Door lock state', + 'vin': 'WBA00000000DEMO02', + }), + 'context': , + 'entity_id': 'binary_sensor.i4_edrive40_door_lock_state', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_entity_state_attrs[binary_sensor.i4_edrive40_lids-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.i4_edrive40_lids', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Lids', + 'platform': 'bmw_connected_drive', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'lids', + 'unique_id': 'WBA00000000DEMO02-lids', + 'unit_of_measurement': None, + }) +# --- +# name: test_entity_state_attrs[binary_sensor.i4_edrive40_lids-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by MyBMW', + 'car': 'i4 eDrive40', + 'device_class': 'opening', + 'friendly_name': 'i4 eDrive40 Lids', + 'hood': 'CLOSED', + 'leftFront': 'CLOSED', + 'leftRear': 'CLOSED', + 'rightFront': 'CLOSED', + 'rightRear': 'CLOSED', + 'trunk': 'CLOSED', + 'vin': 'WBA00000000DEMO02', + }), + 'context': , + 'entity_id': 'binary_sensor.i4_edrive40_lids', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_entity_state_attrs[binary_sensor.i4_edrive40_pre_entry_climatization-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.i4_edrive40_pre_entry_climatization', + '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': 'Pre entry climatization', + 'platform': 'bmw_connected_drive', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'is_pre_entry_climatization_enabled', + 'unique_id': 'WBA00000000DEMO02-is_pre_entry_climatization_enabled', + 'unit_of_measurement': None, + }) +# --- +# name: test_entity_state_attrs[binary_sensor.i4_edrive40_pre_entry_climatization-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by MyBMW', + 'friendly_name': 'i4 eDrive40 Pre entry climatization', + }), + 'context': , + 'entity_id': 'binary_sensor.i4_edrive40_pre_entry_climatization', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_entity_state_attrs[binary_sensor.i4_edrive40_windows-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.i4_edrive40_windows', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Windows', + 'platform': 'bmw_connected_drive', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'windows', + 'unique_id': 'WBA00000000DEMO02-windows', + 'unit_of_measurement': None, + }) +# --- +# name: test_entity_state_attrs[binary_sensor.i4_edrive40_windows-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by MyBMW', + 'car': 'i4 eDrive40', + 'device_class': 'opening', + 'friendly_name': 'i4 eDrive40 Windows', + 'leftFront': 'CLOSED', + 'leftRear': 'CLOSED', + 'rear': 'CLOSED', + 'rightFront': 'CLOSED', + 'rightRear': 'CLOSED', + 'vin': 'WBA00000000DEMO02', + }), + 'context': , + 'entity_id': 'binary_sensor.i4_edrive40_windows', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_entity_state_attrs[binary_sensor.ix_xdrive50_charging_status-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.ix_xdrive50_charging_status', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Charging status', + 'platform': 'bmw_connected_drive', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'charging_status', + 'unique_id': 'WBA00000000DEMO01-charging_status', + 'unit_of_measurement': None, + }) +# --- +# name: test_entity_state_attrs[binary_sensor.ix_xdrive50_charging_status-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by MyBMW', + 'device_class': 'battery_charging', + 'friendly_name': 'iX xDrive50 Charging status', + }), + 'context': , + 'entity_id': 'binary_sensor.ix_xdrive50_charging_status', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'on', + }) +# --- +# name: test_entity_state_attrs[binary_sensor.ix_xdrive50_check_control_messages-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.ix_xdrive50_check_control_messages', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Check control messages', + 'platform': 'bmw_connected_drive', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'check_control_messages', + 'unique_id': 'WBA00000000DEMO01-check_control_messages', + 'unit_of_measurement': None, + }) +# --- +# name: test_entity_state_attrs[binary_sensor.ix_xdrive50_check_control_messages-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by MyBMW', + 'car': 'iX xDrive50', + 'device_class': 'problem', + 'friendly_name': 'iX xDrive50 Check control messages', + 'tire_pressure': 'LOW', + 'vin': 'WBA00000000DEMO01', + }), + 'context': , + 'entity_id': 'binary_sensor.ix_xdrive50_check_control_messages', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_entity_state_attrs[binary_sensor.ix_xdrive50_condition_based_services-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.ix_xdrive50_condition_based_services', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Condition based services', + 'platform': 'bmw_connected_drive', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'condition_based_services', + 'unique_id': 'WBA00000000DEMO01-condition_based_services', + 'unit_of_measurement': None, + }) +# --- +# name: test_entity_state_attrs[binary_sensor.ix_xdrive50_condition_based_services-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by MyBMW', + 'brake_fluid': 'OK', + 'brake_fluid_date': '2024-12-01', + 'brake_fluid_distance': '50000 km', + 'car': 'iX xDrive50', + 'device_class': 'problem', + 'friendly_name': 'iX xDrive50 Condition based services', + 'tire_wear_front': 'OK', + 'tire_wear_rear': 'OK', + 'vehicle_check': 'OK', + 'vehicle_check_date': '2024-12-01', + 'vehicle_check_distance': '50000 km', + 'vehicle_tuv': 'OK', + 'vehicle_tuv_date': '2024-12-01', + 'vehicle_tuv_distance': '50000 km', + 'vin': 'WBA00000000DEMO01', + }), + 'context': , + 'entity_id': 'binary_sensor.ix_xdrive50_condition_based_services', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_entity_state_attrs[binary_sensor.ix_xdrive50_connection_status-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.ix_xdrive50_connection_status', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Connection status', + 'platform': 'bmw_connected_drive', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'connection_status', + 'unique_id': 'WBA00000000DEMO01-connection_status', + 'unit_of_measurement': None, + }) +# --- +# name: test_entity_state_attrs[binary_sensor.ix_xdrive50_connection_status-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by MyBMW', + 'device_class': 'plug', + 'friendly_name': 'iX xDrive50 Connection status', + }), + 'context': , + 'entity_id': 'binary_sensor.ix_xdrive50_connection_status', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'on', + }) +# --- +# name: test_entity_state_attrs[binary_sensor.ix_xdrive50_door_lock_state-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.ix_xdrive50_door_lock_state', + '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 lock state', + 'platform': 'bmw_connected_drive', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'door_lock_state', + 'unique_id': 'WBA00000000DEMO01-door_lock_state', + 'unit_of_measurement': None, + }) +# --- +# name: test_entity_state_attrs[binary_sensor.ix_xdrive50_door_lock_state-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by MyBMW', + 'car': 'iX xDrive50', + 'device_class': 'lock', + 'door_lock_state': 'LOCKED', + 'friendly_name': 'iX xDrive50 Door lock state', + 'vin': 'WBA00000000DEMO01', + }), + 'context': , + 'entity_id': 'binary_sensor.ix_xdrive50_door_lock_state', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_entity_state_attrs[binary_sensor.ix_xdrive50_lids-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.ix_xdrive50_lids', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Lids', + 'platform': 'bmw_connected_drive', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'lids', + 'unique_id': 'WBA00000000DEMO01-lids', + 'unit_of_measurement': None, + }) +# --- +# name: test_entity_state_attrs[binary_sensor.ix_xdrive50_lids-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by MyBMW', + 'car': 'iX xDrive50', + 'device_class': 'opening', + 'friendly_name': 'iX xDrive50 Lids', + 'hood': 'CLOSED', + 'leftFront': 'CLOSED', + 'leftRear': 'CLOSED', + 'rightFront': 'CLOSED', + 'rightRear': 'CLOSED', + 'sunRoof': 'CLOSED', + 'trunk': 'CLOSED', + 'vin': 'WBA00000000DEMO01', + }), + 'context': , + 'entity_id': 'binary_sensor.ix_xdrive50_lids', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_entity_state_attrs[binary_sensor.ix_xdrive50_pre_entry_climatization-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.ix_xdrive50_pre_entry_climatization', + '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': 'Pre entry climatization', + 'platform': 'bmw_connected_drive', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'is_pre_entry_climatization_enabled', + 'unique_id': 'WBA00000000DEMO01-is_pre_entry_climatization_enabled', + 'unit_of_measurement': None, + }) +# --- +# name: test_entity_state_attrs[binary_sensor.ix_xdrive50_pre_entry_climatization-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by MyBMW', + 'friendly_name': 'iX xDrive50 Pre entry climatization', + }), + 'context': , + 'entity_id': 'binary_sensor.ix_xdrive50_pre_entry_climatization', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_entity_state_attrs[binary_sensor.ix_xdrive50_windows-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.ix_xdrive50_windows', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Windows', + 'platform': 'bmw_connected_drive', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'windows', + 'unique_id': 'WBA00000000DEMO01-windows', + 'unit_of_measurement': None, + }) +# --- +# name: test_entity_state_attrs[binary_sensor.ix_xdrive50_windows-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by MyBMW', + 'car': 'iX xDrive50', + 'device_class': 'opening', + 'friendly_name': 'iX xDrive50 Windows', + 'leftFront': 'CLOSED', + 'leftRear': 'CLOSED', + 'rear': 'CLOSED', + 'rightFront': 'CLOSED', + 'rightRear': 'CLOSED', + 'vin': 'WBA00000000DEMO01', + }), + 'context': , + 'entity_id': 'binary_sensor.ix_xdrive50_windows', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_entity_state_attrs[binary_sensor.m340i_xdrive_check_control_messages-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.m340i_xdrive_check_control_messages', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Check control messages', + 'platform': 'bmw_connected_drive', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'check_control_messages', + 'unique_id': 'WBA00000000DEMO03-check_control_messages', + 'unit_of_measurement': None, + }) +# --- +# name: test_entity_state_attrs[binary_sensor.m340i_xdrive_check_control_messages-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by MyBMW', + 'car': 'M340i xDrive', + 'device_class': 'problem', + 'engine_oil': 'LOW', + 'friendly_name': 'M340i xDrive Check control messages', + 'tire_pressure': 'LOW', + 'vin': 'WBA00000000DEMO03', + }), + 'context': , + 'entity_id': 'binary_sensor.m340i_xdrive_check_control_messages', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_entity_state_attrs[binary_sensor.m340i_xdrive_condition_based_services-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.m340i_xdrive_condition_based_services', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Condition based services', + 'platform': 'bmw_connected_drive', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'condition_based_services', + 'unique_id': 'WBA00000000DEMO03-condition_based_services', + 'unit_of_measurement': None, + }) +# --- +# name: test_entity_state_attrs[binary_sensor.m340i_xdrive_condition_based_services-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by MyBMW', + 'brake_fluid': 'OK', + 'brake_fluid_date': '2024-12-01', + 'brake_fluid_distance': '50000 km', + 'car': 'M340i xDrive', + 'device_class': 'problem', + 'friendly_name': 'M340i xDrive Condition based services', + 'oil': 'OK', + 'oil_date': '2024-12-01', + 'oil_distance': '50000 km', + 'tire_wear_front': 'OK', + 'tire_wear_rear': 'OK', + 'vehicle_check': 'OK', + 'vehicle_check_date': '2024-12-01', + 'vehicle_check_distance': '50000 km', + 'vehicle_tuv': 'OK', + 'vehicle_tuv_date': '2024-12-01', + 'vehicle_tuv_distance': '50000 km', + 'vin': 'WBA00000000DEMO03', + }), + 'context': , + 'entity_id': 'binary_sensor.m340i_xdrive_condition_based_services', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_entity_state_attrs[binary_sensor.m340i_xdrive_door_lock_state-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.m340i_xdrive_door_lock_state', + '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 lock state', + 'platform': 'bmw_connected_drive', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'door_lock_state', + 'unique_id': 'WBA00000000DEMO03-door_lock_state', + 'unit_of_measurement': None, + }) +# --- +# name: test_entity_state_attrs[binary_sensor.m340i_xdrive_door_lock_state-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by MyBMW', + 'car': 'M340i xDrive', + 'device_class': 'lock', + 'door_lock_state': 'LOCKED', + 'friendly_name': 'M340i xDrive Door lock state', + 'vin': 'WBA00000000DEMO03', + }), + 'context': , + 'entity_id': 'binary_sensor.m340i_xdrive_door_lock_state', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_entity_state_attrs[binary_sensor.m340i_xdrive_lids-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.m340i_xdrive_lids', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Lids', + 'platform': 'bmw_connected_drive', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'lids', + 'unique_id': 'WBA00000000DEMO03-lids', + 'unit_of_measurement': None, + }) +# --- +# name: test_entity_state_attrs[binary_sensor.m340i_xdrive_lids-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by MyBMW', + 'car': 'M340i xDrive', + 'device_class': 'opening', + 'friendly_name': 'M340i xDrive Lids', + 'hood': 'CLOSED', + 'leftFront': 'CLOSED', + 'leftRear': 'CLOSED', + 'rightFront': 'CLOSED', + 'rightRear': 'CLOSED', + 'trunk': 'CLOSED', + 'vin': 'WBA00000000DEMO03', + }), + 'context': , + 'entity_id': 'binary_sensor.m340i_xdrive_lids', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_entity_state_attrs[binary_sensor.m340i_xdrive_windows-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.m340i_xdrive_windows', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Windows', + 'platform': 'bmw_connected_drive', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'windows', + 'unique_id': 'WBA00000000DEMO03-windows', + 'unit_of_measurement': None, + }) +# --- +# name: test_entity_state_attrs[binary_sensor.m340i_xdrive_windows-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by MyBMW', + 'car': 'M340i xDrive', + 'device_class': 'opening', + 'friendly_name': 'M340i xDrive Windows', + 'leftFront': 'CLOSED', + 'leftRear': 'CLOSED', + 'rear': 'CLOSED', + 'rightFront': 'CLOSED', + 'rightRear': 'CLOSED', + 'vin': 'WBA00000000DEMO03', + }), + 'context': , + 'entity_id': 'binary_sensor.m340i_xdrive_windows', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- diff --git a/tests/components/bmw_connected_drive/snapshots/test_lock.ambr b/tests/components/bmw_connected_drive/snapshots/test_lock.ambr new file mode 100644 index 00000000000..17e6b118011 --- /dev/null +++ b/tests/components/bmw_connected_drive/snapshots/test_lock.ambr @@ -0,0 +1,205 @@ +# serializer version: 1 +# name: test_entity_state_attrs[lock.i3_rex_lock-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.i3_rex_lock', + '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': 'Lock', + 'platform': 'bmw_connected_drive', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'lock', + 'unique_id': 'WBY00000000REXI01-lock', + 'unit_of_measurement': None, + }) +# --- +# name: test_entity_state_attrs[lock.i3_rex_lock-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by MyBMW', + 'car': 'i3 (+ REX)', + 'door_lock_state': 'UNLOCKED', + 'friendly_name': 'i3 (+ REX) Lock', + 'supported_features': , + 'vin': 'WBY00000000REXI01', + }), + 'context': , + 'entity_id': 'lock.i3_rex_lock', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'unlocked', + }) +# --- +# name: test_entity_state_attrs[lock.i4_edrive40_lock-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.i4_edrive40_lock', + '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': 'Lock', + 'platform': 'bmw_connected_drive', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'lock', + 'unique_id': 'WBA00000000DEMO02-lock', + 'unit_of_measurement': None, + }) +# --- +# name: test_entity_state_attrs[lock.i4_edrive40_lock-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by MyBMW', + 'car': 'i4 eDrive40', + 'door_lock_state': 'LOCKED', + 'friendly_name': 'i4 eDrive40 Lock', + 'supported_features': , + 'vin': 'WBA00000000DEMO02', + }), + 'context': , + 'entity_id': 'lock.i4_edrive40_lock', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'locked', + }) +# --- +# name: test_entity_state_attrs[lock.ix_xdrive50_lock-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.ix_xdrive50_lock', + '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': 'Lock', + 'platform': 'bmw_connected_drive', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'lock', + 'unique_id': 'WBA00000000DEMO01-lock', + 'unit_of_measurement': None, + }) +# --- +# name: test_entity_state_attrs[lock.ix_xdrive50_lock-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by MyBMW', + 'car': 'iX xDrive50', + 'door_lock_state': 'LOCKED', + 'friendly_name': 'iX xDrive50 Lock', + 'supported_features': , + 'vin': 'WBA00000000DEMO01', + }), + 'context': , + 'entity_id': 'lock.ix_xdrive50_lock', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'locked', + }) +# --- +# name: test_entity_state_attrs[lock.m340i_xdrive_lock-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.m340i_xdrive_lock', + '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': 'Lock', + 'platform': 'bmw_connected_drive', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'lock', + 'unique_id': 'WBA00000000DEMO03-lock', + 'unit_of_measurement': None, + }) +# --- +# name: test_entity_state_attrs[lock.m340i_xdrive_lock-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by MyBMW', + 'car': 'M340i xDrive', + 'door_lock_state': 'LOCKED', + 'friendly_name': 'M340i xDrive Lock', + 'supported_features': , + 'vin': 'WBA00000000DEMO03', + }), + 'context': , + 'entity_id': 'lock.m340i_xdrive_lock', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'locked', + }) +# --- diff --git a/tests/components/bmw_connected_drive/test_binary_sensor.py b/tests/components/bmw_connected_drive/test_binary_sensor.py new file mode 100644 index 00000000000..a1b3d69bbbf --- /dev/null +++ b/tests/components/bmw_connected_drive/test_binary_sensor.py @@ -0,0 +1,35 @@ +"""Test BMW binary sensors.""" + +from unittest.mock import patch + +from freezegun import freeze_time +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 . import setup_mocked_integration + +from tests.common import snapshot_platform + + +@freeze_time("2023-06-22 10:30:00+00:00") +@pytest.mark.usefixtures("bmw_fixture") +@pytest.mark.usefixtures("entity_registry_enabled_by_default") +async def test_entity_state_attrs( + hass: HomeAssistant, + snapshot: SnapshotAssertion, + entity_registry: er.EntityRegistry, +) -> None: + """Test binary sensor states and attributes.""" + + # Setup component + with patch( + "homeassistant.components.bmw_connected_drive.PLATFORMS", + [Platform.BINARY_SENSOR], + ): + mock_config_entry = await setup_mocked_integration(hass) + + await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id) diff --git a/tests/components/bmw_connected_drive/test_lock.py b/tests/components/bmw_connected_drive/test_lock.py new file mode 100644 index 00000000000..2fa694d426b --- /dev/null +++ b/tests/components/bmw_connected_drive/test_lock.py @@ -0,0 +1,139 @@ +"""Test BMW locks.""" + +from unittest.mock import AsyncMock, patch + +from bimmer_connected.models import MyBMWRemoteServiceError +from bimmer_connected.vehicle.remote_services import RemoteServices +from freezegun import freeze_time +import pytest +import respx +from syrupy.assertion import SnapshotAssertion + +from homeassistant.components.recorder.history import get_significant_states +from homeassistant.const import STATE_UNKNOWN, Platform +from homeassistant.core import HomeAssistant +from homeassistant.exceptions import HomeAssistantError +from homeassistant.helpers import entity_registry as er +from homeassistant.util import dt as dt_util + +from . import check_remote_service_call, setup_mocked_integration + +from tests.common import snapshot_platform +from tests.components.recorder.common import async_wait_recording_done + + +@freeze_time("2023-06-22 10:30:00+00:00") +@pytest.mark.usefixtures("bmw_fixture") +@pytest.mark.usefixtures("entity_registry_enabled_by_default") +async def test_entity_state_attrs( + hass: HomeAssistant, + snapshot: SnapshotAssertion, + entity_registry: er.EntityRegistry, +) -> None: + """Test lock states and attributes.""" + + # Setup component + with patch( + "homeassistant.components.bmw_connected_drive.PLATFORMS", [Platform.LOCK] + ): + mock_config_entry = await setup_mocked_integration(hass) + + await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id) + + +@pytest.mark.usefixtures("recorder_mock") +@pytest.mark.parametrize( + ("entity_id", "new_value", "old_value", "service", "remote_service"), + [ + ( + "lock.m340i_xdrive_lock", + "locked", + "unlocked", + "lock", + "door-lock", + ), + ("lock.m340i_xdrive_lock", "unlocked", "locked", "unlock", "door-unlock"), + ], +) +async def test_service_call_success( + hass: HomeAssistant, + entity_id: str, + new_value: str, + old_value: str, + service: str, + remote_service: str, + bmw_fixture: respx.Router, +) -> None: + """Test successful service call.""" + + # Setup component + assert await setup_mocked_integration(hass) + hass.states.async_set(entity_id, old_value) + assert hass.states.get(entity_id).state == old_value + + now = dt_util.utcnow() + + # Test + await hass.services.async_call( + "lock", + service, + blocking=True, + target={"entity_id": entity_id}, + ) + check_remote_service_call(bmw_fixture, remote_service) + assert hass.states.get(entity_id).state == new_value + + # wait for the recorder to really store the data + await async_wait_recording_done(hass) + states = await hass.async_add_executor_job( + get_significant_states, hass, now, None, [entity_id] + ) + assert any(s for s in states[entity_id] if s.state == STATE_UNKNOWN) is False + + +@pytest.mark.usefixtures("bmw_fixture") +@pytest.mark.usefixtures("recorder_mock") +@pytest.mark.parametrize( + ("entity_id", "service"), + [ + ("lock.m340i_xdrive_lock", "lock"), + ("lock.m340i_xdrive_lock", "unlock"), + ], +) +async def test_service_call_fail( + hass: HomeAssistant, + entity_id: str, + service: str, + monkeypatch: pytest.MonkeyPatch, +) -> None: + """Test failed service call.""" + + # Setup component + assert await setup_mocked_integration(hass) + old_value = hass.states.get(entity_id).state + + now = dt_util.utcnow() + + # Setup exception + monkeypatch.setattr( + RemoteServices, + "trigger_remote_service", + AsyncMock(side_effect=MyBMWRemoteServiceError), + ) + + # Test + with pytest.raises(HomeAssistantError): + await hass.services.async_call( + "lock", + service, + blocking=True, + target={"entity_id": entity_id}, + ) + assert hass.states.get(entity_id).state == old_value + + # wait for the recorder to really store the data + await async_wait_recording_done(hass) + states = await hass.async_add_executor_job( + get_significant_states, hass, now, None, [entity_id] + ) + assert states[entity_id][-2].state == STATE_UNKNOWN