mirror of
https://github.com/home-assistant/core.git
synced 2026-04-02 08:26:41 +01:00
221 lines
6.2 KiB
Python
221 lines
6.2 KiB
Python
"""Tests for the SmartThings integration."""
|
|
|
|
from functools import cache
|
|
from typing import Any
|
|
from unittest.mock import AsyncMock
|
|
|
|
from pysmartthings import (
|
|
Attribute,
|
|
Capability,
|
|
DeviceEvent,
|
|
DeviceHealthEvent,
|
|
DeviceResponse,
|
|
DeviceStatus,
|
|
)
|
|
from pysmartthings.models import HealthStatus
|
|
from syrupy.assertion import SnapshotAssertion
|
|
|
|
from homeassistant.components.smartthings.const import DOMAIN, MAIN
|
|
from homeassistant.const import Platform
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.helpers import entity_registry as er
|
|
|
|
from tests.common import MockConfigEntry, load_fixture
|
|
|
|
DEVICE_FIXTURES = [
|
|
"aq_sensor_3_ikea",
|
|
"aeotec_ms6",
|
|
"da_ac_air_000001",
|
|
"da_ac_air_01011",
|
|
"da_ac_airsensor_01001",
|
|
"da_ac_rac_000001",
|
|
"da_ac_rac_000003",
|
|
"da_ac_rac_100001",
|
|
"da_ac_rac_01001",
|
|
"da_ac_cac_01001",
|
|
"multipurpose_sensor",
|
|
"contact_sensor",
|
|
"base_electric_meter",
|
|
"smart_plug",
|
|
"vd_stv_2017_k",
|
|
"c2c_arlo_pro_3_switch",
|
|
"yale_push_button_deadbolt_lock",
|
|
"ge_in_wall_smart_dimmer",
|
|
"centralite",
|
|
"da_ref_normal_000001",
|
|
"da_ref_normal_01011",
|
|
"da_ref_normal_01011_onedoor",
|
|
"da_ref_normal_01001",
|
|
"vd_network_audio_002s",
|
|
"vd_network_audio_003s",
|
|
"vd_sensor_light_2023",
|
|
"iphone",
|
|
"ikea_leak_battery",
|
|
"ikea_motion_illuminance_battery",
|
|
"ikea_plug_powermeter",
|
|
"aeotec_smart_home_hub",
|
|
"meross_plug",
|
|
"da_sac_ehs_000001_sub",
|
|
"da_sac_ehs_000001_sub_1",
|
|
"da_sac_ehs_000002_sub",
|
|
"da_ac_ehs_01001",
|
|
"da_wm_dw_000001",
|
|
"da_wm_wd_01011",
|
|
"da_wm_wd_000001",
|
|
"da_wm_wd_000001_1",
|
|
"da_wm_wm_01011",
|
|
"da_wm_wm_100001",
|
|
"da_wm_wm_100002",
|
|
"da_wm_wm_000001",
|
|
"da_wm_wm_000001_1",
|
|
"da_wm_mf_01001",
|
|
"da_wm_sc_000001",
|
|
"da_wm_dw_01011",
|
|
"da_rvc_normal_000001",
|
|
"da_rvc_map_01011",
|
|
"da_ks_microwave_0101x",
|
|
"da_ks_cooktop_000001",
|
|
"da_ks_cooktop_31001",
|
|
"da_ks_range_0101x",
|
|
"da_ks_oven_01061",
|
|
"da_ks_oven_0107x",
|
|
"da_ks_walloven_0107x",
|
|
"da_ks_hood_01001",
|
|
"hue_color_temperature_bulb",
|
|
"hue_rgbw_color_bulb",
|
|
"c2c_shade",
|
|
"sonos_player",
|
|
"aeotec_home_energy_meter_gen5",
|
|
"virtual_water_sensor",
|
|
"virtual_thermostat",
|
|
"virtual_valve",
|
|
"sensibo_airconditioner_1",
|
|
"ecobee_sensor",
|
|
"ecobee_thermostat",
|
|
"ecobee_thermostat_offline",
|
|
"sensi_thermostat",
|
|
"siemens_washer",
|
|
"fake_fan",
|
|
"generic_fan_3_speed",
|
|
"heatit_ztrm3_thermostat",
|
|
"heatit_zpushwall",
|
|
"generic_ef00_v1",
|
|
"gas_detector",
|
|
"bosch_radiator_thermostat_ii",
|
|
"im_speaker_ai_0001",
|
|
"im_smarttag2_ble_uwb",
|
|
"abl_light_b_001",
|
|
"tplink_p110",
|
|
"ikea_kadrilj",
|
|
"aux_ac",
|
|
"hw_q80r_soundbar",
|
|
"gas_meter",
|
|
"lumi",
|
|
"tesla_powerwall",
|
|
]
|
|
|
|
|
|
def get_device_status(device_name: str) -> DeviceStatus:
|
|
"""Load a DeviceStatus object from a fixture for the given device name."""
|
|
return DeviceStatus.from_json(
|
|
load_fixture(f"device_status/{device_name}.json", DOMAIN)
|
|
)
|
|
|
|
|
|
def get_device_response(device_name: str) -> DeviceResponse:
|
|
"""Load a DeviceResponse object from a fixture for the given device name."""
|
|
return DeviceResponse.from_json(load_fixture(f"devices/{device_name}.json", DOMAIN))
|
|
|
|
|
|
@cache
|
|
def get_fixture_name(device_id: str) -> str:
|
|
"""Get the fixture name for a given device ID."""
|
|
for fixture_name in DEVICE_FIXTURES:
|
|
for device in get_device_response(fixture_name).items:
|
|
if device.device_id == device_id:
|
|
return fixture_name
|
|
|
|
raise KeyError(f"Fixture for device_id {device_id} not found")
|
|
|
|
|
|
async def setup_integration(hass: HomeAssistant, config_entry: MockConfigEntry) -> None:
|
|
"""Fixture for setting up the component."""
|
|
config_entry.add_to_hass(hass)
|
|
|
|
await hass.config_entries.async_setup(config_entry.entry_id)
|
|
await hass.async_block_till_done()
|
|
|
|
|
|
def snapshot_smartthings_entities(
|
|
hass: HomeAssistant,
|
|
entity_registry: er.EntityRegistry,
|
|
snapshot: SnapshotAssertion,
|
|
platform: Platform,
|
|
) -> None:
|
|
"""Snapshot SmartThings entities."""
|
|
entities = hass.states.async_all(platform)
|
|
for entity_state in entities:
|
|
entity_entry = entity_registry.async_get(entity_state.entity_id)
|
|
prefix = ""
|
|
if platform != Platform.SCENE:
|
|
# SCENE unique id is not based on device fixture
|
|
device_id = entity_entry.unique_id[:36]
|
|
prefix = f"{get_fixture_name(device_id)}]["
|
|
assert entity_entry == snapshot(name=f"{prefix}{entity_entry.entity_id}-entry")
|
|
assert entity_state == snapshot(name=f"{prefix}{entity_entry.entity_id}-state")
|
|
|
|
|
|
def set_attribute_value(
|
|
mock: AsyncMock,
|
|
capability: Capability,
|
|
attribute: Attribute,
|
|
value: Any,
|
|
component: str = MAIN,
|
|
) -> None:
|
|
"""Set the value of an attribute."""
|
|
mock.get_device_status.return_value[component][capability][attribute].value = value
|
|
|
|
|
|
async def trigger_update(
|
|
hass: HomeAssistant,
|
|
mock: AsyncMock,
|
|
device_id: str,
|
|
capability: Capability,
|
|
attribute: Attribute,
|
|
value: str | float | dict[str, Any] | list[Any] | None,
|
|
data: dict[str, Any] | None = None,
|
|
component: str = MAIN,
|
|
) -> None:
|
|
"""Trigger an update."""
|
|
event = DeviceEvent(
|
|
"abc",
|
|
"abc",
|
|
"abc",
|
|
device_id,
|
|
component,
|
|
capability,
|
|
attribute,
|
|
value,
|
|
data,
|
|
)
|
|
for call in mock.add_unspecified_device_event_listener.call_args_list:
|
|
call[0][0](event)
|
|
for call in mock.add_device_event_listener.call_args_list:
|
|
if call[0][0] == device_id:
|
|
call[0][3](event)
|
|
for call in mock.add_device_capability_event_listener.call_args_list:
|
|
if call[0][0] == device_id and call[0][2] == capability:
|
|
call[0][3](event)
|
|
await hass.async_block_till_done()
|
|
|
|
|
|
async def trigger_health_update(
|
|
hass: HomeAssistant, mock: AsyncMock, device_id: str, status: HealthStatus
|
|
) -> None:
|
|
"""Trigger a health update."""
|
|
event = DeviceHealthEvent("abc", "abc", status)
|
|
for call in mock.add_device_availability_event_listener.call_args_list:
|
|
if call[0][0] == device_id:
|
|
call[0][1](event)
|
|
await hass.async_block_till_done()
|