diff --git a/homeassistant/components/homekit_controller/connection.py b/homeassistant/components/homekit_controller/connection.py index 112c05b17f5..4b1a70bb60b 100644 --- a/homeassistant/components/homekit_controller/connection.py +++ b/homeassistant/components/homekit_controller/connection.py @@ -214,7 +214,11 @@ class HKDevice: devices = {} - for accessory in self.entity_map.accessories: + # Accessories need to be created in the correct order or setting up + # relationships with ATTR_VIA_DEVICE may fail. + for accessory in sorted( + self.entity_map.accessories, key=lambda accessory: accessory.aid + ): info = accessory.services.first( service_type=ServicesTypes.ACCESSORY_INFORMATION, ) diff --git a/tests/components/homekit_controller/common.py b/tests/components/homekit_controller/common.py index ce17311c513..68791e89af2 100644 --- a/tests/components/homekit_controller/common.py +++ b/tests/components/homekit_controller/common.py @@ -6,6 +6,7 @@ from datetime import timedelta import json import logging import os +from typing import Any from unittest import mock from aiohomekit.model import Accessories, Accessory @@ -14,6 +15,7 @@ from aiohomekit.model.services import ServicesTypes from aiohomekit.testing import FakeController from homeassistant.components import zeroconf +from homeassistant.components.device_automation import DeviceAutomationType from homeassistant.components.homekit_controller import config_flow from homeassistant.components.homekit_controller.const import ( CONTROLLER, @@ -24,10 +26,16 @@ from homeassistant.components.homekit_controller.const import ( ) from homeassistant.core import HomeAssistant from homeassistant.helpers import device_registry as dr, entity_registry as er +from homeassistant.helpers.entity import EntityCategory from homeassistant.setup import async_setup_component import homeassistant.util.dt as dt_util -from tests.common import MockConfigEntry, async_fire_time_changed, load_fixture +from tests.common import ( + MockConfigEntry, + async_fire_time_changed, + async_get_device_automations, + load_fixture, +) logger = logging.getLogger(__name__) @@ -41,23 +49,43 @@ class EntityTestInfo: friendly_name: str state: str supported_features: int = 0 + capabilities: dict[str, Any] | None = None + entity_category: EntityCategory | None = None + unit_of_measurement: str | None = None + + +@dataclass +class DeviceTriggerInfo: + """ + Describe a automation trigger we expect to be created. + + We only use these for a stateless characteristic like a doorbell. + """ + + type: str + subtype: str @dataclass class DeviceTestInfo: """Describes how we exepced a device to be created by homekit_controlller.""" - unique_id: str name: str manufacturer: str model: str sw_version: str hw_version: str - serial_number: str devices: list[DeviceTestInfo] entities: list[EntityTestInfo] + # At least one of these must be provided + unique_id: str | None = None + serial_number: str | None = None + + # A homekit device can have events but no entity (like a doorbell or remote) + stateless_triggers: list[DeviceTriggerInfo] | None = None + class Helper: """Helper methods for interacting with HomeKit fakes.""" @@ -210,12 +238,14 @@ async def setup_test_component(hass, setup_accessory, capitalize=False, suffix=N return Helper(hass, ".".join((domain, entity)), pairing, accessory, config_entry) -def assert_devices_and_entities_created(hass: HomeAssistant, expected: DeviceTestInfo): +async def assert_devices_and_entities_created( + hass: HomeAssistant, expected: DeviceTestInfo +): """Check that all expected devices and entities are loaded and enumerated as expected.""" entity_registry = er.async_get(hass) device_registry = dr.async_get(hass) - def _do_assertions(expected: DeviceTestInfo) -> dr.DeviceEntry: + async def _do_assertions(expected: DeviceTestInfo) -> dr.DeviceEntry: # Note: homekit_controller currently uses a 3-tuple for device identifiers # The current standard is a 2-tuple (hkc was not migrated when this change was brought in) @@ -245,11 +275,21 @@ def assert_devices_and_entities_created(hass: HomeAssistant, expected: DeviceTes # We might have matched the device by one identifier only # Lets check that the other one is correct. Otherwise the test might silently be wrong. + serial_number_set = False + accessory_id_set = False + for _, key, value in device.identifiers: if key == IDENTIFIER_SERIAL_NUMBER: assert value == expected.serial_number + serial_number_set = True + elif key == IDENTIFIER_ACCESSORY_ID: assert value == expected.unique_id + accessory_id_set = True + + # If unique_id or serial is provided it MUST actually appear in the device registry entry. + assert (not expected.unique_id) ^ accessory_id_set + assert (not expected.serial_number) ^ serial_number_set for entity_info in expected.entities: entity = entity_registry.async_get(entity_info.entity_id) @@ -259,6 +299,9 @@ def assert_devices_and_entities_created(hass: HomeAssistant, expected: DeviceTes assert entity.device_id == device.id assert entity.unique_id == entity_info.unique_id assert entity.supported_features == entity_info.supported_features + assert entity.entity_category == entity_info.entity_category + assert entity.unit_of_measurement == entity_info.unit_of_measurement + assert entity.capabilities == entity_info.capabilities state = hass.states.get(entity_info.entity_id) logger.debug("Comparing state %r to %r", state, entity_info) @@ -267,14 +310,28 @@ def assert_devices_and_entities_created(hass: HomeAssistant, expected: DeviceTes assert state.state == entity_info.state assert state.attributes["friendly_name"] == entity_info.friendly_name + all_triggers = await async_get_device_automations( + hass, DeviceAutomationType.TRIGGER, device.id + ) + stateless_triggers = [] + for trigger in all_triggers: + if trigger.get("entity_id"): + continue + stateless_triggers.append( + DeviceTriggerInfo( + type=trigger.get("type"), subtype=trigger.get("subtype") + ) + ) + assert stateless_triggers == (expected.stateless_triggers or []) + for child in expected.devices: - child_device = _do_assertions(child) + child_device = await _do_assertions(child) assert child_device.via_device_id == device.id assert child_device.id != device.id return device - root_device = _do_assertions(expected) + root_device = await _do_assertions(expected) # Root device must not have a via, otherwise its not the device assert root_device.via_device_id is None diff --git a/tests/components/homekit_controller/conftest.py b/tests/components/homekit_controller/conftest.py index 174fc4f7b8d..46b8a5de3e7 100644 --- a/tests/components/homekit_controller/conftest.py +++ b/tests/components/homekit_controller/conftest.py @@ -10,6 +10,8 @@ import homeassistant.util.dt as dt_util from tests.components.light.conftest import mock_light_profiles # noqa: F401 +pytest.register_assert_rewrite("tests.components.homekit_controller.common") + @pytest.fixture def utcnow(request): diff --git a/tests/components/homekit_controller/fixtures/hue_bridge.json b/tests/components/homekit_controller/fixtures/hue_bridge.json index 7ed3882be09..ed893cdad60 100644 --- a/tests/components/homekit_controller/fixtures/hue_bridge.json +++ b/tests/components/homekit_controller/fixtures/hue_bridge.json @@ -422,7 +422,7 @@ "pr" ], "type": "00000030-0000-1000-8000-0026BB765291", - "value": "1" + "value": "123456" }, { "format": "bool", diff --git a/tests/components/homekit_controller/specific_devices/test_anker_eufycam.py b/tests/components/homekit_controller/specific_devices/test_anker_eufycam.py index 652ac5b0559..b963d33c83e 100644 --- a/tests/components/homekit_controller/specific_devices/test_anker_eufycam.py +++ b/tests/components/homekit_controller/specific_devices/test_anker_eufycam.py @@ -1,8 +1,9 @@ """Test against characteristics captured from a eufycam.""" -from homeassistant.helpers import device_registry as dr, entity_registry as er from tests.components.homekit_controller.common import ( - Helper, + DeviceTestInfo, + EntityTestInfo, + assert_devices_and_entities_created, setup_accessories_from_file, setup_test_accessories, ) @@ -11,45 +12,45 @@ from tests.components.homekit_controller.common import ( async def test_eufycam_setup(hass): """Test that a eufycam can be correctly setup in HA.""" accessories = await setup_accessories_from_file(hass, "anker_eufycam.json") - config_entry, pairing = await setup_test_accessories(hass, accessories) + await setup_test_accessories(hass, accessories) - entity_registry = er.async_get(hass) - - # Check that the camera is correctly found and set up - camera_id = "camera.eufycam2_0000" - camera = entity_registry.async_get(camera_id) - assert camera.unique_id == "homekit-A0000A000000000D-aid:4" - - camera_helper = Helper( + await assert_devices_and_entities_created( hass, - "camera.eufycam2_0000", - pairing, - accessories[0], - config_entry, + DeviceTestInfo( + unique_id="00:00:00:00:00:00", + name="eufy HomeBase2-0AAA", + model="T8010", + manufacturer="Anker", + sw_version="2.1.6", + hw_version="2.0.0", + serial_number="A0000A000000000A", + devices=[ + DeviceTestInfo( + name="eufyCam2-0000", + model="T8113", + manufacturer="Anker", + sw_version="1.6.7", + hw_version="1.0.0", + serial_number="A0000A000000000D", + devices=[], + entities=[ + EntityTestInfo( + entity_id="camera.eufycam2_0000", + friendly_name="eufyCam2-0000", + unique_id="homekit-A0000A000000000D-aid:4", + state="idle", + ), + ], + ), + ], + entities=[], + ), ) - camera_state = await camera_helper.poll_and_get_state() - assert camera_state.attributes["friendly_name"] == "eufyCam2-0000" - assert camera_state.state == "idle" - assert camera_state.attributes["supported_features"] == 0 - - device_registry = dr.async_get(hass) - - device = device_registry.async_get(camera.device_id) - assert device.manufacturer == "Anker" - assert device.name == "eufyCam2-0000" - assert device.model == "T8113" - assert device.sw_version == "1.6.7" - assert device.hw_version == "1.0.0" - - # These cameras are via a bridge, so via should be set - assert device.via_device_id is not None - + # There are multiple rtsp services, we only want to create 1 + # camera entity per accessory, not 1 camera per service. cameras_count = 0 for state in hass.states.async_all(): if state.entity_id.startswith("camera."): cameras_count += 1 - - # There are multiple rtsp services, we only want to create 1 - # camera entity per accessory, not 1 camera per service. assert cameras_count == 3 diff --git a/tests/components/homekit_controller/specific_devices/test_aqara_gateway.py b/tests/components/homekit_controller/specific_devices/test_aqara_gateway.py index fd9ef96752a..70b6dc4870a 100644 --- a/tests/components/homekit_controller/specific_devices/test_aqara_gateway.py +++ b/tests/components/homekit_controller/specific_devices/test_aqara_gateway.py @@ -9,11 +9,13 @@ from homeassistant.components.alarm_control_panel import ( SUPPORT_ALARM_ARM_NIGHT, ) from homeassistant.components.light import SUPPORT_BRIGHTNESS, SUPPORT_COLOR -from homeassistant.helpers import device_registry as dr, entity_registry as er +from homeassistant.components.number import NumberMode from homeassistant.helpers.entity import EntityCategory from tests.components.homekit_controller.common import ( - Helper, + DeviceTestInfo, + EntityTestInfo, + assert_devices_and_entities_created, setup_accessories_from_file, setup_test_accessories, ) @@ -22,131 +24,108 @@ from tests.components.homekit_controller.common import ( async def test_aqara_gateway_setup(hass): """Test that a Aqara Gateway can be correctly setup in HA.""" accessories = await setup_accessories_from_file(hass, "aqara_gateway.json") - config_entry, pairing = await setup_test_accessories(hass, accessories) + await setup_test_accessories(hass, accessories) - entity_registry = er.async_get(hass) - device_registry = dr.async_get(hass) - - sensors = [ - ( - "alarm_control_panel.aqara_hub_1563", - "homekit-0000000123456789-66304", - "Aqara Hub-1563", - SUPPORT_ALARM_ARM_NIGHT | SUPPORT_ALARM_ARM_HOME | SUPPORT_ALARM_ARM_AWAY, - None, + await assert_devices_and_entities_created( + hass, + DeviceTestInfo( + unique_id="00:00:00:00:00:00", + name="Aqara Hub-1563", + model="ZHWA11LM", + manufacturer="Aqara", + sw_version="1.4.7", + hw_version="", + serial_number="0000000123456789", + devices=[], + entities=[ + EntityTestInfo( + "alarm_control_panel.aqara_hub_1563", + friendly_name="Aqara Hub-1563", + unique_id="homekit-0000000123456789-66304", + supported_features=SUPPORT_ALARM_ARM_NIGHT + | SUPPORT_ALARM_ARM_HOME + | SUPPORT_ALARM_ARM_AWAY, + state="disarmed", + ), + EntityTestInfo( + "light.aqara_hub_1563", + friendly_name="Aqara Hub-1563", + unique_id="homekit-0000000123456789-65792", + supported_features=SUPPORT_BRIGHTNESS | SUPPORT_COLOR, + capabilities={"supported_color_modes": ["hs"]}, + state="off", + ), + EntityTestInfo( + "number.aqara_hub_1563_volume", + friendly_name="Aqara Hub-1563 Volume", + unique_id="homekit-0000000123456789-aid:1-sid:65536-cid:65541", + capabilities={ + "max": 100, + "min": 0, + "mode": NumberMode.AUTO, + "step": 1, + }, + entity_category=EntityCategory.CONFIG, + state="40", + ), + EntityTestInfo( + "switch.aqara_hub_1563_pairing_mode", + friendly_name="Aqara Hub-1563 Pairing Mode", + unique_id="homekit-0000000123456789-aid:1-sid:65536-cid:65538", + entity_category=EntityCategory.CONFIG, + state="off", + ), + ], ), - ( - "light.aqara_hub_1563", - "homekit-0000000123456789-65792", - "Aqara Hub-1563", - SUPPORT_BRIGHTNESS | SUPPORT_COLOR, - None, - ), - ( - "number.aqara_hub_1563_volume", - "homekit-0000000123456789-aid:1-sid:65536-cid:65541", - "Aqara Hub-1563 Volume", - None, - EntityCategory.CONFIG, - ), - ( - "switch.aqara_hub_1563_pairing_mode", - "homekit-0000000123456789-aid:1-sid:65536-cid:65538", - "Aqara Hub-1563 Pairing Mode", - None, - EntityCategory.CONFIG, - ), - ] - - device_ids = set() - - for (entity_id, unique_id, friendly_name, supported_features, category) in sensors: - entry = entity_registry.async_get(entity_id) - assert entry.unique_id == unique_id - assert entry.entity_category == category - - helper = Helper( - hass, - entity_id, - pairing, - accessories[0], - config_entry, - ) - state = await helper.poll_and_get_state() - assert state.attributes["friendly_name"] == friendly_name - assert state.attributes.get("supported_features") == supported_features - - device = device_registry.async_get(entry.device_id) - assert device.manufacturer == "Aqara" - assert device.name == "Aqara Hub-1563" - assert device.model == "ZHWA11LM" - assert device.sw_version == "1.4.7" - assert device.via_device_id is None - - device_ids.add(entry.device_id) - - # All entities should be part of same device - assert len(device_ids) == 1 + ) async def test_aqara_gateway_e1_setup(hass): """Test that an Aqara E1 Gateway can be correctly setup in HA.""" accessories = await setup_accessories_from_file(hass, "aqara_e1.json") - config_entry, pairing = await setup_test_accessories(hass, accessories) + await setup_test_accessories(hass, accessories) - entity_registry = er.async_get(hass) - device_registry = dr.async_get(hass) - - sensors = [ - ( - "alarm_control_panel.aqara_hub_e1_00a0", - "homekit-00aa00000a0-16", - "Aqara-Hub-E1-00A0", - SUPPORT_ALARM_ARM_NIGHT | SUPPORT_ALARM_ARM_HOME | SUPPORT_ALARM_ARM_AWAY, - None, + await assert_devices_and_entities_created( + hass, + DeviceTestInfo( + unique_id="00:00:00:00:00:00", + name="Aqara-Hub-E1-00A0", + model="HE1-G01", + manufacturer="Aqara", + sw_version="3.3.0", + hw_version="1.0", + serial_number="00aa00000a0", + devices=[], + entities=[ + EntityTestInfo( + "alarm_control_panel.aqara_hub_e1_00a0", + friendly_name="Aqara-Hub-E1-00A0", + unique_id="homekit-00aa00000a0-16", + supported_features=SUPPORT_ALARM_ARM_NIGHT + | SUPPORT_ALARM_ARM_HOME + | SUPPORT_ALARM_ARM_AWAY, + state="disarmed", + ), + EntityTestInfo( + "number.aqara_hub_e1_00a0_volume", + friendly_name="Aqara-Hub-E1-00A0 Volume", + unique_id="homekit-00aa00000a0-aid:1-sid:17-cid:1114116", + capabilities={ + "max": 100, + "min": 0, + "mode": NumberMode.AUTO, + "step": 1, + }, + entity_category=EntityCategory.CONFIG, + state="40", + ), + EntityTestInfo( + "switch.aqara_hub_e1_00a0_pairing_mode", + friendly_name="Aqara-Hub-E1-00A0 Pairing Mode", + unique_id="homekit-00aa00000a0-aid:1-sid:17-cid:1114117", + entity_category=EntityCategory.CONFIG, + state="off", + ), + ], ), - ( - "number.aqara_hub_e1_00a0_volume", - "homekit-00aa00000a0-aid:1-sid:17-cid:1114116", - "Aqara-Hub-E1-00A0 Volume", - None, - EntityCategory.CONFIG, - ), - ( - "switch.aqara_hub_e1_00a0_pairing_mode", - "homekit-00aa00000a0-aid:1-sid:17-cid:1114117", - "Aqara-Hub-E1-00A0 Pairing Mode", - None, - EntityCategory.CONFIG, - ), - ] - - device_ids = set() - - for (entity_id, unique_id, friendly_name, supported_features, category) in sensors: - entry = entity_registry.async_get(entity_id) - assert entry.unique_id == unique_id - assert entry.entity_category == category - - helper = Helper( - hass, - entity_id, - pairing, - accessories[0], - config_entry, - ) - state = await helper.poll_and_get_state() - assert state.attributes["friendly_name"] == friendly_name - assert state.attributes.get("supported_features") == supported_features - - device = device_registry.async_get(entry.device_id) - assert device.manufacturer == "Aqara" - assert device.name == "Aqara-Hub-E1-00A0" - assert device.model == "HE1-G01" - assert device.sw_version == "3.3.0" - assert device.via_device_id is None - - device_ids.add(entry.device_id) - - # All entities should be part of same device - assert len(device_ids) == 1 + ) diff --git a/tests/components/homekit_controller/specific_devices/test_aqara_switch.py b/tests/components/homekit_controller/specific_devices/test_aqara_switch.py index 945d950ecc9..342dda263d8 100644 --- a/tests/components/homekit_controller/specific_devices/test_aqara_switch.py +++ b/tests/components/homekit_controller/specific_devices/test_aqara_switch.py @@ -7,11 +7,13 @@ service-label-index despite not being linked to a service-label. https://github.com/home-assistant/core/pull/39090 """ -from homeassistant.components.device_automation import DeviceAutomationType -from homeassistant.helpers import entity_registry as er +from homeassistant.const import PERCENTAGE -from tests.common import assert_lists_same, async_get_device_automations from tests.components.homekit_controller.common import ( + DeviceTestInfo, + DeviceTriggerInfo, + EntityTestInfo, + assert_devices_and_entities_created, setup_accessories_from_file, setup_test_accessories, ) @@ -20,38 +22,32 @@ from tests.components.homekit_controller.common import ( async def test_aqara_switch_setup(hass): """Test that a Aqara Switch can be correctly setup in HA.""" accessories = await setup_accessories_from_file(hass, "aqara_switch.json") - config_entry, pairing = await setup_test_accessories(hass, accessories) + await setup_test_accessories(hass, accessories) - entity_registry = er.async_get(hass) - - battery_id = "sensor.programmable_switch_battery" - battery = entity_registry.async_get(battery_id) - assert battery.unique_id == "homekit-111a1111a1a111-5" - - # The fixture file has 1 button and a battery - - expected = [ - { - "device_id": battery.device_id, - "domain": "sensor", - "entity_id": "sensor.programmable_switch_battery", - "platform": "device", - "type": "battery_level", - } - ] - - for subtype in ("single_press", "double_press", "long_press"): - expected.append( - { - "device_id": battery.device_id, - "domain": "homekit_controller", - "platform": "device", - "type": "button1", - "subtype": subtype, - } - ) - - triggers = await async_get_device_automations( - hass, DeviceAutomationType.TRIGGER, battery.device_id + await assert_devices_and_entities_created( + hass, + DeviceTestInfo( + unique_id="00:00:00:00:00:00", + name="Programmable Switch", + model="AR004", + manufacturer="Aqara", + sw_version="9", + hw_version="1.0", + serial_number="111a1111a1a111", + devices=[], + entities=[ + EntityTestInfo( + entity_id="sensor.programmable_switch_battery", + friendly_name="Programmable Switch Battery", + unique_id="homekit-111a1111a1a111-5", + unit_of_measurement=PERCENTAGE, + state="100", + ), + ], + stateless_triggers=[ + DeviceTriggerInfo(type="button1", subtype="single_press"), + DeviceTriggerInfo(type="button1", subtype="double_press"), + DeviceTriggerInfo(type="button1", subtype="long_press"), + ], + ), ) - assert_lists_same(triggers, expected) diff --git a/tests/components/homekit_controller/specific_devices/test_arlo_baby.py b/tests/components/homekit_controller/specific_devices/test_arlo_baby.py index 86fb9f65f11..815613e675e 100644 --- a/tests/components/homekit_controller/specific_devices/test_arlo_baby.py +++ b/tests/components/homekit_controller/specific_devices/test_arlo_baby.py @@ -1,9 +1,13 @@ """Make sure that an Arlo Baby can be setup.""" -from homeassistant.helpers import device_registry as dr, entity_registry as er +from homeassistant.components.light import SUPPORT_BRIGHTNESS, SUPPORT_COLOR +from homeassistant.components.sensor import SensorStateClass +from homeassistant.const import PERCENTAGE, TEMP_CELSIUS from tests.components.homekit_controller.common import ( - Helper, + DeviceTestInfo, + EntityTestInfo, + assert_devices_and_entities_created, setup_accessories_from_file, setup_test_accessories, ) @@ -12,73 +16,68 @@ from tests.components.homekit_controller.common import ( async def test_arlo_baby_setup(hass): """Test that an Arlo Baby can be correctly setup in HA.""" accessories = await setup_accessories_from_file(hass, "arlo_baby.json") - config_entry, pairing = await setup_test_accessories(hass, accessories) + await setup_test_accessories(hass, accessories) - entity_registry = er.async_get(hass) - device_registry = dr.async_get(hass) - - sensors = [ - ( - "camera.arlobabya0", - "homekit-00A0000000000-aid:1", - "ArloBabyA0", + await assert_devices_and_entities_created( + hass, + DeviceTestInfo( + unique_id="00:00:00:00:00:00", + name="ArloBabyA0", + model="ABC1000", + manufacturer="Netgear, Inc", + sw_version="1.10.931", + hw_version="", + serial_number="00A0000000000", + devices=[], + entities=[ + EntityTestInfo( + entity_id="camera.arlobabya0", + unique_id="homekit-00A0000000000-aid:1", + friendly_name="ArloBabyA0", + state="idle", + ), + EntityTestInfo( + entity_id="binary_sensor.arlobabya0", + unique_id="homekit-00A0000000000-500", + friendly_name="ArloBabyA0", + state="off", + ), + EntityTestInfo( + entity_id="sensor.arlobabya0_battery", + unique_id="homekit-00A0000000000-700", + friendly_name="ArloBabyA0 Battery", + unit_of_measurement=PERCENTAGE, + state="82", + ), + EntityTestInfo( + entity_id="sensor.arlobabya0_humidity", + unique_id="homekit-00A0000000000-900", + friendly_name="ArloBabyA0 Humidity", + unit_of_measurement=PERCENTAGE, + state="60.099998", + ), + EntityTestInfo( + entity_id="sensor.arlobabya0_temperature", + unique_id="homekit-00A0000000000-1000", + friendly_name="ArloBabyA0 Temperature", + unit_of_measurement=TEMP_CELSIUS, + state="24.0", + ), + EntityTestInfo( + entity_id="sensor.arlobabya0_air_quality", + unique_id="homekit-00A0000000000-aid:1-sid:800-cid:802", + capabilities={"state_class": SensorStateClass.MEASUREMENT}, + friendly_name="ArloBabyA0 - Air Quality", + state="1", + ), + EntityTestInfo( + entity_id="light.arlobabya0", + unique_id="homekit-00A0000000000-1100", + friendly_name="ArloBabyA0", + supported_features=SUPPORT_BRIGHTNESS | SUPPORT_COLOR, + capabilities={"supported_color_modes": ["hs"]}, + state="off", + ), + ], ), - ( - "binary_sensor.arlobabya0", - "homekit-00A0000000000-500", - "ArloBabyA0", - ), - ( - "sensor.arlobabya0_battery", - "homekit-00A0000000000-700", - "ArloBabyA0 Battery", - ), - ( - "sensor.arlobabya0_humidity", - "homekit-00A0000000000-900", - "ArloBabyA0 Humidity", - ), - ( - "sensor.arlobabya0_temperature", - "homekit-00A0000000000-1000", - "ArloBabyA0 Temperature", - ), - ( - "sensor.arlobabya0_air_quality", - "homekit-00A0000000000-aid:1-sid:800-cid:802", - "ArloBabyA0 - Air Quality", - ), - ( - "light.arlobabya0", - "homekit-00A0000000000-1100", - "ArloBabyA0", - ), - ] - - device_ids = set() - - for (entity_id, unique_id, friendly_name) in sensors: - entry = entity_registry.async_get(entity_id) - assert entry.unique_id == unique_id - - helper = Helper( - hass, - entity_id, - pairing, - accessories[0], - config_entry, - ) - state = await helper.poll_and_get_state() - assert state.attributes["friendly_name"] == friendly_name - - device = device_registry.async_get(entry.device_id) - assert device.manufacturer == "Netgear, Inc" - assert device.name == "ArloBabyA0" - assert device.model == "ABC1000" - assert device.sw_version == "1.10.931" - assert device.via_device_id is None - - device_ids.add(entry.device_id) - - # All entities should be part of same device - assert len(device_ids) == 1 + ) diff --git a/tests/components/homekit_controller/specific_devices/test_connectsense.py b/tests/components/homekit_controller/specific_devices/test_connectsense.py index 29559118fe6..702ca825752 100644 --- a/tests/components/homekit_controller/specific_devices/test_connectsense.py +++ b/tests/components/homekit_controller/specific_devices/test_connectsense.py @@ -1,9 +1,16 @@ """Make sure that ConnectSense Smart Outlet2 / In-Wall Outlet is enumerated properly.""" -from homeassistant.helpers import device_registry as dr, entity_registry as er +from homeassistant.components.sensor import SensorStateClass +from homeassistant.const import ( + ELECTRIC_CURRENT_AMPERE, + ENERGY_KILO_WATT_HOUR, + POWER_WATT, +) from tests.components.homekit_controller.common import ( - Helper, + DeviceTestInfo, + EntityTestInfo, + assert_devices_and_entities_created, setup_accessories_from_file, setup_test_accessories, ) @@ -12,78 +19,80 @@ from tests.components.homekit_controller.common import ( async def test_connectsense_setup(hass): """Test that the accessory can be correctly setup in HA.""" accessories = await setup_accessories_from_file(hass, "connectsense.json") - config_entry, pairing = await setup_test_accessories(hass, accessories) + await setup_test_accessories(hass, accessories) - entity_registry = er.async_get(hass) - device_registry = dr.async_get(hass) - - entities = [ - ( - "sensor.inwall_outlet_0394de_real_time_current", - "homekit-1020301376-aid:1-sid:13-cid:18", - "InWall Outlet-0394DE - Real Time Current", + await assert_devices_and_entities_created( + hass, + DeviceTestInfo( + unique_id="00:00:00:00:00:00", + name="InWall Outlet-0394DE", + model="CS-IWO", + manufacturer="ConnectSense", + sw_version="1.0.0", + hw_version="", + serial_number="1020301376", + devices=[], + entities=[ + EntityTestInfo( + entity_id="sensor.inwall_outlet_0394de_real_time_current", + friendly_name="InWall Outlet-0394DE - Real Time Current", + unique_id="homekit-1020301376-aid:1-sid:13-cid:18", + capabilities={"state_class": SensorStateClass.MEASUREMENT}, + unit_of_measurement=ELECTRIC_CURRENT_AMPERE, + state="0.03", + ), + EntityTestInfo( + entity_id="sensor.inwall_outlet_0394de_real_time_energy", + friendly_name="InWall Outlet-0394DE - Real Time Energy", + unique_id="homekit-1020301376-aid:1-sid:13-cid:19", + capabilities={"state_class": SensorStateClass.MEASUREMENT}, + unit_of_measurement=POWER_WATT, + state="0.8", + ), + EntityTestInfo( + entity_id="sensor.inwall_outlet_0394de_energy_kwh", + friendly_name="InWall Outlet-0394DE - Energy kWh", + unique_id="homekit-1020301376-aid:1-sid:13-cid:20", + capabilities={"state_class": SensorStateClass.MEASUREMENT}, + unit_of_measurement=ENERGY_KILO_WATT_HOUR, + state="379.69299", + ), + EntityTestInfo( + entity_id="switch.inwall_outlet_0394de", + friendly_name="InWall Outlet-0394DE", + unique_id="homekit-1020301376-13", + state="on", + ), + EntityTestInfo( + entity_id="sensor.inwall_outlet_0394de_real_time_current_2", + friendly_name="InWall Outlet-0394DE - Real Time Current", + unique_id="homekit-1020301376-aid:1-sid:25-cid:30", + capabilities={"state_class": SensorStateClass.MEASUREMENT}, + unit_of_measurement=ELECTRIC_CURRENT_AMPERE, + state="0.05", + ), + EntityTestInfo( + entity_id="sensor.inwall_outlet_0394de_real_time_energy_2", + friendly_name="InWall Outlet-0394DE - Real Time Energy", + unique_id="homekit-1020301376-aid:1-sid:25-cid:31", + capabilities={"state_class": SensorStateClass.MEASUREMENT}, + unit_of_measurement=POWER_WATT, + state="0.8", + ), + EntityTestInfo( + entity_id="sensor.inwall_outlet_0394de_energy_kwh_2", + friendly_name="InWall Outlet-0394DE - Energy kWh", + unique_id="homekit-1020301376-aid:1-sid:25-cid:32", + capabilities={"state_class": SensorStateClass.MEASUREMENT}, + unit_of_measurement=ENERGY_KILO_WATT_HOUR, + state="175.85001", + ), + EntityTestInfo( + entity_id="switch.inwall_outlet_0394de_2", + friendly_name="InWall Outlet-0394DE", + unique_id="homekit-1020301376-25", + state="on", + ), + ], ), - ( - "sensor.inwall_outlet_0394de_real_time_energy", - "homekit-1020301376-aid:1-sid:13-cid:19", - "InWall Outlet-0394DE - Real Time Energy", - ), - ( - "sensor.inwall_outlet_0394de_energy_kwh", - "homekit-1020301376-aid:1-sid:13-cid:20", - "InWall Outlet-0394DE - Energy kWh", - ), - ( - "switch.inwall_outlet_0394de", - "homekit-1020301376-13", - "InWall Outlet-0394DE", - ), - ( - "sensor.inwall_outlet_0394de_real_time_current_2", - "homekit-1020301376-aid:1-sid:25-cid:30", - "InWall Outlet-0394DE - Real Time Current", - ), - ( - "sensor.inwall_outlet_0394de_real_time_energy_2", - "homekit-1020301376-aid:1-sid:25-cid:31", - "InWall Outlet-0394DE - Real Time Energy", - ), - ( - "sensor.inwall_outlet_0394de_energy_kwh_2", - "homekit-1020301376-aid:1-sid:25-cid:32", - "InWall Outlet-0394DE - Energy kWh", - ), - ( - "switch.inwall_outlet_0394de_2", - "homekit-1020301376-25", - "InWall Outlet-0394DE", - ), - ] - - device_ids = set() - - for (entity_id, unique_id, friendly_name) in entities: - entry = entity_registry.async_get(entity_id) - assert entry.unique_id == unique_id - - helper = Helper( - hass, - entity_id, - pairing, - accessories[0], - config_entry, - ) - state = await helper.poll_and_get_state() - assert state.attributes["friendly_name"] == friendly_name - - device = device_registry.async_get(entry.device_id) - assert device.manufacturer == "ConnectSense" - assert device.name == "InWall Outlet-0394DE" - assert device.model == "CS-IWO" - assert device.sw_version == "1.0.0" - assert device.via_device_id is None - - device_ids.add(entry.device_id) - - # All entities should be part of same device - assert len(device_ids) == 1 + ) diff --git a/tests/components/homekit_controller/specific_devices/test_ecobee3.py b/tests/components/homekit_controller/specific_devices/test_ecobee3.py index 94f3aabc12a..5847d222e9e 100644 --- a/tests/components/homekit_controller/specific_devices/test_ecobee3.py +++ b/tests/components/homekit_controller/specific_devices/test_ecobee3.py @@ -14,11 +14,15 @@ from homeassistant.components.climate.const import ( SUPPORT_TARGET_TEMPERATURE, SUPPORT_TARGET_TEMPERATURE_RANGE, ) +from homeassistant.components.sensor import SensorStateClass from homeassistant.config_entries import ConfigEntryState -from homeassistant.helpers import device_registry as dr, entity_registry as er +from homeassistant.const import TEMP_CELSIUS +from homeassistant.helpers import entity_registry as er from tests.components.homekit_controller.common import ( - Helper, + DeviceTestInfo, + EntityTestInfo, + assert_devices_and_entities_created, device_config_changed, setup_accessories_from_file, setup_test_accessories, @@ -29,71 +33,101 @@ from tests.components.homekit_controller.common import ( async def test_ecobee3_setup(hass): """Test that a Ecbobee 3 can be correctly setup in HA.""" accessories = await setup_accessories_from_file(hass, "ecobee3.json") - config_entry, pairing = await setup_test_accessories(hass, accessories) + await setup_test_accessories(hass, accessories) - entity_registry = er.async_get(hass) - - climate = entity_registry.async_get("climate.homew") - assert climate.unique_id == "homekit-123456789012-16" - - climate_helper = Helper( - hass, "climate.homew", pairing, accessories[0], config_entry + await assert_devices_and_entities_created( + hass, + DeviceTestInfo( + unique_id="00:00:00:00:00:00", + name="HomeW", + model="ecobee3", + manufacturer="ecobee Inc.", + sw_version="4.2.394", + hw_version="", + serial_number="123456789012", + devices=[ + DeviceTestInfo( + name="Kitchen", + model="REMOTE SENSOR", + manufacturer="ecobee Inc.", + sw_version="1.0.0", + hw_version="", + serial_number="AB1C", + devices=[], + entities=[ + EntityTestInfo( + entity_id="binary_sensor.kitchen", + friendly_name="Kitchen", + unique_id="homekit-AB1C-56", + state="off", + ), + ], + ), + DeviceTestInfo( + name="Porch", + model="REMOTE SENSOR", + manufacturer="ecobee Inc.", + sw_version="1.0.0", + hw_version="", + serial_number="AB2C", + devices=[], + entities=[ + EntityTestInfo( + entity_id="binary_sensor.porch", + friendly_name="Porch", + unique_id="homekit-AB2C-56", + state="off", + ), + ], + ), + DeviceTestInfo( + name="Basement", + model="REMOTE SENSOR", + manufacturer="ecobee Inc.", + sw_version="1.0.0", + hw_version="", + serial_number="AB3C", + devices=[], + entities=[ + EntityTestInfo( + entity_id="binary_sensor.basement", + friendly_name="Basement", + unique_id="homekit-AB3C-56", + state="off", + ), + ], + ), + ], + entities=[ + EntityTestInfo( + entity_id="climate.homew", + friendly_name="HomeW", + unique_id="homekit-123456789012-16", + supported_features=( + SUPPORT_TARGET_TEMPERATURE + | SUPPORT_TARGET_TEMPERATURE_RANGE + | SUPPORT_TARGET_HUMIDITY + ), + capabilities={ + "hvac_modes": ["off", "heat", "cool", "heat_cool"], + "min_temp": 7.2, + "max_temp": 33.3, + "min_humidity": 20, + "max_humidity": 50, + }, + state="heat", + ), + EntityTestInfo( + entity_id="sensor.homew_current_temperature", + friendly_name="HomeW - Current Temperature", + unique_id="homekit-123456789012-aid:1-sid:16-cid:19", + capabilities={"state_class": SensorStateClass.MEASUREMENT}, + unit_of_measurement=TEMP_CELSIUS, + state="21.8", + ), + ], + ), ) - climate_state = await climate_helper.poll_and_get_state() - assert climate_state.attributes["friendly_name"] == "HomeW" - assert climate_state.attributes["supported_features"] == ( - SUPPORT_TARGET_TEMPERATURE - | SUPPORT_TARGET_TEMPERATURE_RANGE - | SUPPORT_TARGET_HUMIDITY - ) - - assert climate_state.attributes["hvac_modes"] == [ - "off", - "heat", - "cool", - "heat_cool", - ] - - assert climate_state.attributes["min_temp"] == 7.2 - assert climate_state.attributes["max_temp"] == 33.3 - assert climate_state.attributes["min_humidity"] == 20 - assert climate_state.attributes["max_humidity"] == 50 - - climate_sensor = entity_registry.async_get("sensor.homew_current_temperature") - assert climate_sensor.unique_id == "homekit-123456789012-aid:1-sid:16-cid:19" - - occ1 = entity_registry.async_get("binary_sensor.kitchen") - assert occ1.unique_id == "homekit-AB1C-56" - - occ1_helper = Helper( - hass, "binary_sensor.kitchen", pairing, accessories[0], config_entry - ) - occ1_state = await occ1_helper.poll_and_get_state() - assert occ1_state.attributes["friendly_name"] == "Kitchen" - - occ2 = entity_registry.async_get("binary_sensor.porch") - assert occ2.unique_id == "homekit-AB2C-56" - - occ3 = entity_registry.async_get("binary_sensor.basement") - assert occ3.unique_id == "homekit-AB3C-56" - - device_registry = dr.async_get(hass) - - climate_device = device_registry.async_get(climate.device_id) - assert climate_device.manufacturer == "ecobee Inc." - assert climate_device.name == "HomeW" - assert climate_device.model == "ecobee3" - assert climate_device.sw_version == "4.2.394" - assert climate_device.via_device_id is None - - # Check that an attached sensor has its own device entity that - # is linked to the bridge - sensor_device = device_registry.async_get(occ1.device_id) - assert sensor_device.manufacturer == "ecobee Inc." - assert sensor_device.name == "Kitchen" - assert sensor_device.model == "REMOTE SENSOR" - assert sensor_device.sw_version == "1.0.0" - assert sensor_device.via_device_id == climate_device.id async def test_ecobee3_setup_from_cache(hass, hass_storage): diff --git a/tests/components/homekit_controller/specific_devices/test_ecobee_occupancy.py b/tests/components/homekit_controller/specific_devices/test_ecobee_occupancy.py index 63f5d22e04b..293ecd07dd2 100644 --- a/tests/components/homekit_controller/specific_devices/test_ecobee_occupancy.py +++ b/tests/components/homekit_controller/specific_devices/test_ecobee_occupancy.py @@ -4,10 +4,10 @@ Regression tests for Ecobee occupancy. https://github.com/home-assistant/core/issues/31827 """ -from homeassistant.helpers import device_registry as dr, entity_registry as er - from tests.components.homekit_controller.common import ( - Helper, + DeviceTestInfo, + EntityTestInfo, + assert_devices_and_entities_created, setup_accessories_from_file, setup_test_accessories, ) @@ -16,24 +16,26 @@ from tests.components.homekit_controller.common import ( async def test_ecobee_occupancy_setup(hass): """Test that an Ecbobee occupancy sensor be correctly setup in HA.""" accessories = await setup_accessories_from_file(hass, "ecobee_occupancy.json") - config_entry, pairing = await setup_test_accessories(hass, accessories) + await setup_test_accessories(hass, accessories) - entity_registry = er.async_get(hass) - - sensor = entity_registry.async_get("binary_sensor.master_fan") - assert sensor.unique_id == "homekit-111111111111-56" - - sensor_helper = Helper( - hass, "binary_sensor.master_fan", pairing, accessories[0], config_entry + await assert_devices_and_entities_created( + hass, + DeviceTestInfo( + unique_id="00:00:00:00:00:00", + name="Master Fan", + model="ecobee Switch+", + manufacturer="ecobee Inc.", + sw_version="4.5.130201", + hw_version="", + serial_number="111111111111", + devices=[], + entities=[ + EntityTestInfo( + entity_id="binary_sensor.master_fan", + friendly_name="Master Fan", + unique_id="homekit-111111111111-56", + state="off", + ), + ], + ), ) - sensor_state = await sensor_helper.poll_and_get_state() - assert sensor_state.attributes["friendly_name"] == "Master Fan" - - device_registry = dr.async_get(hass) - - device = device_registry.async_get(sensor.device_id) - assert device.manufacturer == "ecobee Inc." - assert device.name == "Master Fan" - assert device.model == "ecobee Switch+" - assert device.sw_version == "4.5.130201" - assert device.via_device_id is None diff --git a/tests/components/homekit_controller/specific_devices/test_eve_degree.py b/tests/components/homekit_controller/specific_devices/test_eve_degree.py index 312316e8870..466123a224e 100644 --- a/tests/components/homekit_controller/specific_devices/test_eve_degree.py +++ b/tests/components/homekit_controller/specific_devices/test_eve_degree.py @@ -1,9 +1,14 @@ """Make sure that Eve Degree (via Eve Extend) is enumerated properly.""" -from homeassistant.helpers import device_registry as dr, entity_registry as er +from homeassistant.components.number import NumberMode +from homeassistant.components.sensor import SensorStateClass +from homeassistant.const import PERCENTAGE, PRESSURE_HPA, TEMP_CELSIUS +from homeassistant.helpers.entity import EntityCategory from tests.components.homekit_controller.common import ( - Helper, + DeviceTestInfo, + EntityTestInfo, + assert_devices_and_entities_created, setup_accessories_from_file, setup_test_accessories, ) @@ -12,63 +17,62 @@ from tests.components.homekit_controller.common import ( async def test_eve_degree_setup(hass): """Test that the accessory can be correctly setup in HA.""" accessories = await setup_accessories_from_file(hass, "eve_degree.json") - config_entry, pairing = await setup_test_accessories(hass, accessories) + await setup_test_accessories(hass, accessories) - entity_registry = er.async_get(hass) - device_registry = dr.async_get(hass) - - sensors = [ - ( - "sensor.eve_degree_aa11_temperature", - "homekit-AA00A0A00000-22", - "Eve Degree AA11 Temperature", + await assert_devices_and_entities_created( + hass, + DeviceTestInfo( + unique_id="00:00:00:00:00:00", + name="Eve Degree AA11", + model="Eve Degree 00AAA0000", + manufacturer="Elgato", + sw_version="1.2.8", + hw_version="1.0.0", + serial_number="AA00A0A00000", + devices=[], + entities=[ + EntityTestInfo( + entity_id="sensor.eve_degree_aa11_temperature", + unique_id="homekit-AA00A0A00000-22", + friendly_name="Eve Degree AA11 Temperature", + unit_of_measurement=TEMP_CELSIUS, + state="22.7719116210938", + ), + EntityTestInfo( + entity_id="sensor.eve_degree_aa11_humidity", + unique_id="homekit-AA00A0A00000-27", + friendly_name="Eve Degree AA11 Humidity", + unit_of_measurement=PERCENTAGE, + state="59.4818115234375", + ), + EntityTestInfo( + entity_id="sensor.eve_degree_aa11_air_pressure", + unique_id="homekit-AA00A0A00000-aid:1-sid:30-cid:32", + friendly_name="Eve Degree AA11 - Air Pressure", + unit_of_measurement=PRESSURE_HPA, + capabilities={"state_class": SensorStateClass.MEASUREMENT}, + state="1005.70001220703", + ), + EntityTestInfo( + entity_id="sensor.eve_degree_aa11_battery", + unique_id="homekit-AA00A0A00000-17", + friendly_name="Eve Degree AA11 Battery", + unit_of_measurement=PERCENTAGE, + state="65", + ), + EntityTestInfo( + entity_id="number.eve_degree_aa11_elevation", + unique_id="homekit-AA00A0A00000-aid:1-sid:30-cid:33", + friendly_name="Eve Degree AA11 Elevation", + capabilities={ + "max": 9000, + "min": -450, + "mode": NumberMode.AUTO, + "step": 1, + }, + state="0", + entity_category=EntityCategory.CONFIG, + ), + ], ), - ( - "sensor.eve_degree_aa11_humidity", - "homekit-AA00A0A00000-27", - "Eve Degree AA11 Humidity", - ), - ( - "sensor.eve_degree_aa11_air_pressure", - "homekit-AA00A0A00000-aid:1-sid:30-cid:32", - "Eve Degree AA11 - Air Pressure", - ), - ( - "sensor.eve_degree_aa11_battery", - "homekit-AA00A0A00000-17", - "Eve Degree AA11 Battery", - ), - ( - "number.eve_degree_aa11_elevation", - "homekit-AA00A0A00000-aid:1-sid:30-cid:33", - "Eve Degree AA11 Elevation", - ), - ] - - device_ids = set() - - for (entity_id, unique_id, friendly_name) in sensors: - entry = entity_registry.async_get(entity_id) - assert entry.unique_id == unique_id - - helper = Helper( - hass, - entity_id, - pairing, - accessories[0], - config_entry, - ) - state = await helper.poll_and_get_state() - assert state.attributes["friendly_name"] == friendly_name - - device = device_registry.async_get(entry.device_id) - assert device.manufacturer == "Elgato" - assert device.name == "Eve Degree AA11" - assert device.model == "Eve Degree 00AAA0000" - assert device.sw_version == "1.2.8" - assert device.via_device_id is None - - device_ids.add(entry.device_id) - - # All entities should be part of same device - assert len(device_ids) == 1 + ) diff --git a/tests/components/homekit_controller/specific_devices/test_haa_fan.py b/tests/components/homekit_controller/specific_devices/test_haa_fan.py index 0339c61168f..cd12831210a 100644 --- a/tests/components/homekit_controller/specific_devices/test_haa_fan.py +++ b/tests/components/homekit_controller/specific_devices/test_haa_fan.py @@ -1,9 +1,12 @@ """Make sure that a H.A.A. fan can be setup.""" -from homeassistant.helpers import device_registry as dr, entity_registry as er +from homeassistant.components.fan import SUPPORT_SET_SPEED +from homeassistant.helpers.entity import EntityCategory from tests.components.homekit_controller.common import ( - Helper, + DeviceTestInfo, + EntityTestInfo, + assert_devices_and_entities_created, setup_accessories_from_file, setup_test_accessories, ) @@ -12,65 +15,65 @@ from tests.components.homekit_controller.common import ( async def test_haa_fan_setup(hass): """Test that a H.A.A. fan can be correctly setup in HA.""" accessories = await setup_accessories_from_file(hass, "haa_fan.json") - config_entry, pairing = await setup_test_accessories(hass, accessories) + await setup_test_accessories(hass, accessories) - entity_registry = er.async_get(hass) - device_registry = dr.async_get(hass) + # FIXME: assert round(state.attributes["percentage_step"], 2) == 33.33 - # Check that the switch entity is handled correctly - - entry = entity_registry.async_get("switch.haa_c718b3") - assert entry.unique_id == "homekit-C718B3-2-8" - - helper = Helper(hass, "switch.haa_c718b3", pairing, accessories[0], config_entry) - state = await helper.poll_and_get_state() - assert state.attributes["friendly_name"] == "HAA-C718B3" - - device = device_registry.async_get(entry.device_id) - assert device.manufacturer == "José A. Jiménez Campos" - assert device.name == "HAA-C718B3" - assert device.sw_version == "5.0.18" - assert device.via_device_id is not None - - # Assert the fan is detected - entry = entity_registry.async_get("fan.haa_c718b3") - assert entry.unique_id == "homekit-C718B3-1-8" - - helper = Helper( + await assert_devices_and_entities_created( hass, - "fan.haa_c718b3", - pairing, - accessories[0], - config_entry, + DeviceTestInfo( + unique_id="00:00:00:00:00:00", + name="HAA-C718B3", + model="RavenSystem HAA", + manufacturer="José A. Jiménez Campos", + sw_version="5.0.18", + hw_version="", + serial_number="C718B3-1", + devices=[ + DeviceTestInfo( + name="HAA-C718B3", + model="RavenSystem HAA", + manufacturer="José A. Jiménez Campos", + sw_version="5.0.18", + hw_version="", + serial_number="C718B3-2", + devices=[], + entities=[ + EntityTestInfo( + entity_id="switch.haa_c718b3", + friendly_name="HAA-C718B3", + unique_id="homekit-C718B3-2-8", + state="off", + ) + ], + ), + ], + entities=[ + EntityTestInfo( + entity_id="fan.haa_c718b3", + friendly_name="HAA-C718B3", + unique_id="homekit-C718B3-1-8", + state="off", + supported_features=SUPPORT_SET_SPEED, + capabilities={ + "preset_modes": None, + "speed_list": ["off", "low", "medium", "high"], + }, + ), + EntityTestInfo( + entity_id="button.haa_c718b3_setup", + friendly_name="HAA-C718B3 - Setup", + unique_id="homekit-C718B3-1-aid:1-sid:1010-cid:1012", + entity_category=EntityCategory.CONFIG, + state="unknown", + ), + EntityTestInfo( + entity_id="button.haa_c718b3_update", + friendly_name="HAA-C718B3 - Update", + unique_id="homekit-C718B3-1-aid:1-sid:1010-cid:1011", + entity_category=EntityCategory.CONFIG, + state="unknown", + ), + ], + ), ) - state = await helper.poll_and_get_state() - assert state.attributes["friendly_name"] == "HAA-C718B3" - assert round(state.attributes["percentage_step"], 2) == 33.33 - - # Check that custom HAA Setup button is created - entry = entity_registry.async_get("button.haa_c718b3_setup") - assert entry.unique_id == "homekit-C718B3-1-aid:1-sid:1010-cid:1012" - - helper = Helper( - hass, - "button.haa_c718b3_setup", - pairing, - accessories[0], - config_entry, - ) - state = await helper.poll_and_get_state() - assert state.attributes["friendly_name"] == "HAA-C718B3 - Setup" - - # Check that custom HAA Update button is created - entry = entity_registry.async_get("button.haa_c718b3_update") - assert entry.unique_id == "homekit-C718B3-1-aid:1-sid:1010-cid:1011" - - helper = Helper( - hass, - "button.haa_c718b3_update", - pairing, - accessories[0], - config_entry, - ) - state = await helper.poll_and_get_state() - assert state.attributes["friendly_name"] == "HAA-C718B3 - Update" diff --git a/tests/components/homekit_controller/specific_devices/test_homeassistant_bridge.py b/tests/components/homekit_controller/specific_devices/test_homeassistant_bridge.py index 1cbfa23b64c..684b2ebde27 100644 --- a/tests/components/homekit_controller/specific_devices/test_homeassistant_bridge.py +++ b/tests/components/homekit_controller/specific_devices/test_homeassistant_bridge.py @@ -5,10 +5,11 @@ from homeassistant.components.fan import ( SUPPORT_OSCILLATE, SUPPORT_SET_SPEED, ) -from homeassistant.helpers import device_registry as dr, entity_registry as er from tests.components.homekit_controller.common import ( - Helper, + DeviceTestInfo, + EntityTestInfo, + assert_devices_and_entities_created, setup_accessories_from_file, setup_test_accessories, ) @@ -19,40 +20,46 @@ async def test_homeassistant_bridge_fan_setup(hass): accessories = await setup_accessories_from_file( hass, "home_assistant_bridge_fan.json" ) - config_entry, pairing = await setup_test_accessories(hass, accessories) + await setup_test_accessories(hass, accessories) - entity_registry = er.async_get(hass) - - # Check that the fan is correctly found and set up - fan_id = "fan.living_room_fan" - fan = entity_registry.async_get(fan_id) - assert fan.unique_id == "homekit-fan.living_room_fan-8" - - fan_helper = Helper( + await assert_devices_and_entities_created( hass, - "fan.living_room_fan", - pairing, - accessories[0], - config_entry, + DeviceTestInfo( + unique_id="00:00:00:00:00:00", + name="Home Assistant Bridge", + model="Bridge", + manufacturer="Home Assistant", + sw_version="0.104.0.dev0", + hw_version="", + serial_number="homekit.bridge", + devices=[ + DeviceTestInfo( + name="Living Room Fan", + model="Fan", + manufacturer="Home Assistant", + sw_version="0.104.0.dev0", + hw_version="", + serial_number="fan.living_room_fan", + devices=[], + entities=[ + EntityTestInfo( + entity_id="fan.living_room_fan", + friendly_name="Living Room Fan", + unique_id="homekit-fan.living_room_fan-8", + supported_features=( + SUPPORT_DIRECTION + | SUPPORT_SET_SPEED + | SUPPORT_OSCILLATE + ), + capabilities={ + "preset_modes": None, + "speed_list": ["off", "low", "medium", "high"], + }, + state="off", + ) + ], + ), + ], + entities=[], + ), ) - - fan_state = await fan_helper.poll_and_get_state() - assert fan_state.attributes["friendly_name"] == "Living Room Fan" - assert fan_state.state == "off" - assert fan_state.attributes["supported_features"] == ( - SUPPORT_DIRECTION | SUPPORT_SET_SPEED | SUPPORT_OSCILLATE - ) - - device_registry = dr.async_get(hass) - - device = device_registry.async_get(fan.device_id) - assert device.manufacturer == "Home Assistant" - assert device.name == "Living Room Fan" - assert device.model == "Fan" - assert device.sw_version == "0.104.0.dev0" - - bridge = device = device_registry.async_get(device.via_device_id) - assert bridge.manufacturer == "Home Assistant" - assert bridge.name == "Home Assistant Bridge" - assert bridge.model == "Bridge" - assert bridge.sw_version == "0.104.0.dev0" diff --git a/tests/components/homekit_controller/specific_devices/test_hue_bridge.py b/tests/components/homekit_controller/specific_devices/test_hue_bridge.py index 5bc540a50a4..2a8855ac9da 100644 --- a/tests/components/homekit_controller/specific_devices/test_hue_bridge.py +++ b/tests/components/homekit_controller/specific_devices/test_hue_bridge.py @@ -1,11 +1,12 @@ """Tests for handling accessories on a Hue bridge via HomeKit.""" -from homeassistant.components.device_automation import DeviceAutomationType -from homeassistant.helpers import device_registry as dr, entity_registry as er +from homeassistant.const import PERCENTAGE -from tests.common import assert_lists_same, async_get_device_automations from tests.components.homekit_controller.common import ( - Helper, + DeviceTestInfo, + DeviceTriggerInfo, + EntityTestInfo, + assert_devices_and_entities_created, setup_accessories_from_file, setup_test_accessories, ) @@ -14,57 +15,44 @@ from tests.components.homekit_controller.common import ( async def test_hue_bridge_setup(hass): """Test that a Hue hub can be correctly setup in HA via HomeKit.""" accessories = await setup_accessories_from_file(hass, "hue_bridge.json") - config_entry, pairing = await setup_test_accessories(hass, accessories) + await setup_test_accessories(hass, accessories) - entity_registry = er.async_get(hass) - - # Check that the battery is correctly found and set up - battery_id = "sensor.hue_dimmer_switch_battery" - battery = entity_registry.async_get(battery_id) - assert battery.unique_id == "homekit-6623462389072572-644245094400" - - battery_helper = Helper( - hass, "sensor.hue_dimmer_switch_battery", pairing, accessories[0], config_entry + await assert_devices_and_entities_created( + hass, + DeviceTestInfo( + unique_id="00:00:00:00:00:00", + name="Philips hue - 482544", + model="BSB002", + manufacturer="Philips Lighting", + sw_version="1.32.1932126170", + hw_version="", + serial_number="123456", + devices=[ + DeviceTestInfo( + name="Hue dimmer switch", + model="RWL021", + manufacturer="Philips", + sw_version="45.1.17846", + hw_version="", + serial_number="6623462389072572", + devices=[], + entities=[ + EntityTestInfo( + entity_id="sensor.hue_dimmer_switch_battery", + friendly_name="Hue dimmer switch Battery", + unique_id="homekit-6623462389072572-644245094400", + unit_of_measurement=PERCENTAGE, + state="100", + ) + ], + stateless_triggers=[ + DeviceTriggerInfo(type="button1", subtype="single_press"), + DeviceTriggerInfo(type="button2", subtype="single_press"), + DeviceTriggerInfo(type="button3", subtype="single_press"), + DeviceTriggerInfo(type="button4", subtype="single_press"), + ], + ), + ], + entities=[], + ), ) - battery_state = await battery_helper.poll_and_get_state() - assert battery_state.attributes["friendly_name"] == "Hue dimmer switch Battery" - assert battery_state.attributes["icon"] == "mdi:battery" - assert battery_state.state == "100" - - device_registry = dr.async_get(hass) - - device = device_registry.async_get(battery.device_id) - assert device.manufacturer == "Philips" - assert device.name == "Hue dimmer switch" - assert device.model == "RWL021" - assert device.sw_version == "45.1.17846" - - # The fixture file has 1 dimmer, which is a remote with 4 buttons - # It (incorrectly) claims to support single, double and long press events - # It also has a battery - - expected = [ - { - "device_id": device.id, - "domain": "sensor", - "entity_id": "sensor.hue_dimmer_switch_battery", - "platform": "device", - "type": "battery_level", - } - ] - - for button in ("button1", "button2", "button3", "button4"): - expected.append( - { - "device_id": device.id, - "domain": "homekit_controller", - "platform": "device", - "type": button, - "subtype": "single_press", - } - ) - - triggers = await async_get_device_automations( - hass, DeviceAutomationType.TRIGGER, device.id - ) - assert_lists_same(triggers, expected) diff --git a/tests/components/homekit_controller/specific_devices/test_koogeek_ls1.py b/tests/components/homekit_controller/specific_devices/test_koogeek_ls1.py index 505ff2aacc7..ef655d79fdf 100644 --- a/tests/components/homekit_controller/specific_devices/test_koogeek_ls1.py +++ b/tests/components/homekit_controller/specific_devices/test_koogeek_ls1.py @@ -8,12 +8,14 @@ from aiohomekit.testing import FakePairing import pytest from homeassistant.components.light import SUPPORT_BRIGHTNESS, SUPPORT_COLOR -from homeassistant.helpers import device_registry as dr, entity_registry as er import homeassistant.util.dt as dt_util from tests.common import async_fire_time_changed from tests.components.homekit_controller.common import ( + DeviceTestInfo, + EntityTestInfo, Helper, + assert_devices_and_entities_created, setup_accessories_from_file, setup_test_accessories, ) @@ -24,35 +26,31 @@ LIGHT_ON = ("lightbulb", "on") async def test_koogeek_ls1_setup(hass): """Test that a Koogeek LS1 can be correctly setup in HA.""" accessories = await setup_accessories_from_file(hass, "koogeek_ls1.json") - config_entry, pairing = await setup_test_accessories(hass, accessories) + await setup_test_accessories(hass, accessories) - entity_registry = er.async_get(hass) - - # Assert that the entity is correctly added to the entity registry - entry = entity_registry.async_get("light.koogeek_ls1_20833f") - assert entry.unique_id == "homekit-AAAA011111111111-7" - - helper = Helper( - hass, "light.koogeek_ls1_20833f", pairing, accessories[0], config_entry + await assert_devices_and_entities_created( + hass, + DeviceTestInfo( + unique_id="00:00:00:00:00:00", + name="Koogeek-LS1-20833F", + model="LS1", + manufacturer="Koogeek", + sw_version="2.2.15", + hw_version="", + serial_number="AAAA011111111111", + devices=[], + entities=[ + EntityTestInfo( + entity_id="light.koogeek_ls1_20833f", + friendly_name="Koogeek-LS1-20833F", + unique_id="homekit-AAAA011111111111-7", + supported_features=SUPPORT_BRIGHTNESS | SUPPORT_COLOR, + capabilities={"supported_color_modes": ["hs"]}, + state="off", + ), + ], + ), ) - state = await helper.poll_and_get_state() - - # Assert that the friendly name is detected correctly - assert state.attributes["friendly_name"] == "Koogeek-LS1-20833F" - - # Assert that all optional features the LS1 supports are detected - assert state.attributes["supported_features"] == ( - SUPPORT_BRIGHTNESS | SUPPORT_COLOR - ) - - device_registry = dr.async_get(hass) - - device = device_registry.async_get(entry.device_id) - assert device.manufacturer == "Koogeek" - assert device.name == "Koogeek-LS1-20833F" - assert device.model == "LS1" - assert device.sw_version == "2.2.15" - assert device.via_device_id is None @pytest.mark.parametrize("failure_cls", [AccessoryDisconnectedError, EncryptionError]) diff --git a/tests/components/homekit_controller/specific_devices/test_koogeek_p1eu.py b/tests/components/homekit_controller/specific_devices/test_koogeek_p1eu.py index 1761edb3c8c..1065cfe2209 100644 --- a/tests/components/homekit_controller/specific_devices/test_koogeek_p1eu.py +++ b/tests/components/homekit_controller/specific_devices/test_koogeek_p1eu.py @@ -1,10 +1,12 @@ """Make sure that existing Koogeek P1EU support isn't broken.""" +from homeassistant.components.sensor import SensorStateClass from homeassistant.const import POWER_WATT -from homeassistant.helpers import device_registry as dr, entity_registry as er from tests.components.homekit_controller.common import ( - Helper, + DeviceTestInfo, + EntityTestInfo, + assert_devices_and_entities_created, setup_accessories_from_file, setup_test_accessories, ) @@ -13,43 +15,34 @@ from tests.components.homekit_controller.common import ( async def test_koogeek_p1eu_setup(hass): """Test that a Koogeek P1EU can be correctly setup in HA.""" accessories = await setup_accessories_from_file(hass, "koogeek_p1eu.json") - config_entry, pairing = await setup_test_accessories(hass, accessories) + await setup_test_accessories(hass, accessories) - entity_registry = er.async_get(hass) - device_registry = dr.async_get(hass) - - # Check that the switch entity is handled correctly - - entry = entity_registry.async_get("switch.koogeek_p1_a00aa0") - assert entry.unique_id == "homekit-EUCP03190xxxxx48-7" - - helper = Helper( - hass, "switch.koogeek_p1_a00aa0", pairing, accessories[0], config_entry - ) - state = await helper.poll_and_get_state() - assert state.attributes["friendly_name"] == "Koogeek-P1-A00AA0" - - device = device_registry.async_get(entry.device_id) - assert device.manufacturer == "Koogeek" - assert device.name == "Koogeek-P1-A00AA0" - assert device.model == "P1EU" - assert device.sw_version == "2.3.7" - assert device.via_device_id is None - - # Assert the power sensor is detected - entry = entity_registry.async_get("sensor.koogeek_p1_a00aa0_real_time_energy") - assert entry.unique_id == "homekit-EUCP03190xxxxx48-aid:1-sid:21-cid:22" - - helper = Helper( + await assert_devices_and_entities_created( hass, - "sensor.koogeek_p1_a00aa0_real_time_energy", - pairing, - accessories[0], - config_entry, + DeviceTestInfo( + unique_id="00:00:00:00:00:00", + name="Koogeek-P1-A00AA0", + model="P1EU", + manufacturer="Koogeek", + sw_version="2.3.7", + hw_version="", + serial_number="EUCP03190xxxxx48", + devices=[], + entities=[ + EntityTestInfo( + entity_id="switch.koogeek_p1_a00aa0", + friendly_name="Koogeek-P1-A00AA0", + unique_id="homekit-EUCP03190xxxxx48-7", + state="off", + ), + EntityTestInfo( + entity_id="sensor.koogeek_p1_a00aa0_real_time_energy", + friendly_name="Koogeek-P1-A00AA0 - Real Time Energy", + unique_id="homekit-EUCP03190xxxxx48-aid:1-sid:21-cid:22", + unit_of_measurement=POWER_WATT, + capabilities={"state_class": SensorStateClass.MEASUREMENT}, + state="5", + ), + ], + ), ) - state = await helper.poll_and_get_state() - assert state.attributes["friendly_name"] == "Koogeek-P1-A00AA0 - Real Time Energy" - assert state.attributes["unit_of_measurement"] == POWER_WATT - - # The sensor and switch should be part of the same device - assert entry.device_id == device.id diff --git a/tests/components/homekit_controller/specific_devices/test_koogeek_sw2.py b/tests/components/homekit_controller/specific_devices/test_koogeek_sw2.py index 768959e0331..7a94a6652b9 100644 --- a/tests/components/homekit_controller/specific_devices/test_koogeek_sw2.py +++ b/tests/components/homekit_controller/specific_devices/test_koogeek_sw2.py @@ -6,61 +6,49 @@ This Koogeek device has a custom power sensor that extra handling. It should have 2 entities - the actual switch and a sensor for power usage. """ +from homeassistant.components.sensor import SensorStateClass from homeassistant.const import POWER_WATT -from homeassistant.helpers import device_registry as dr, entity_registry as er from tests.components.homekit_controller.common import ( - Helper, + DeviceTestInfo, + EntityTestInfo, + assert_devices_and_entities_created, setup_accessories_from_file, setup_test_accessories, ) -async def test_koogeek_ls1_setup(hass): +async def test_koogeek_sw2_setup(hass): """Test that a Koogeek LS1 can be correctly setup in HA.""" accessories = await setup_accessories_from_file(hass, "koogeek_sw2.json") - config_entry, pairing = await setup_test_accessories(hass, accessories) + await setup_test_accessories(hass, accessories) - entity_registry = er.async_get(hass) - - # Assert that the switch entity is correctly added to the entity registry - entry = entity_registry.async_get("switch.koogeek_sw2_187a91") - assert entry.unique_id == "homekit-CNNT061751001372-8" - - helper = Helper( - hass, "switch.koogeek_sw2_187a91", pairing, accessories[0], config_entry - ) - state = await helper.poll_and_get_state() - - # Assert that the friendly name is detected correctly - assert state.attributes["friendly_name"] == "Koogeek-SW2-187A91" - - device_registry = dr.async_get(hass) - - device = device_registry.async_get(entry.device_id) - assert device.manufacturer == "Koogeek" - assert device.name == "Koogeek-SW2-187A91" - assert device.model == "KH02CN" - assert device.sw_version == "1.0.3" - assert device.via_device_id is None - - # Assert that the power sensor entity is correctly added to the entity registry - entry = entity_registry.async_get("sensor.koogeek_sw2_187a91_real_time_energy") - assert entry.unique_id == "homekit-CNNT061751001372-aid:1-sid:14-cid:18" - - helper = Helper( + await assert_devices_and_entities_created( hass, - "sensor.koogeek_sw2_187a91_real_time_energy", - pairing, - accessories[0], - config_entry, + DeviceTestInfo( + unique_id="00:00:00:00:00:00", + name="Koogeek-SW2-187A91", + model="KH02CN", + manufacturer="Koogeek", + sw_version="1.0.3", + hw_version="", + serial_number="CNNT061751001372", + devices=[], + entities=[ + EntityTestInfo( + entity_id="switch.koogeek_sw2_187a91", + friendly_name="Koogeek-SW2-187A91", + unique_id="homekit-CNNT061751001372-8", + state="off", + ), + EntityTestInfo( + entity_id="sensor.koogeek_sw2_187a91_real_time_energy", + friendly_name="Koogeek-SW2-187A91 - Real Time Energy", + unique_id="homekit-CNNT061751001372-aid:1-sid:14-cid:18", + unit_of_measurement=POWER_WATT, + capabilities={"state_class": SensorStateClass.MEASUREMENT}, + state="0", + ), + ], + ), ) - state = await helper.poll_and_get_state() - - # Assert that the friendly name is detected correctly - assert state.attributes["friendly_name"] == "Koogeek-SW2-187A91 - Real Time Energy" - assert state.attributes["unit_of_measurement"] == POWER_WATT - - device_registry = dr.async_get(hass) - - assert device.id == entry.device_id diff --git a/tests/components/homekit_controller/specific_devices/test_lennox_e30.py b/tests/components/homekit_controller/specific_devices/test_lennox_e30.py index cdab08039e1..979fbd48028 100644 --- a/tests/components/homekit_controller/specific_devices/test_lennox_e30.py +++ b/tests/components/homekit_controller/specific_devices/test_lennox_e30.py @@ -8,10 +8,11 @@ from homeassistant.components.climate.const import ( SUPPORT_TARGET_TEMPERATURE, SUPPORT_TARGET_TEMPERATURE_RANGE, ) -from homeassistant.helpers import device_registry as dr, entity_registry as er from tests.components.homekit_controller.common import ( - Helper, + DeviceTestInfo, + EntityTestInfo, + assert_devices_and_entities_created, setup_accessories_from_file, setup_test_accessories, ) @@ -20,30 +21,34 @@ from tests.components.homekit_controller.common import ( async def test_lennox_e30_setup(hass): """Test that a Lennox E30 can be correctly setup in HA.""" accessories = await setup_accessories_from_file(hass, "lennox_e30.json") - config_entry, pairing = await setup_test_accessories(hass, accessories) + await setup_test_accessories(hass, accessories) - entity_registry = er.async_get(hass) - - climate = entity_registry.async_get("climate.lennox") - assert climate.unique_id == "homekit-XXXXXXXX-100" - - climate_helper = Helper( - hass, "climate.lennox", pairing, accessories[0], config_entry + await assert_devices_and_entities_created( + hass, + DeviceTestInfo( + unique_id="00:00:00:00:00:00", + name="Lennox", + model="E30 2B", + manufacturer="Lennox", + sw_version="3.40.XX", + hw_version="3.0.XX", + serial_number="XXXXXXXX", + devices=[], + entities=[ + EntityTestInfo( + entity_id="climate.lennox", + friendly_name="Lennox", + unique_id="homekit-XXXXXXXX-100", + supported_features=( + SUPPORT_TARGET_TEMPERATURE | SUPPORT_TARGET_TEMPERATURE_RANGE + ), + capabilities={ + "hvac_modes": ["off", "heat", "cool", "heat_cool"], + "max_temp": 37, + "min_temp": 4.5, + }, + state="heat_cool", + ), + ], + ), ) - climate_state = await climate_helper.poll_and_get_state() - assert climate_state.attributes["friendly_name"] == "Lennox" - assert climate_state.attributes["supported_features"] == ( - SUPPORT_TARGET_TEMPERATURE | SUPPORT_TARGET_TEMPERATURE_RANGE - ) - - device_registry = dr.async_get(hass) - - device = device_registry.async_get(climate.device_id) - assert device.manufacturer == "Lennox" - assert device.name == "Lennox" - assert device.model == "E30 2B" - assert device.sw_version == "3.40.XX" - - # The fixture contains a single accessory - so its a single device - # and no bridge - assert device.via_device_id is None diff --git a/tests/components/homekit_controller/specific_devices/test_lg_tv.py b/tests/components/homekit_controller/specific_devices/test_lg_tv.py index 592ad2088b8..2841acac402 100644 --- a/tests/components/homekit_controller/specific_devices/test_lg_tv.py +++ b/tests/components/homekit_controller/specific_devices/test_lg_tv.py @@ -1,16 +1,15 @@ """Make sure that handling real world LG HomeKit characteristics isn't broken.""" -from homeassistant.components.device_automation import DeviceAutomationType from homeassistant.components.media_player.const import ( SUPPORT_PAUSE, SUPPORT_PLAY, SUPPORT_SELECT_SOURCE, ) -from homeassistant.helpers import device_registry as dr, entity_registry as er -from tests.common import async_get_device_automations from tests.components.homekit_controller.common import ( - Helper, + DeviceTestInfo, + EntityTestInfo, + assert_devices_and_entities_created, setup_accessories_from_file, setup_test_accessories, ) @@ -19,56 +18,47 @@ from tests.components.homekit_controller.common import ( async def test_lg_tv(hass): """Test that a Koogeek LS1 can be correctly setup in HA.""" accessories = await setup_accessories_from_file(hass, "lg_tv.json") - config_entry, pairing = await setup_test_accessories(hass, accessories) + await setup_test_accessories(hass, accessories) - entity_registry = er.async_get(hass) - - # Assert that the entity is correctly added to the entity registry - entry = entity_registry.async_get("media_player.lg_webos_tv_af80") - assert entry.unique_id == "homekit-999AAAAAA999-48" - - helper = Helper( - hass, "media_player.lg_webos_tv_af80", pairing, accessories[0], config_entry + await assert_devices_and_entities_created( + hass, + DeviceTestInfo( + unique_id="00:00:00:00:00:00", + name="LG webOS TV AF80", + model="OLED55B9PUA", + manufacturer="LG Electronics", + sw_version="04.71.04", + hw_version="1", + serial_number="999AAAAAA999", + devices=[], + entities=[ + EntityTestInfo( + entity_id="media_player.lg_webos_tv_af80", + friendly_name="LG webOS TV AF80", + unique_id="homekit-999AAAAAA999-48", + supported_features=( + SUPPORT_PAUSE | SUPPORT_PLAY | SUPPORT_SELECT_SOURCE + ), + capabilities={ + "source_list": [ + "AirPlay", + "Live TV", + "HDMI 1", + "Sony", + "Apple", + "AV", + "HDMI 4", + ] + }, + # The LG TV doesn't (at least at this patch level) report + # its media state via CURRENT_MEDIA_STATE. Therefore "ok" + # is the best we can say. + state="ok", + ), + ], + ), ) - state = await helper.poll_and_get_state() - # Assert that the friendly name is detected correctly - assert state.attributes["friendly_name"] == "LG webOS TV AF80" - - # Assert that all channels were found and that we know which is active. - assert state.attributes["source_list"] == [ - "AirPlay", - "Live TV", - "HDMI 1", - "Sony", - "Apple", - "AV", - "HDMI 4", - ] + """ assert state.attributes["source"] == "HDMI 4" - - # Assert that all optional features the LS1 supports are detected - assert state.attributes["supported_features"] == ( - SUPPORT_PAUSE | SUPPORT_PLAY | SUPPORT_SELECT_SOURCE - ) - - # The LG TV doesn't (at least at this patch level) report its media state via - # CURRENT_MEDIA_STATE. Therefore "ok" is the best we can say. - assert state.state == "ok" - - device_registry = dr.async_get(hass) - - device = device_registry.async_get(entry.device_id) - assert device.manufacturer == "LG Electronics" - assert device.name == "LG webOS TV AF80" - assert device.model == "OLED55B9PUA" - assert device.sw_version == "04.71.04" - assert device.via_device_id is None - assert device.hw_version == "1" - - # A TV has media player device triggers - triggers = await async_get_device_automations( - hass, DeviceAutomationType.TRIGGER, device.id - ) - for trigger in triggers: - assert trigger["domain"] == "media_player" + """ diff --git a/tests/components/homekit_controller/specific_devices/test_mysa_living.py b/tests/components/homekit_controller/specific_devices/test_mysa_living.py index ea1c1084071..e2fdb7b2a8f 100644 --- a/tests/components/homekit_controller/specific_devices/test_mysa_living.py +++ b/tests/components/homekit_controller/specific_devices/test_mysa_living.py @@ -1,9 +1,14 @@ """Make sure that Mysa Living is enumerated properly.""" -from homeassistant.helpers import device_registry as dr, entity_registry as er +from homeassistant.components.climate import SUPPORT_TARGET_TEMPERATURE +from homeassistant.components.light import SUPPORT_BRIGHTNESS +from homeassistant.components.sensor import SensorStateClass +from homeassistant.const import PERCENTAGE, TEMP_CELSIUS from tests.components.homekit_controller.common import ( - Helper, + DeviceTestInfo, + EntityTestInfo, + assert_devices_and_entities_created, setup_accessories_from_file, setup_test_accessories, ) @@ -12,80 +17,56 @@ from tests.components.homekit_controller.common import ( async def test_mysa_living_setup(hass): """Test that the accessory can be correctly setup in HA.""" accessories = await setup_accessories_from_file(hass, "mysa_living.json") - config_entry, pairing = await setup_test_accessories(hass, accessories) + await setup_test_accessories(hass, accessories) - entity_registry = er.async_get(hass) - device_registry = dr.async_get(hass) - - # Check that the switch entity is handled correctly - - entry = entity_registry.async_get("sensor.mysa_85dda9_current_humidity") - assert entry.unique_id == "homekit-AAAAAAA000-aid:1-sid:20-cid:27" - - helper = Helper( + await assert_devices_and_entities_created( hass, - "sensor.mysa_85dda9_current_humidity", - pairing, - accessories[0], - config_entry, + DeviceTestInfo( + unique_id="00:00:00:00:00:00", + name="Mysa-85dda9", + model="v1", + manufacturer="Empowered Homes Inc.", + sw_version="2.8.1", + hw_version="", + serial_number="AAAAAAA000", + devices=[], + entities=[ + EntityTestInfo( + entity_id="climate.mysa_85dda9", + friendly_name="Mysa-85dda9", + unique_id="homekit-AAAAAAA000-20", + supported_features=SUPPORT_TARGET_TEMPERATURE, + capabilities={ + "hvac_modes": ["off", "heat", "cool", "heat_cool"], + "max_temp": 35, + "min_temp": 7, + }, + state="off", + ), + EntityTestInfo( + entity_id="sensor.mysa_85dda9_current_humidity", + friendly_name="Mysa-85dda9 - Current Humidity", + unique_id="homekit-AAAAAAA000-aid:1-sid:20-cid:27", + unit_of_measurement=PERCENTAGE, + capabilities={"state_class": SensorStateClass.MEASUREMENT}, + state="40", + ), + EntityTestInfo( + entity_id="sensor.mysa_85dda9_current_temperature", + friendly_name="Mysa-85dda9 - Current Temperature", + unique_id="homekit-AAAAAAA000-aid:1-sid:20-cid:25", + unit_of_measurement=TEMP_CELSIUS, + capabilities={"state_class": SensorStateClass.MEASUREMENT}, + state="24.1", + ), + EntityTestInfo( + entity_id="light.mysa_85dda9", + friendly_name="Mysa-85dda9", + unique_id="homekit-AAAAAAA000-40", + supported_features=SUPPORT_BRIGHTNESS, + capabilities={"supported_color_modes": ["brightness"]}, + state="off", + ), + ], + ), ) - state = await helper.poll_and_get_state() - assert state.attributes["friendly_name"] == "Mysa-85dda9 - Current Humidity" - - device = device_registry.async_get(entry.device_id) - assert device.manufacturer == "Empowered Homes Inc." - assert device.name == "Mysa-85dda9" - assert device.model == "v1" - assert device.sw_version == "2.8.1" - assert device.via_device_id is None - - # Assert the humidifier is detected - entry = entity_registry.async_get("sensor.mysa_85dda9_current_temperature") - assert entry.unique_id == "homekit-AAAAAAA000-aid:1-sid:20-cid:25" - - helper = Helper( - hass, - "sensor.mysa_85dda9_current_temperature", - pairing, - accessories[0], - config_entry, - ) - state = await helper.poll_and_get_state() - assert state.attributes["friendly_name"] == "Mysa-85dda9 - Current Temperature" - - # The sensor should be part of the same device - assert entry.device_id == device.id - - # Assert the light is detected - entry = entity_registry.async_get("light.mysa_85dda9") - assert entry.unique_id == "homekit-AAAAAAA000-40" - - helper = Helper( - hass, - "light.mysa_85dda9", - pairing, - accessories[0], - config_entry, - ) - state = await helper.poll_and_get_state() - assert state.attributes["friendly_name"] == "Mysa-85dda9" - - # The light should be part of the same device - assert entry.device_id == device.id - - # Assert the climate entity is detected - entry = entity_registry.async_get("climate.mysa_85dda9") - assert entry.unique_id == "homekit-AAAAAAA000-20" - - helper = Helper( - hass, - "climate.mysa_85dda9", - pairing, - accessories[0], - config_entry, - ) - state = await helper.poll_and_get_state() - assert state.attributes["friendly_name"] == "Mysa-85dda9" - - # The light should be part of the same device - assert entry.device_id == device.id diff --git a/tests/components/homekit_controller/specific_devices/test_netamo_doorbell.py b/tests/components/homekit_controller/specific_devices/test_netamo_doorbell.py index d213e72c59c..969f03cdeb8 100644 --- a/tests/components/homekit_controller/specific_devices/test_netamo_doorbell.py +++ b/tests/components/homekit_controller/specific_devices/test_netamo_doorbell.py @@ -4,12 +4,11 @@ Regression tests for Netamo Doorbell. https://github.com/home-assistant/core/issues/44596 """ -from homeassistant.components.device_automation import DeviceAutomationType -from homeassistant.helpers import device_registry as dr, entity_registry as er - -from tests.common import assert_lists_same, async_get_device_automations from tests.components.homekit_controller.common import ( - Helper, + DeviceTestInfo, + DeviceTriggerInfo, + EntityTestInfo, + assert_devices_and_entities_created, setup_accessories_from_file, setup_test_accessories, ) @@ -18,59 +17,31 @@ from tests.components.homekit_controller.common import ( async def test_netamo_doorbell_setup(hass): """Test that a Netamo Doorbell can be correctly setup in HA.""" accessories = await setup_accessories_from_file(hass, "netamo_doorbell.json") - config_entry, pairing = await setup_test_accessories(hass, accessories) + await setup_test_accessories(hass, accessories) - entity_registry = er.async_get(hass) - - # Check that the camera is correctly found and set up - doorbell_id = "camera.netatmo_doorbell_g738658" - doorbell = entity_registry.async_get(doorbell_id) - assert doorbell.unique_id == "homekit-g738658-aid:1" - - camera_helper = Helper( + await assert_devices_and_entities_created( hass, - "camera.netatmo_doorbell_g738658", - pairing, - accessories[0], - config_entry, + DeviceTestInfo( + unique_id="00:00:00:00:00:00", + name="Netatmo-Doorbell-g738658", + model="Netatmo Doorbell", + manufacturer="Netatmo", + sw_version="80.0.0", + hw_version="", + serial_number="g738658", + devices=[], + entities=[ + EntityTestInfo( + entity_id="camera.netatmo_doorbell_g738658", + friendly_name="Netatmo-Doorbell-g738658", + unique_id="homekit-g738658-aid:1", + state="idle", + ), + ], + stateless_triggers=[ + DeviceTriggerInfo(type="doorbell", subtype="single_press"), + DeviceTriggerInfo(type="doorbell", subtype="double_press"), + DeviceTriggerInfo(type="doorbell", subtype="long_press"), + ], + ), ) - camera_helper = await camera_helper.poll_and_get_state() - assert camera_helper.attributes["friendly_name"] == "Netatmo-Doorbell-g738658" - - device_registry = dr.async_get(hass) - - device = device_registry.async_get(doorbell.device_id) - assert device.manufacturer == "Netatmo" - assert device.name == "Netatmo-Doorbell-g738658" - assert device.model == "Netatmo Doorbell" - assert device.sw_version == "80.0.0" - assert device.via_device_id is None - - # The fixture file has 1 button - expected = [] - for subtype in ("single_press", "double_press", "long_press"): - expected.append( - { - "device_id": doorbell.device_id, - "domain": "homekit_controller", - "platform": "device", - "type": "doorbell", - "subtype": subtype, - } - ) - - for type in ("no_motion", "motion"): - expected.append( - { - "device_id": doorbell.device_id, - "domain": "binary_sensor", - "entity_id": "binary_sensor.netatmo_doorbell_g738658", - "platform": "device", - "type": type, - } - ) - - triggers = await async_get_device_automations( - hass, DeviceAutomationType.TRIGGER, doorbell.device_id - ) - assert_lists_same(triggers, expected) diff --git a/tests/components/homekit_controller/specific_devices/test_rainmachine_pro_8.py b/tests/components/homekit_controller/specific_devices/test_rainmachine_pro_8.py index ee008fbfa62..5b29c2d52e7 100644 --- a/tests/components/homekit_controller/specific_devices/test_rainmachine_pro_8.py +++ b/tests/components/homekit_controller/specific_devices/test_rainmachine_pro_8.py @@ -4,10 +4,10 @@ Make sure that existing RainMachine support isn't broken. https://github.com/home-assistant/core/issues/31745 """ -from homeassistant.helpers import device_registry as dr, entity_registry as er - from tests.components.homekit_controller.common import ( - Helper, + DeviceTestInfo, + EntityTestInfo, + assert_devices_and_entities_created, setup_accessories_from_file, setup_test_accessories, ) @@ -16,53 +16,68 @@ from tests.components.homekit_controller.common import ( async def test_rainmachine_pro_8_setup(hass): """Test that a RainMachine can be correctly setup in HA.""" accessories = await setup_accessories_from_file(hass, "rainmachine-pro-8.json") - config_entry, pairing = await setup_test_accessories(hass, accessories) + await setup_test_accessories(hass, accessories) - entity_registry = er.async_get(hass) - - # Assert that the entity is correctly added to the entity registry - entry = entity_registry.async_get("switch.rainmachine_00ce4a") - assert entry.unique_id == "homekit-00aa0000aa0a-512" - - helper = Helper( - hass, "switch.rainmachine_00ce4a", pairing, accessories[0], config_entry + await assert_devices_and_entities_created( + hass, + DeviceTestInfo( + unique_id="00:00:00:00:00:00", + name="RainMachine-00ce4a", + model="SPK5 Pro", + manufacturer="Green Electronics LLC", + sw_version="1.0.4", + hw_version="1", + serial_number="00aa0000aa0a", + devices=[], + entities=[ + EntityTestInfo( + entity_id="switch.rainmachine_00ce4a", + friendly_name="RainMachine-00ce4a", + unique_id="homekit-00aa0000aa0a-512", + state="off", + ), + EntityTestInfo( + entity_id="switch.rainmachine_00ce4a_2", + friendly_name="RainMachine-00ce4a", + unique_id="homekit-00aa0000aa0a-768", + state="off", + ), + EntityTestInfo( + entity_id="switch.rainmachine_00ce4a_3", + friendly_name="RainMachine-00ce4a", + unique_id="homekit-00aa0000aa0a-1024", + state="off", + ), + EntityTestInfo( + entity_id="switch.rainmachine_00ce4a_4", + friendly_name="RainMachine-00ce4a", + unique_id="homekit-00aa0000aa0a-1280", + state="off", + ), + EntityTestInfo( + entity_id="switch.rainmachine_00ce4a_5", + friendly_name="RainMachine-00ce4a", + unique_id="homekit-00aa0000aa0a-1536", + state="off", + ), + EntityTestInfo( + entity_id="switch.rainmachine_00ce4a_6", + friendly_name="RainMachine-00ce4a", + unique_id="homekit-00aa0000aa0a-1792", + state="off", + ), + EntityTestInfo( + entity_id="switch.rainmachine_00ce4a_7", + friendly_name="RainMachine-00ce4a", + unique_id="homekit-00aa0000aa0a-2048", + state="off", + ), + EntityTestInfo( + entity_id="switch.rainmachine_00ce4a_8", + friendly_name="RainMachine-00ce4a", + unique_id="homekit-00aa0000aa0a-2304", + state="off", + ), + ], + ), ) - state = await helper.poll_and_get_state() - - # Assert that the friendly name is detected correctly - assert state.attributes["friendly_name"] == "RainMachine-00ce4a" - - device_registry = dr.async_get(hass) - - device = device_registry.async_get(entry.device_id) - assert device.manufacturer == "Green Electronics LLC" - assert device.name == "RainMachine-00ce4a" - assert device.model == "SPK5 Pro" - assert device.sw_version == "1.0.4" - assert device.via_device_id is None - assert device.hw_version == "1" - - # The device is made up of multiple valves - make sure we have enumerated them all - entry = entity_registry.async_get("switch.rainmachine_00ce4a_2") - assert entry.unique_id == "homekit-00aa0000aa0a-768" - - entry = entity_registry.async_get("switch.rainmachine_00ce4a_3") - assert entry.unique_id == "homekit-00aa0000aa0a-1024" - - entry = entity_registry.async_get("switch.rainmachine_00ce4a_4") - assert entry.unique_id == "homekit-00aa0000aa0a-1280" - - entry = entity_registry.async_get("switch.rainmachine_00ce4a_5") - assert entry.unique_id == "homekit-00aa0000aa0a-1536" - - entry = entity_registry.async_get("switch.rainmachine_00ce4a_6") - assert entry.unique_id == "homekit-00aa0000aa0a-1792" - - entry = entity_registry.async_get("switch.rainmachine_00ce4a_7") - assert entry.unique_id == "homekit-00aa0000aa0a-2048" - - entry = entity_registry.async_get("switch.rainmachine_00ce4a_8") - assert entry.unique_id == "homekit-00aa0000aa0a-2304" - - entry = entity_registry.async_get("switch.rainmachine_00ce4a_9") - assert entry is None diff --git a/tests/components/homekit_controller/specific_devices/test_ryse_smart_bridge.py b/tests/components/homekit_controller/specific_devices/test_ryse_smart_bridge.py index bc1eb76af85..54393d1ac4f 100644 --- a/tests/components/homekit_controller/specific_devices/test_ryse_smart_bridge.py +++ b/tests/components/homekit_controller/specific_devices/test_ryse_smart_bridge.py @@ -5,6 +5,7 @@ from homeassistant.components.cover import ( SUPPORT_OPEN, SUPPORT_SET_POSITION, ) +from homeassistant.const import PERCENTAGE from tests.components.homekit_controller.common import ( DeviceTestInfo, @@ -22,7 +23,7 @@ async def test_ryse_smart_bridge_setup(hass): accessories = await setup_accessories_from_file(hass, "ryse_smart_bridge.json") await setup_test_accessories(hass, accessories) - assert_devices_and_entities_created( + await assert_devices_and_entities_created( hass, DeviceTestInfo( unique_id="00:00:00:00:00:00", @@ -55,6 +56,7 @@ async def test_ryse_smart_bridge_setup(hass): entity_id="sensor.master_bath_south_battery", friendly_name="Master Bath South Battery", unique_id="homekit-00:00:00:00:00:00-2-64", + unit_of_measurement=PERCENTAGE, state="100", ), ], @@ -80,6 +82,7 @@ async def test_ryse_smart_bridge_setup(hass): entity_id="sensor.ryse_smartshade_battery", friendly_name="RYSE SmartShade Battery", unique_id="homekit-00:00:00:00:00:00-3-64", + unit_of_measurement=PERCENTAGE, state="100", ), ], @@ -97,7 +100,7 @@ async def test_ryse_smart_bridge_four_shades_setup(hass): ) await setup_test_accessories(hass, accessories) - assert_devices_and_entities_created( + await assert_devices_and_entities_created( hass, DeviceTestInfo( unique_id="00:00:00:00:00:00", @@ -130,6 +133,7 @@ async def test_ryse_smart_bridge_four_shades_setup(hass): entity_id="sensor.lr_left_battery", friendly_name="LR Left Battery", unique_id="homekit-00:00:00:00:00:00-2-64", + unit_of_measurement=PERCENTAGE, state="89", ), ], @@ -155,6 +159,7 @@ async def test_ryse_smart_bridge_four_shades_setup(hass): entity_id="sensor.lr_right_battery", friendly_name="LR Right Battery", unique_id="homekit-00:00:00:00:00:00-3-64", + unit_of_measurement=PERCENTAGE, state="100", ), ], @@ -180,6 +185,7 @@ async def test_ryse_smart_bridge_four_shades_setup(hass): entity_id="sensor.br_left_battery", friendly_name="BR Left Battery", unique_id="homekit-00:00:00:00:00:00-4-64", + unit_of_measurement=PERCENTAGE, state="100", ), ], @@ -205,6 +211,7 @@ async def test_ryse_smart_bridge_four_shades_setup(hass): entity_id="sensor.rzss_battery", friendly_name="RZSS Battery", unique_id="homekit-00:00:00:00:00:00-5-64", + unit_of_measurement=PERCENTAGE, state="0", ), ], diff --git a/tests/components/homekit_controller/specific_devices/test_simpleconnect_fan.py b/tests/components/homekit_controller/specific_devices/test_simpleconnect_fan.py index 4bc564033fc..1df0a0192db 100644 --- a/tests/components/homekit_controller/specific_devices/test_simpleconnect_fan.py +++ b/tests/components/homekit_controller/specific_devices/test_simpleconnect_fan.py @@ -20,7 +20,7 @@ async def test_simpleconnect_fan_setup(hass): accessories = await setup_accessories_from_file(hass, "simpleconnect_fan.json") await setup_test_accessories(hass, accessories) - assert_devices_and_entities_created( + await assert_devices_and_entities_created( hass, DeviceTestInfo( unique_id="00:00:00:00:00:00", @@ -37,6 +37,10 @@ async def test_simpleconnect_fan_setup(hass): friendly_name="SIMPLEconnect Fan-06F674", unique_id="homekit-1234567890abcd-8", supported_features=SUPPORT_DIRECTION | SUPPORT_SET_SPEED, + capabilities={ + "preset_modes": None, + "speed_list": ["off", "low", "medium", "high"], + }, state="off", ), ], diff --git a/tests/components/homekit_controller/specific_devices/test_velux_gateway.py b/tests/components/homekit_controller/specific_devices/test_velux_gateway.py index 5bb947ae894..d6b9fe9cfbf 100644 --- a/tests/components/homekit_controller/specific_devices/test_velux_gateway.py +++ b/tests/components/homekit_controller/specific_devices/test_velux_gateway.py @@ -9,6 +9,11 @@ from homeassistant.components.cover import ( SUPPORT_OPEN, SUPPORT_SET_POSITION, ) +from homeassistant.const import ( + CONCENTRATION_PARTS_PER_MILLION, + PERCENTAGE, + TEMP_CELSIUS, +) from tests.components.homekit_controller.common import ( DeviceTestInfo, @@ -24,7 +29,7 @@ async def test_velux_cover_setup(hass): accessories = await setup_accessories_from_file(hass, "velux_gateway.json") await setup_test_accessories(hass, accessories) - assert_devices_and_entities_created( + await assert_devices_and_entities_created( hass, DeviceTestInfo( unique_id="00:00:00:00:00:00", @@ -36,7 +41,6 @@ async def test_velux_cover_setup(hass): serial_number="a1a11a1", devices=[ DeviceTestInfo( - unique_id="00:00:00:00:00:00-1", name="VELUX Window", model="VELUX Window", manufacturer="VELUX", @@ -57,7 +61,6 @@ async def test_velux_cover_setup(hass): ], ), DeviceTestInfo( - unique_id="00:00:00:00:00:00-2", name="VELUX Sensor", model="VELUX Sensor", manufacturer="VELUX", @@ -70,18 +73,21 @@ async def test_velux_cover_setup(hass): entity_id="sensor.velux_sensor_temperature", friendly_name="VELUX Sensor Temperature", unique_id="homekit-a11b111-8", + unit_of_measurement=TEMP_CELSIUS, state="18.9", ), EntityTestInfo( entity_id="sensor.velux_sensor_humidity", friendly_name="VELUX Sensor Humidity", unique_id="homekit-a11b111-11", + unit_of_measurement=PERCENTAGE, state="58", ), EntityTestInfo( entity_id="sensor.velux_sensor_co2", friendly_name="VELUX Sensor CO2", unique_id="homekit-a11b111-14", + unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION, state="400", ), ], diff --git a/tests/components/homekit_controller/specific_devices/test_vocolinc_flowerbud.py b/tests/components/homekit_controller/specific_devices/test_vocolinc_flowerbud.py index 69b4b73fab3..3680437ada6 100644 --- a/tests/components/homekit_controller/specific_devices/test_vocolinc_flowerbud.py +++ b/tests/components/homekit_controller/specific_devices/test_vocolinc_flowerbud.py @@ -2,6 +2,10 @@ from homeassistant.components.humidifier.const import SUPPORT_MODES from homeassistant.components.light import SUPPORT_BRIGHTNESS, SUPPORT_COLOR +from homeassistant.components.number import NumberMode +from homeassistant.components.sensor import SensorStateClass +from homeassistant.const import PERCENTAGE +from homeassistant.helpers.entity import EntityCategory from tests.components.homekit_controller.common import ( DeviceTestInfo, @@ -17,7 +21,7 @@ async def test_vocolinc_flowerbud_setup(hass): accessories = await setup_accessories_from_file(hass, "vocolinc_flowerbud.json") await setup_test_accessories(hass, accessories) - assert_devices_and_entities_created( + await assert_devices_and_entities_created( hass, DeviceTestInfo( unique_id="00:00:00:00:00:00", @@ -34,6 +38,11 @@ async def test_vocolinc_flowerbud_setup(hass): friendly_name="VOCOlinc-Flowerbud-0d324b", unique_id="homekit-AM01121849000327-30", supported_features=SUPPORT_MODES, + capabilities={ + "available_modes": ["normal", "auto"], + "max_humidity": 100.0, + "min_humidity": 0.0, + }, state="off", ), EntityTestInfo( @@ -41,18 +50,28 @@ async def test_vocolinc_flowerbud_setup(hass): friendly_name="VOCOlinc-Flowerbud-0d324b", unique_id="homekit-AM01121849000327-9", supported_features=SUPPORT_BRIGHTNESS | SUPPORT_COLOR, + capabilities={"supported_color_modes": ["hs"]}, state="on", ), EntityTestInfo( entity_id="number.vocolinc_flowerbud_0d324b_spray_quantity", friendly_name="VOCOlinc-Flowerbud-0d324b Spray Quantity", unique_id="homekit-AM01121849000327-aid:1-sid:30-cid:38", + capabilities={ + "max": 5, + "min": 1, + "mode": NumberMode.AUTO, + "step": 1, + }, state="5", + entity_category=EntityCategory.CONFIG, ), EntityTestInfo( entity_id="sensor.vocolinc_flowerbud_0d324b_current_humidity", friendly_name="VOCOlinc-Flowerbud-0d324b - Current Humidity", unique_id="homekit-AM01121849000327-aid:1-sid:30-cid:33", + capabilities={"state_class": SensorStateClass.MEASUREMENT}, + unit_of_measurement=PERCENTAGE, state="45.0", ), ],