core/tests/components/homematicip_cloud/helper.py

217 lines
7.0 KiB
Python

"""Helper for HomematicIP Cloud Tests."""
import json
from asynctest import Mock, patch
from homematicip.aio.class_maps import (
TYPE_CLASS_MAP,
TYPE_GROUP_MAP,
TYPE_SECURITY_EVENT_MAP,
)
from homematicip.aio.device import AsyncDevice
from homematicip.aio.group import AsyncGroup
from homematicip.aio.home import AsyncHome
from homematicip.home import Home
from homeassistant import config_entries
from homeassistant.components.homematicip_cloud import DOMAIN as HMIPC_DOMAIN
from homeassistant.components.homematicip_cloud.device import (
ATTR_IS_GROUP,
ATTR_MODEL_TYPE,
)
from homeassistant.components.homematicip_cloud.hap import HomematicipHAP
from homeassistant.helpers.typing import HomeAssistantType
from homeassistant.setup import async_setup_component
from tests.common import load_fixture
HAPID = "3014F7110000000000000001"
HAPPIN = "5678"
AUTH_TOKEN = "1234"
HOME_JSON = "homematicip_cloud.json"
FIXTURE_DATA = load_fixture(HOME_JSON)
def get_and_check_entity_basics(hass, mock_hap, entity_id, entity_name, device_model):
"""Get and test basic device."""
ha_state = hass.states.get(entity_id)
assert ha_state is not None
if device_model:
assert ha_state.attributes[ATTR_MODEL_TYPE] == device_model
assert ha_state.name == entity_name
hmip_device = mock_hap.hmip_device_by_entity_id.get(entity_id)
if hmip_device:
if isinstance(hmip_device, AsyncDevice):
assert ha_state.attributes[ATTR_IS_GROUP] is False
elif isinstance(hmip_device, AsyncGroup):
assert ha_state.attributes[ATTR_IS_GROUP]
return ha_state, hmip_device
async def async_manipulate_test_data(
hass, hmip_device, attribute, new_value, channel=1, fire_device=None
):
"""Set new value on hmip device."""
if channel == 1:
setattr(hmip_device, attribute, new_value)
if hasattr(hmip_device, "functionalChannels"):
functional_channel = hmip_device.functionalChannels[channel]
setattr(functional_channel, attribute, new_value)
fire_target = hmip_device if fire_device is None else fire_device
if isinstance(fire_target, AsyncHome):
fire_target.fire_update_event(
fire_target._rawJSONData # pylint: disable=protected-access
)
else:
fire_target.fire_update_event()
await hass.async_block_till_done()
class HomeFactory:
"""Factory to create a HomematicIP Cloud Home."""
def __init__(
self,
hass: HomeAssistantType,
mock_connection,
hmip_config_entry: config_entries.ConfigEntry,
):
"""Initialize the Factory."""
self.hass = hass
self.mock_connection = mock_connection
self.hmip_config_entry = hmip_config_entry
async def async_get_mock_hap(
self, test_devices=[], test_groups=[]
) -> HomematicipHAP:
"""Create a mocked homematic access point."""
home_name = self.hmip_config_entry.data["name"]
mock_home = (
HomeTemplate(
connection=self.mock_connection,
home_name=home_name,
test_devices=test_devices,
test_groups=test_groups,
)
.init_home()
.get_async_home_mock()
)
self.hmip_config_entry.add_to_hass(self.hass)
with patch(
"homeassistant.components.homematicip_cloud.hap.HomematicipHAP.get_hap",
return_value=mock_home,
):
assert await async_setup_component(self.hass, HMIPC_DOMAIN, {})
await self.hass.async_block_till_done()
hap = self.hass.data[HMIPC_DOMAIN][HAPID]
mock_home.on_update(hap.async_update)
mock_home.on_create(hap.async_create_entity)
return hap
class HomeTemplate(Home):
"""
Home template as builder for home mock.
It is based on the upstream libs home class to generate hmip devices
and groups based on the given homematicip_cloud.json.
All further testing activities should be done by using the AsyncHome mock,
that is generated by get_async_home_mock(self).
The class also generated mocks of devices and groups for further testing.
"""
_typeClassMap = TYPE_CLASS_MAP
_typeGroupMap = TYPE_GROUP_MAP
_typeSecurityEventMap = TYPE_SECURITY_EVENT_MAP
def __init__(self, connection=None, home_name="", test_devices=[], test_groups=[]):
"""Init template with connection."""
super().__init__(connection=connection)
self.label = "Access Point"
self.name = home_name
self.model_type = "HmIP-HAP"
self.init_json_state = None
self.test_devices = test_devices
self.test_groups = test_groups
def _cleanup_json(self, json):
if self.test_devices is not None:
new_devices = {}
for json_device in json["devices"].items():
if json_device[1]["label"] in self.test_devices:
new_devices.update([json_device])
json["devices"] = new_devices
if self.test_groups is not None:
new_groups = {}
for json_group in json["groups"].items():
if json_group[1]["label"] in self.test_groups:
new_groups.update([json_group])
json["groups"] = new_groups
return json
def init_home(self):
"""Init template with json."""
self.init_json_state = self._cleanup_json(json.loads(FIXTURE_DATA))
self.update_home(json_state=self.init_json_state, clearConfig=True)
return self
def update_home(self, json_state, clearConfig: bool = False):
"""Update home and ensure that mocks are created."""
result = super().update_home(json_state, clearConfig)
self._generate_mocks()
return result
def _generate_mocks(self):
"""Generate mocks for groups and devices."""
mock_devices = []
for device in self.devices:
mock_devices.append(_get_mock(device))
self.devices = mock_devices
mock_groups = []
for group in self.groups:
mock_groups.append(_get_mock(group))
self.groups = mock_groups
def download_configuration(self):
"""Return the initial json config."""
return self.init_json_state
def get_async_home_mock(self):
"""
Create Mock for Async_Home. based on template to be used for testing.
It adds collections of mocked devices and groups to the home objects,
and sets required attributes.
"""
mock_home = Mock(
spec=AsyncHome, wraps=self, label="Access Point", modelType="HmIP-HAP"
)
mock_home.__dict__.update(self.__dict__)
return mock_home
def _get_mock(instance):
"""Create a mock and copy instance attributes over mock."""
if isinstance(instance, Mock):
instance.__dict__.update(
instance._mock_wraps.__dict__ # pylint: disable=protected-access
)
return instance
mock = Mock(spec=instance, wraps=instance)
mock.__dict__.update(instance.__dict__)
return mock