Refactor homekit_controller tests to reduce duplication. (#64198)
This commit is contained in:
parent
187b4fad84
commit
99481e2258
5 changed files with 435 additions and 290 deletions
|
@ -1,6 +1,10 @@
|
|||
"""Code to support homekit_controller tests."""
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
from unittest import mock
|
||||
|
||||
|
@ -15,12 +19,45 @@ from homeassistant.components.homekit_controller.const import (
|
|||
CONTROLLER,
|
||||
DOMAIN,
|
||||
HOMEKIT_ACCESSORY_DISPATCH,
|
||||
IDENTIFIER_ACCESSORY_ID,
|
||||
IDENTIFIER_SERIAL_NUMBER,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||
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
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@dataclass
|
||||
class EntityTestInfo:
|
||||
"""Describes how we expected an entity to be created by homekit_controller."""
|
||||
|
||||
entity_id: str
|
||||
unique_id: str
|
||||
friendly_name: str
|
||||
state: str
|
||||
supported_features: int = 0
|
||||
|
||||
|
||||
@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]
|
||||
|
||||
|
||||
class Helper:
|
||||
"""Helper methods for interacting with HomeKit fakes."""
|
||||
|
@ -171,3 +208,73 @@ async def setup_test_component(hass, setup_accessory, capitalize=False, suffix=N
|
|||
config_entry, pairing = await setup_test_accessories(hass, [accessory])
|
||||
entity = "testdevice" if suffix is None else f"testdevice_{suffix}"
|
||||
return Helper(hass, ".".join((domain, entity)), pairing, accessory, config_entry)
|
||||
|
||||
|
||||
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:
|
||||
# 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)
|
||||
|
||||
# There are currently really 3 cases here:
|
||||
# - We can match exactly one device by serial number. This won't work for devices like the Ryse.
|
||||
# These have nlank or broken serial numbers.
|
||||
# - The device unique id is "00:00:00:00:00:00" - this is the pairing id. This is only set for
|
||||
# the root (bridge) device.
|
||||
# - The device unique id is "00:00:00:00:00:00-X", where X is a HAP aid. This is only set when
|
||||
# we have detected broken serial numbers (and serial number is not used as an identifier).
|
||||
|
||||
device = device_registry.async_get_device(
|
||||
{
|
||||
(DOMAIN, IDENTIFIER_SERIAL_NUMBER, expected.serial_number),
|
||||
(DOMAIN, IDENTIFIER_ACCESSORY_ID, expected.unique_id),
|
||||
}
|
||||
)
|
||||
|
||||
logger.debug("Comparing device %r to %r", device, expected)
|
||||
|
||||
assert device
|
||||
assert device.name == expected.name
|
||||
assert device.model == expected.model
|
||||
assert device.manufacturer == expected.manufacturer
|
||||
assert device.hw_version == expected.hw_version
|
||||
assert device.sw_version == expected.sw_version
|
||||
|
||||
# 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.
|
||||
for _, key, value in device.identifiers:
|
||||
if key == IDENTIFIER_SERIAL_NUMBER:
|
||||
assert value == expected.serial_number
|
||||
elif key == IDENTIFIER_ACCESSORY_ID:
|
||||
assert value == expected.unique_id
|
||||
|
||||
for entity_info in expected.entities:
|
||||
entity = entity_registry.async_get(entity_info.entity_id)
|
||||
logger.debug("Comparing entity %r to %r", entity, entity_info)
|
||||
|
||||
assert entity
|
||||
assert entity.device_id == device.id
|
||||
assert entity.unique_id == entity_info.unique_id
|
||||
assert entity.supported_features == entity_info.supported_features
|
||||
|
||||
state = hass.states.get(entity_info.entity_id)
|
||||
logger.debug("Comparing state %r to %r", state, entity_info)
|
||||
|
||||
assert state is not None
|
||||
assert state.state == entity_info.state
|
||||
assert state.attributes["friendly_name"] == entity_info.friendly_name
|
||||
|
||||
for child in expected.devices:
|
||||
child_device = _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 must not have a via, otherwise its not the device
|
||||
assert root_device.via_device_id is None
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue