Add tests for Tractive integration (#118470)

Co-authored-by: Maciej Bieniek <478555+bieniu@users.noreply.github.com>
This commit is contained in:
Maciej Bieniek 2024-05-30 12:45:11 +02:00 committed by GitHub
parent fc5d58effd
commit cf51179009
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 1686 additions and 18 deletions

View File

@ -1470,12 +1470,6 @@ omit =
homeassistant/components/traccar_server/entity.py homeassistant/components/traccar_server/entity.py
homeassistant/components/traccar_server/helpers.py homeassistant/components/traccar_server/helpers.py
homeassistant/components/traccar_server/sensor.py homeassistant/components/traccar_server/sensor.py
homeassistant/components/tractive/__init__.py
homeassistant/components/tractive/binary_sensor.py
homeassistant/components/tractive/device_tracker.py
homeassistant/components/tractive/entity.py
homeassistant/components/tractive/sensor.py
homeassistant/components/tractive/switch.py
homeassistant/components/tradfri/__init__.py homeassistant/components/tradfri/__init__.py
homeassistant/components/tradfri/base_class.py homeassistant/components/tradfri/base_class.py
homeassistant/components/tradfri/coordinator.py homeassistant/components/tradfri/coordinator.py

View File

@ -1 +1,18 @@
"""Tests for the tractive integration.""" """Tests for the tractive integration."""
from unittest.mock import patch
from homeassistant.core import HomeAssistant
from tests.common import MockConfigEntry
async def init_integration(
hass: HomeAssistant, entry: MockConfigEntry
) -> MockConfigEntry:
"""Set up the Tractive integration in Home Assistant."""
entry.add_to_hass(hass)
with patch("homeassistant.components.tractive.TractiveClient._listen"):
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()

View File

@ -1,14 +1,16 @@
"""Common fixtures for the Tractive tests.""" """Common fixtures for the Tractive tests."""
from collections.abc import Generator from collections.abc import Generator
from typing import Any
from unittest.mock import AsyncMock, Mock, patch from unittest.mock import AsyncMock, Mock, patch
from aiotractive.trackable_object import TrackableObject from aiotractive.trackable_object import TrackableObject
from aiotractive.tracker import Tracker from aiotractive.tracker import Tracker
import pytest import pytest
from homeassistant.components.tractive.const import DOMAIN from homeassistant.components.tractive.const import DOMAIN, SERVER_UNAVAILABLE
from homeassistant.const import CONF_EMAIL, CONF_PASSWORD from homeassistant.const import CONF_EMAIL, CONF_PASSWORD
from homeassistant.helpers.dispatcher import async_dispatcher_send
from tests.common import MockConfigEntry, load_json_object_fixture from tests.common import MockConfigEntry, load_json_object_fixture
@ -17,7 +19,72 @@ from tests.common import MockConfigEntry, load_json_object_fixture
def mock_tractive_client() -> Generator[AsyncMock, None, None]: def mock_tractive_client() -> Generator[AsyncMock, None, None]:
"""Mock a Tractive client.""" """Mock a Tractive client."""
trackable_object = load_json_object_fixture("tractive/trackable_object.json") def send_hardware_event(
entry: MockConfigEntry, event: dict[str, Any] | None = None
):
"""Send hardware event."""
if event is None:
event = {
"tracker_id": "device_id_123",
"hardware": {"battery_level": 88},
"tracker_state": "operational",
"charging_state": "CHARGING",
}
entry.runtime_data.client._send_hardware_update(event)
def send_wellness_event(
entry: MockConfigEntry, event: dict[str, Any] | None = None
):
"""Send wellness event."""
if event is None:
event = {
"pet_id": "pet_id_123",
"sleep": {"minutes_day_sleep": 100, "minutes_night_sleep": 300},
"wellness": {"activity_label": "ok", "sleep_label": "good"},
"activity": {
"calories": 999,
"minutes_goal": 200,
"minutes_active": 150,
"minutes_rest": 122,
},
}
entry.runtime_data.client._send_wellness_update(event)
def send_position_event(
entry: MockConfigEntry, event: dict[str, Any] | None = None
):
"""Send position event."""
if event is None:
event = {
"tracker_id": "device_id_123",
"position": {
"latlong": [22.333, 44.555],
"accuracy": 99,
"sensor_used": "GPS",
},
}
entry.runtime_data.client._send_position_update(event)
def send_switch_event(entry: MockConfigEntry, event: dict[str, Any] | None = None):
"""Send switch event."""
if event is None:
event = {
"tracker_id": "device_id_123",
"buzzer_control": {"active": True},
"led_control": {"active": False},
"live_tracking": {"active": True},
}
entry.runtime_data.client._send_switch_update(event)
def send_server_unavailable_event(hass):
"""Send server unavailable event."""
async_dispatcher_send(hass, f"{SERVER_UNAVAILABLE}-12345")
trackable_object = load_json_object_fixture("trackable_object.json", DOMAIN)
tracker_details = load_json_object_fixture("tracker_details.json", DOMAIN)
tracker_hw_info = load_json_object_fixture("tracker_hw_info.json", DOMAIN)
tracker_pos_report = load_json_object_fixture("tracker_pos_report.json", DOMAIN)
with ( with (
patch( patch(
"homeassistant.components.tractive.aiotractive.Tractive", autospec=True "homeassistant.components.tractive.aiotractive.Tractive", autospec=True
@ -33,7 +100,21 @@ def mock_tractive_client() -> Generator[AsyncMock, None, None]:
details=AsyncMock(return_value=trackable_object), details=AsyncMock(return_value=trackable_object),
), ),
] ]
client.tracker.return_value = Mock(spec=Tracker) client.tracker.return_value = AsyncMock(
spec=Tracker,
details=AsyncMock(return_value=tracker_details),
hw_info=AsyncMock(return_value=tracker_hw_info),
pos_report=AsyncMock(return_value=tracker_pos_report),
set_live_tracking_active=AsyncMock(return_value={"pending": True}),
set_buzzer_active=AsyncMock(return_value={"pending": True}),
set_led_active=AsyncMock(return_value={"pending": True}),
)
client.send_hardware_event = send_hardware_event
client.send_wellness_event = send_wellness_event
client.send_position_event = send_position_event
client.send_switch_event = send_switch_event
client.send_server_unavailable_event = send_server_unavailable_event
yield client yield client

View File

@ -1,7 +1,8 @@
{ {
"device_id": "54321", "device_id": "device_id_123",
"_id": "pet_id_123",
"details": { "details": {
"_id": "xyz123", "_id": "pet_id_123",
"_version": "123abc", "_version": "123abc",
"name": "Test Pet", "name": "Test Pet",
"pet_type": "DOG", "pet_type": "DOG",

View File

@ -0,0 +1,38 @@
{
"_id": "device_id_123",
"_version": "abcd-123-efgh-456",
"hw_id": "device_id_123",
"model_number": "TG4422",
"hw_edition": "BLUE-WHITE",
"bluetooth_mac": null,
"geofence_sensitivity": "HIGH",
"battery_save_mode": null,
"read_only": false,
"demo": false,
"self_test_available": false,
"capabilities": [
"LT",
"BUZZER",
"LT_BLE",
"LED_BLE",
"BUZZER_BLE",
"HW_REPORTS_BLE",
"WIFI_SCAN_REPORTS_BLE",
"LED",
"ACTIVITY_TRACKING",
"WIFI_ZONE",
"SLEEP_TRACKING"
],
"supported_geofence_types": ["CIRCLE", "RECTANGLE", "POLYGON"],
"fw_version": "123.456",
"state": "OPERATIONAL",
"state_reason": "POWER_SAVING",
"charging_state": "NOT_CHARGING",
"battery_state": "FULL",
"power_saving_zone_id": "abcdef12345",
"prioritized_zone_id": "098765",
"prioritized_zone_type": "POWER_SAVING",
"prioritized_zone_last_seen_at": 1716106551,
"prioritized_zone_entered_at": 1716105066,
"_type": "tracker"
}

View File

@ -0,0 +1,11 @@
{
"time": 1716105966,
"battery_level": 96,
"clip_mounted_state": null,
"_id": "device_id_123",
"_type": "device_hw_report",
"_version": "e87646946",
"report_id": "098123",
"power_saving_zone_id": "abcdef12345",
"hw_status": null
}

View File

@ -0,0 +1,16 @@
{
"time": 1716106551,
"time_rcvd": 1716106561,
"pos_status": null,
"latlong": [33.222222, 44.555555],
"speed": null,
"pos_uncertainty": 30,
"_id": "device_id_123",
"_type": "device_pos_report",
"_version": "b7422b930",
"altitude": 85,
"report_id": "098123",
"sensor_used": "KNOWN_WIFI",
"nearby_user_id": null,
"power_saving_zone_id": "abcdef12345"
}

View File

@ -0,0 +1,95 @@
# serializer version: 1
# name: test_binary_sensor[binary_sensor.test_pet_tracker_battery_charging-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.test_pet_tracker_battery_charging',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <BinarySensorDeviceClass.BATTERY_CHARGING: 'battery_charging'>,
'original_icon': None,
'original_name': 'Tracker battery charging',
'platform': 'tractive',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'tracker_battery_charging',
'unique_id': 'pet_id_123_battery_charging',
'unit_of_measurement': None,
})
# ---
# name: test_binary_sensor[binary_sensor.test_pet_tracker_battery_charging-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'battery_charging',
'friendly_name': 'Test Pet Tracker battery charging',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.test_pet_tracker_battery_charging',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_sensor[binary_sensor.test_pet_tracker_battery_charging-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.test_pet_tracker_battery_charging',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <BinarySensorDeviceClass.BATTERY_CHARGING: 'battery_charging'>,
'original_icon': None,
'original_name': 'Tracker battery charging',
'platform': 'tractive',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'tracker_battery_charging',
'unique_id': 'pet_id_123_battery_charging',
'unit_of_measurement': None,
})
# ---
# name: test_sensor[binary_sensor.test_pet_tracker_battery_charging-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'battery_charging',
'friendly_name': 'Test Pet Tracker battery charging',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.test_pet_tracker_battery_charging',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---

View File

@ -0,0 +1,103 @@
# serializer version: 1
# name: test_device_tracker[device_tracker.test_pet_tracker-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'device_tracker',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'device_tracker.test_pet_tracker',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Tracker',
'platform': 'tractive',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'tracker',
'unique_id': 'pet_id_123',
'unit_of_measurement': None,
})
# ---
# name: test_device_tracker[device_tracker.test_pet_tracker-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'battery_level': 88,
'friendly_name': 'Test Pet Tracker',
'gps_accuracy': 99,
'latitude': 22.333,
'longitude': 44.555,
'source_type': <SourceType.GPS: 'gps'>,
}),
'context': <ANY>,
'entity_id': 'device_tracker.test_pet_tracker',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'not_home',
})
# ---
# name: test_sensor[device_tracker.test_pet_tracker-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'device_tracker',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'device_tracker.test_pet_tracker',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Tracker',
'platform': 'tractive',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'tracker',
'unique_id': 'pet_id_123',
'unit_of_measurement': None,
})
# ---
# name: test_sensor[device_tracker.test_pet_tracker-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'battery_level': 88,
'friendly_name': 'Test Pet Tracker',
'gps_accuracy': 99,
'latitude': 22.333,
'longitude': 44.555,
'source_type': <SourceType.GPS: 'gps'>,
}),
'context': <ANY>,
'entity_id': 'device_tracker.test_pet_tracker',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'not_home',
})
# ---

View File

@ -21,6 +21,7 @@
}), }),
'trackables': list([ 'trackables': list([
dict({ dict({
'_id': '**REDACTED**',
'details': dict({ 'details': dict({
'_id': '**REDACTED**', '_id': '**REDACTED**',
'_type': 'pet_detail', '_type': 'pet_detail',
@ -64,7 +65,7 @@
'weight': 23700, 'weight': 23700,
'weight_is_default': None, 'weight_is_default': None,
}), }),
'device_id': '54321', 'device_id': 'device_id_123',
}), }),
]), ]),
}) })

View File

@ -0,0 +1,524 @@
# serializer version: 1
# name: test_sensor[sensor.test_pet_activity-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'options': list([
'good',
'low',
'ok',
]),
}),
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.test_pet_activity',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <SensorDeviceClass.ENUM: 'enum'>,
'original_icon': None,
'original_name': 'Activity',
'platform': 'tractive',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'activity',
'unique_id': 'pet_id_123_activity_label',
'unit_of_measurement': None,
})
# ---
# name: test_sensor[sensor.test_pet_activity-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'enum',
'friendly_name': 'Test Pet Activity',
'options': list([
'good',
'low',
'ok',
]),
}),
'context': <ANY>,
'entity_id': 'sensor.test_pet_activity',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'ok',
})
# ---
# name: test_sensor[sensor.test_pet_activity_time-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.TOTAL: 'total'>,
}),
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.test_pet_activity_time',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Activity time',
'platform': 'tractive',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'activity_time',
'unique_id': 'pet_id_123_minutes_active',
'unit_of_measurement': <UnitOfTime.MINUTES: 'min'>,
})
# ---
# name: test_sensor[sensor.test_pet_activity_time-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Test Pet Activity time',
'state_class': <SensorStateClass.TOTAL: 'total'>,
'unit_of_measurement': <UnitOfTime.MINUTES: 'min'>,
}),
'context': <ANY>,
'entity_id': 'sensor.test_pet_activity_time',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '150',
})
# ---
# name: test_sensor[sensor.test_pet_calories_burned-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.TOTAL: 'total'>,
}),
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.test_pet_calories_burned',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Calories burned',
'platform': 'tractive',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'calories',
'unique_id': 'pet_id_123_calories',
'unit_of_measurement': 'kcal',
})
# ---
# name: test_sensor[sensor.test_pet_calories_burned-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Test Pet Calories burned',
'state_class': <SensorStateClass.TOTAL: 'total'>,
'unit_of_measurement': 'kcal',
}),
'context': <ANY>,
'entity_id': 'sensor.test_pet_calories_burned',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '999',
})
# ---
# name: test_sensor[sensor.test_pet_daily_goal-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.test_pet_daily_goal',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Daily goal',
'platform': 'tractive',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'daily_goal',
'unique_id': 'pet_id_123_daily_goal',
'unit_of_measurement': <UnitOfTime.MINUTES: 'min'>,
})
# ---
# name: test_sensor[sensor.test_pet_daily_goal-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Test Pet Daily goal',
'unit_of_measurement': <UnitOfTime.MINUTES: 'min'>,
}),
'context': <ANY>,
'entity_id': 'sensor.test_pet_daily_goal',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '200',
})
# ---
# name: test_sensor[sensor.test_pet_day_sleep-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.TOTAL: 'total'>,
}),
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.test_pet_day_sleep',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Day sleep',
'platform': 'tractive',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'minutes_day_sleep',
'unique_id': 'pet_id_123_minutes_day_sleep',
'unit_of_measurement': <UnitOfTime.MINUTES: 'min'>,
})
# ---
# name: test_sensor[sensor.test_pet_day_sleep-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Test Pet Day sleep',
'state_class': <SensorStateClass.TOTAL: 'total'>,
'unit_of_measurement': <UnitOfTime.MINUTES: 'min'>,
}),
'context': <ANY>,
'entity_id': 'sensor.test_pet_day_sleep',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '100',
})
# ---
# name: test_sensor[sensor.test_pet_night_sleep-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.TOTAL: 'total'>,
}),
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.test_pet_night_sleep',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Night sleep',
'platform': 'tractive',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'minutes_night_sleep',
'unique_id': 'pet_id_123_minutes_night_sleep',
'unit_of_measurement': <UnitOfTime.MINUTES: 'min'>,
})
# ---
# name: test_sensor[sensor.test_pet_night_sleep-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Test Pet Night sleep',
'state_class': <SensorStateClass.TOTAL: 'total'>,
'unit_of_measurement': <UnitOfTime.MINUTES: 'min'>,
}),
'context': <ANY>,
'entity_id': 'sensor.test_pet_night_sleep',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '300',
})
# ---
# name: test_sensor[sensor.test_pet_rest_time-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.TOTAL: 'total'>,
}),
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.test_pet_rest_time',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Rest time',
'platform': 'tractive',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'rest_time',
'unique_id': 'pet_id_123_minutes_rest',
'unit_of_measurement': <UnitOfTime.MINUTES: 'min'>,
})
# ---
# name: test_sensor[sensor.test_pet_rest_time-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Test Pet Rest time',
'state_class': <SensorStateClass.TOTAL: 'total'>,
'unit_of_measurement': <UnitOfTime.MINUTES: 'min'>,
}),
'context': <ANY>,
'entity_id': 'sensor.test_pet_rest_time',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '122',
})
# ---
# name: test_sensor[sensor.test_pet_sleep-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'options': list([
'good',
'low',
'ok',
]),
}),
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.test_pet_sleep',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <SensorDeviceClass.ENUM: 'enum'>,
'original_icon': None,
'original_name': 'Sleep',
'platform': 'tractive',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'sleep',
'unique_id': 'pet_id_123_sleep_label',
'unit_of_measurement': None,
})
# ---
# name: test_sensor[sensor.test_pet_sleep-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'enum',
'friendly_name': 'Test Pet Sleep',
'options': list([
'good',
'low',
'ok',
]),
}),
'context': <ANY>,
'entity_id': 'sensor.test_pet_sleep',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'good',
})
# ---
# name: test_sensor[sensor.test_pet_tracker_battery-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.test_pet_tracker_battery',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <SensorDeviceClass.BATTERY: 'battery'>,
'original_icon': None,
'original_name': 'Tracker battery',
'platform': 'tractive',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'tracker_battery_level',
'unique_id': 'pet_id_123_battery_level',
'unit_of_measurement': '%',
})
# ---
# name: test_sensor[sensor.test_pet_tracker_battery-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'battery',
'friendly_name': 'Test Pet Tracker battery',
'unit_of_measurement': '%',
}),
'context': <ANY>,
'entity_id': 'sensor.test_pet_tracker_battery',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '88',
})
# ---
# name: test_sensor[sensor.test_pet_tracker_state-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'options': list([
'inaccurate_position',
'not_reporting',
'operational',
'system_shutdown_user',
'system_startup',
]),
}),
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.test_pet_tracker_state',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <SensorDeviceClass.ENUM: 'enum'>,
'original_icon': None,
'original_name': 'Tracker state',
'platform': 'tractive',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'tracker_state',
'unique_id': 'pet_id_123_tracker_state',
'unit_of_measurement': None,
})
# ---
# name: test_sensor[sensor.test_pet_tracker_state-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'enum',
'friendly_name': 'Test Pet Tracker state',
'options': list([
'inaccurate_position',
'not_reporting',
'operational',
'system_shutdown_user',
'system_startup',
]),
}),
'context': <ANY>,
'entity_id': 'sensor.test_pet_tracker_state',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'operational',
})
# ---

View File

@ -0,0 +1,277 @@
# serializer version: 1
# name: test_sensor[switch.test_pet_live_tracking-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'switch',
'entity_category': <EntityCategory.CONFIG: 'config'>,
'entity_id': 'switch.test_pet_live_tracking',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Live tracking',
'platform': 'tractive',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'live_tracking',
'unique_id': 'pet_id_123_live_tracking',
'unit_of_measurement': None,
})
# ---
# name: test_sensor[switch.test_pet_live_tracking-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Test Pet Live tracking',
}),
'context': <ANY>,
'entity_id': 'switch.test_pet_live_tracking',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_sensor[switch.test_pet_tracker_buzzer-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'switch',
'entity_category': <EntityCategory.CONFIG: 'config'>,
'entity_id': 'switch.test_pet_tracker_buzzer',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Tracker buzzer',
'platform': 'tractive',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'tracker_buzzer',
'unique_id': 'pet_id_123_buzzer',
'unit_of_measurement': None,
})
# ---
# name: test_sensor[switch.test_pet_tracker_buzzer-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Test Pet Tracker buzzer',
}),
'context': <ANY>,
'entity_id': 'switch.test_pet_tracker_buzzer',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_sensor[switch.test_pet_tracker_led-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'switch',
'entity_category': <EntityCategory.CONFIG: 'config'>,
'entity_id': 'switch.test_pet_tracker_led',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Tracker LED',
'platform': 'tractive',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'tracker_led',
'unique_id': 'pet_id_123_led',
'unit_of_measurement': None,
})
# ---
# name: test_sensor[switch.test_pet_tracker_led-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Test Pet Tracker LED',
}),
'context': <ANY>,
'entity_id': 'switch.test_pet_tracker_led',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_switch[switch.test_pet_live_tracking-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'switch',
'entity_category': <EntityCategory.CONFIG: 'config'>,
'entity_id': 'switch.test_pet_live_tracking',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Live tracking',
'platform': 'tractive',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'live_tracking',
'unique_id': 'pet_id_123_live_tracking',
'unit_of_measurement': None,
})
# ---
# name: test_switch[switch.test_pet_live_tracking-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Test Pet Live tracking',
}),
'context': <ANY>,
'entity_id': 'switch.test_pet_live_tracking',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_switch[switch.test_pet_tracker_buzzer-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'switch',
'entity_category': <EntityCategory.CONFIG: 'config'>,
'entity_id': 'switch.test_pet_tracker_buzzer',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Tracker buzzer',
'platform': 'tractive',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'tracker_buzzer',
'unique_id': 'pet_id_123_buzzer',
'unit_of_measurement': None,
})
# ---
# name: test_switch[switch.test_pet_tracker_buzzer-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Test Pet Tracker buzzer',
}),
'context': <ANY>,
'entity_id': 'switch.test_pet_tracker_buzzer',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_switch[switch.test_pet_tracker_led-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'switch',
'entity_category': <EntityCategory.CONFIG: 'config'>,
'entity_id': 'switch.test_pet_tracker_led',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Tracker LED',
'platform': 'tractive',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'tracker_led',
'unique_id': 'pet_id_123_led',
'unit_of_measurement': None,
})
# ---
# name: test_switch[switch.test_pet_tracker_led-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Test Pet Tracker LED',
}),
'context': <ANY>,
'entity_id': 'switch.test_pet_tracker_led',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---

View File

@ -0,0 +1,29 @@
"""Test the Tractive binary sensor platform."""
from unittest.mock import AsyncMock, patch
from syrupy import SnapshotAssertion
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from . import init_integration
from tests.common import MockConfigEntry, snapshot_platform
async def test_binary_sensor(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
snapshot: SnapshotAssertion,
mock_tractive_client: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test states of the binary sensor."""
with patch("homeassistant.components.tractive.PLATFORMS", [Platform.BINARY_SENSOR]):
await init_integration(hass, mock_config_entry)
mock_tractive_client.send_hardware_event(mock_config_entry)
await hass.async_block_till_done()
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)

View File

@ -0,0 +1,61 @@
"""Test the Tractive device tracker platform."""
from unittest.mock import AsyncMock, patch
from syrupy import SnapshotAssertion
from homeassistant.components.device_tracker import SourceType
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from . import init_integration
from tests.common import MockConfigEntry, snapshot_platform
async def test_device_tracker(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
snapshot: SnapshotAssertion,
mock_tractive_client: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test states of the device_tracker."""
with patch(
"homeassistant.components.tractive.PLATFORMS", [Platform.DEVICE_TRACKER]
):
await init_integration(hass, mock_config_entry)
mock_tractive_client.send_position_event(mock_config_entry)
mock_tractive_client.send_hardware_event(mock_config_entry)
await hass.async_block_till_done()
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
async def test_source_type_phone(
hass: HomeAssistant,
mock_tractive_client: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test the device tracker with source type phone."""
await init_integration(hass, mock_config_entry)
mock_tractive_client.send_position_event(
mock_config_entry,
{
"tracker_id": "device_id_123",
"position": {
"latlong": [22.333, 44.555],
"accuracy": 99,
"sensor_used": "PHONE",
},
},
)
mock_tractive_client.send_hardware_event(mock_config_entry)
await hass.async_block_till_done()
assert (
hass.states.get("device_tracker.test_pet_tracker").attributes["source_type"]
is SourceType.BLUETOOTH
)

View File

@ -1,12 +1,12 @@
"""Test the Tractive diagnostics.""" """Test the Tractive diagnostics."""
from unittest.mock import AsyncMock, patch from unittest.mock import AsyncMock
from syrupy import SnapshotAssertion from syrupy import SnapshotAssertion
from homeassistant.components.tractive.const import DOMAIN
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
from . import init_integration
from tests.common import MockConfigEntry from tests.common import MockConfigEntry
from tests.components.diagnostics import get_diagnostics_for_config_entry from tests.components.diagnostics import get_diagnostics_for_config_entry
@ -21,9 +21,8 @@ async def test_entry_diagnostics(
mock_config_entry: MockConfigEntry, mock_config_entry: MockConfigEntry,
) -> None: ) -> None:
"""Test config entry diagnostics.""" """Test config entry diagnostics."""
mock_config_entry.add_to_hass(hass) await init_integration(hass, mock_config_entry)
with patch("homeassistant.components.tractive.PLATFORMS", []):
assert await async_setup_component(hass, DOMAIN, {})
result = await get_diagnostics_for_config_entry( result = await get_diagnostics_for_config_entry(
hass, hass_client, mock_config_entry hass, hass_client, mock_config_entry
) )

View File

@ -0,0 +1,163 @@
"""Test init of Tractive integration."""
from unittest.mock import AsyncMock, patch
from aiotractive.exceptions import TractiveError, UnauthorizedError
import pytest
from homeassistant.components.tractive.const import DOMAIN
from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import EVENT_HOMEASSISTANT_STOP, STATE_UNAVAILABLE
from homeassistant.core import HomeAssistant
from . import init_integration
from tests.common import MockConfigEntry
async def test_setup_entry(
hass: HomeAssistant,
mock_tractive_client: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test a successful setup entry."""
await init_integration(hass, mock_config_entry)
assert mock_config_entry.state is ConfigEntryState.LOADED
async def test_unload_entry(
hass: HomeAssistant,
mock_tractive_client: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test successful unload of entry."""
await init_integration(hass, mock_config_entry)
assert len(hass.config_entries.async_entries(DOMAIN)) == 1
assert mock_config_entry.state is ConfigEntryState.LOADED
with patch("homeassistant.components.tractive.TractiveClient.unsubscribe"):
assert await hass.config_entries.async_unload(mock_config_entry.entry_id)
await hass.async_block_till_done()
assert mock_config_entry.state is ConfigEntryState.NOT_LOADED
assert not hass.data.get(DOMAIN)
@pytest.mark.parametrize(
("method", "exc", "entry_state"),
[
("authenticate", UnauthorizedError, ConfigEntryState.SETUP_ERROR),
("authenticate", TractiveError, ConfigEntryState.SETUP_RETRY),
("trackable_objects", TractiveError, ConfigEntryState.SETUP_RETRY),
],
)
async def test_setup_failed(
hass: HomeAssistant,
mock_tractive_client: AsyncMock,
mock_config_entry: MockConfigEntry,
method: str,
exc: Exception,
entry_state: ConfigEntryState,
) -> None:
"""Test for setup failure."""
getattr(mock_tractive_client, method).side_effect = exc
await init_integration(hass, mock_config_entry)
assert mock_config_entry.state is entry_state
async def test_config_not_ready(
hass: HomeAssistant,
mock_tractive_client: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test for setup failure if the tracker_details doesn't contain '_id'."""
mock_tractive_client.tracker.return_value.details.return_value.pop("_id")
await init_integration(hass, mock_config_entry)
assert mock_config_entry.state is ConfigEntryState.SETUP_RETRY
async def test_trackable_without_details(
hass: HomeAssistant,
mock_tractive_client: AsyncMock,
mock_config_entry: MockConfigEntry,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test a successful setup entry."""
mock_tractive_client.trackable_objects.return_value[0].details.return_value = {
"device_id": "xyz098"
}
await init_integration(hass, mock_config_entry)
assert (
"Tracker xyz098 has no details and will be skipped. This happens for shared trackers"
in caplog.text
)
assert mock_config_entry.state is ConfigEntryState.LOADED
async def test_trackable_without_device_id(
hass: HomeAssistant,
mock_tractive_client: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test a successful setup entry."""
mock_tractive_client.trackable_objects.return_value[0].details.return_value = {
"device_id": None
}
await init_integration(hass, mock_config_entry)
assert mock_config_entry.state is ConfigEntryState.LOADED
async def test_unsubscribe_on_ha_stop(
hass: HomeAssistant,
mock_tractive_client: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test unsuscribe when HA stops."""
await init_integration(hass, mock_config_entry)
with patch(
"homeassistant.components.tractive.TractiveClient.unsubscribe"
) as mock_unsuscribe:
hass.bus.async_fire(EVENT_HOMEASSISTANT_STOP)
await hass.async_block_till_done()
assert mock_unsuscribe.called
async def test_server_unavailable(
hass: HomeAssistant,
mock_tractive_client: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test states of the sensor."""
entity_id = "sensor.test_pet_tracker_battery"
await init_integration(hass, mock_config_entry)
# send event to make the entity available
mock_tractive_client.send_hardware_event(mock_config_entry)
await hass.async_block_till_done()
assert hass.states.get(entity_id).state != STATE_UNAVAILABLE
# send server unavailable event, the entity should be unavailable
mock_tractive_client.send_server_unavailable_event(hass)
await hass.async_block_till_done()
assert hass.states.get(entity_id).state == STATE_UNAVAILABLE
# send event to make the entity available once again
mock_tractive_client.send_hardware_event(mock_config_entry)
await hass.async_block_till_done()
assert hass.states.get(entity_id).state != STATE_UNAVAILABLE

View File

@ -0,0 +1,30 @@
"""Test the Tractive sensor platform."""
from unittest.mock import AsyncMock, patch
from syrupy import SnapshotAssertion
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from . import init_integration
from tests.common import MockConfigEntry, snapshot_platform
async def test_sensor(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
snapshot: SnapshotAssertion,
mock_tractive_client: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test states of the sensor."""
with patch("homeassistant.components.tractive.PLATFORMS", [Platform.SENSOR]):
await init_integration(hass, mock_config_entry)
mock_tractive_client.send_hardware_event(mock_config_entry)
mock_tractive_client.send_wellness_event(mock_config_entry)
await hass.async_block_till_done()
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)

View File

@ -0,0 +1,228 @@
"""Test the Tractive switch platform."""
from unittest.mock import AsyncMock, patch
from aiotractive.exceptions import TractiveError
from syrupy import SnapshotAssertion
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
from homeassistant.const import (
ATTR_ENTITY_ID,
SERVICE_TURN_OFF,
SERVICE_TURN_ON,
STATE_OFF,
STATE_ON,
Platform,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from . import init_integration
from tests.common import MockConfigEntry, snapshot_platform
async def test_switch(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
snapshot: SnapshotAssertion,
mock_tractive_client: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test states of the switch."""
with patch("homeassistant.components.tractive.PLATFORMS", [Platform.SWITCH]):
await init_integration(hass, mock_config_entry)
mock_tractive_client.send_switch_event(mock_config_entry)
await hass.async_block_till_done()
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
async def test_switch_on(
hass: HomeAssistant,
mock_tractive_client: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test the switch can be turned on."""
entity_id = "switch.test_pet_tracker_led"
await init_integration(hass, mock_config_entry)
mock_tractive_client.send_switch_event(mock_config_entry)
await hass.async_block_till_done()
state = hass.states.get(entity_id)
assert state
assert state.state == STATE_OFF
await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: entity_id},
blocking=True,
)
mock_tractive_client.send_switch_event(
mock_config_entry,
{"tracker_id": "device_id_123", "led_control": {"active": True}},
)
await hass.async_block_till_done()
assert mock_tractive_client.tracker.return_value.set_led_active.call_count == 1
assert (
mock_tractive_client.tracker.return_value.set_led_active.call_args[0][0] is True
)
state = hass.states.get(entity_id)
assert state
assert state.state == STATE_ON
async def test_switch_off(
hass: HomeAssistant,
mock_tractive_client: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test the switch can be turned off."""
entity_id = "switch.test_pet_tracker_buzzer"
await init_integration(hass, mock_config_entry)
mock_tractive_client.send_switch_event(mock_config_entry)
await hass.async_block_till_done()
state = hass.states.get(entity_id)
assert state
assert state.state == STATE_ON
await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: entity_id},
blocking=True,
)
mock_tractive_client.send_switch_event(
mock_config_entry,
{"tracker_id": "device_id_123", "buzzer_control": {"active": False}},
)
await hass.async_block_till_done()
assert mock_tractive_client.tracker.return_value.set_buzzer_active.call_count == 1
assert (
mock_tractive_client.tracker.return_value.set_buzzer_active.call_args[0][0]
is False
)
state = hass.states.get(entity_id)
assert state
assert state.state == STATE_OFF
async def test_live_tracking_switch(
hass: HomeAssistant,
mock_tractive_client: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test the live_tracking switch."""
entity_id = "switch.test_pet_live_tracking"
await init_integration(hass, mock_config_entry)
mock_tractive_client.send_switch_event(mock_config_entry)
await hass.async_block_till_done()
state = hass.states.get(entity_id)
assert state
assert state.state == STATE_ON
await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: entity_id},
blocking=True,
)
mock_tractive_client.send_switch_event(
mock_config_entry,
{"tracker_id": "device_id_123", "live_tracking": {"active": False}},
)
await hass.async_block_till_done()
assert (
mock_tractive_client.tracker.return_value.set_live_tracking_active.call_count
== 1
)
assert (
mock_tractive_client.tracker.return_value.set_live_tracking_active.call_args[0][
0
]
is False
)
state = hass.states.get(entity_id)
assert state
assert state.state == STATE_OFF
async def test_switch_on_with_exception(
hass: HomeAssistant,
mock_tractive_client: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test the switch turn on with exception."""
entity_id = "switch.test_pet_tracker_led"
await init_integration(hass, mock_config_entry)
mock_tractive_client.send_switch_event(mock_config_entry)
await hass.async_block_till_done()
state = hass.states.get(entity_id)
assert state
assert state.state == STATE_OFF
mock_tractive_client.tracker.return_value.set_led_active.side_effect = TractiveError
await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: entity_id},
blocking=True,
)
await hass.async_block_till_done()
state = hass.states.get(entity_id)
assert state
assert state.state == STATE_OFF
async def test_switch_off_with_exception(
hass: HomeAssistant,
mock_tractive_client: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test the switch turn off with exception."""
entity_id = "switch.test_pet_tracker_buzzer"
await init_integration(hass, mock_config_entry)
mock_tractive_client.send_switch_event(mock_config_entry)
await hass.async_block_till_done()
state = hass.states.get(entity_id)
assert state
assert state.state == STATE_ON
mock_tractive_client.tracker.return_value.set_buzzer_active.side_effect = (
TractiveError
)
await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: entity_id},
blocking=True,
)
await hass.async_block_till_done()
state = hass.states.get(entity_id)
assert state
assert state.state == STATE_ON