"""Test configuration and mocks for LCN component.""" import json from typing import Any from unittest.mock import AsyncMock, Mock, patch import pypck from pypck import lcn_defs from pypck.device import DeviceConnection, Serials import pytest from homeassistant.components.lcn import PchkConnectionManager from homeassistant.components.lcn.config_flow import LcnFlowHandler from homeassistant.components.lcn.const import DOMAIN from homeassistant.components.lcn.helpers import AddressType, generate_unique_id from homeassistant.const import CONF_ADDRESS, CONF_DEVICES, CONF_ENTITIES, CONF_HOST from homeassistant.core import HomeAssistant from homeassistant.helpers import device_registry as dr from tests.common import MockConfigEntry, load_fixture LATEST_CONFIG_ENTRY_VERSION = (LcnFlowHandler.VERSION, LcnFlowHandler.MINOR_VERSION) class MockDeviceConnection(DeviceConnection): """Fake a LCN module connection.""" request_name = AsyncMock(return_value="TestModule") request_serials = AsyncMock( return_value=Serials( hardware_serial=0x1A20A1234, manu=0x01, software_serial=0x190B11, hardware_type=lcn_defs.HardwareType.UPP, ) ) send_command = AsyncMock(return_value=True) request_status_output = AsyncMock() request_status_relays = AsyncMock() request_status_motor_position = AsyncMock() request_status_binary_sensors = AsyncMock() request_status_variable = AsyncMock() request_status_led_and_logic_ops = AsyncMock() request_status_locked_keys = AsyncMock() def __init__(self, *args: Any, **kwargs: Any) -> None: """Construct ModuleConnection instance.""" super().__init__(*args, **kwargs) self._serials_known.set() class MockPchkConnectionManager(PchkConnectionManager): """Fake connection handler.""" async def async_connect(self, timeout: int = 30) -> None: """Mock establishing a connection to PCHK.""" self.authentication_completed_future.set_result(True) self.license_error_future.set_result(True) self.segment_scan_completed_event.set() async def async_close(self) -> None: """Mock closing a connection to PCHK.""" @patch.object(pypck.connection, "DeviceConnection", MockDeviceConnection) def get_device_connection(self, addr): """Get LCN device connection.""" return super().get_device_connection(addr) scan_modules = AsyncMock() send_command = AsyncMock() def create_config_entry( name: str, version: tuple[int, int] = LATEST_CONFIG_ENTRY_VERSION ) -> MockConfigEntry: """Set up config entries with configuration data.""" fixture_filename = f"lcn/config_entry_{name}.json" entry_data = json.loads(load_fixture(fixture_filename)) for device in entry_data[CONF_DEVICES]: device[CONF_ADDRESS] = tuple(device[CONF_ADDRESS]) for entity in entry_data[CONF_ENTITIES]: entity[CONF_ADDRESS] = tuple(entity[CONF_ADDRESS]) options = {} title = entry_data[CONF_HOST] return MockConfigEntry( entry_id=fixture_filename.replace(".", "_"), domain=DOMAIN, title=title, data=entry_data, options=options, version=version[0], minor_version=version[1], ) @pytest.fixture(name="entry") def create_config_entry_pchk() -> MockConfigEntry: """Return one specific config entry.""" return create_config_entry("pchk") @pytest.fixture(name="entry2") def create_config_entry_myhome() -> MockConfigEntry: """Return one specific config entry.""" return create_config_entry("myhome") async def init_integration( hass: HomeAssistant, entry: MockConfigEntry ) -> MockPchkConnectionManager: """Set up the LCN integration in Home Assistant.""" hass.http = Mock() # needs to be mocked as hass.http.register_static_path is called when registering the frontend lcn_connection = None def lcn_connection_factory(*args, **kwargs): nonlocal lcn_connection lcn_connection = MockPchkConnectionManager(*args, **kwargs) return lcn_connection entry.add_to_hass(hass) with patch( "homeassistant.components.lcn.PchkConnectionManager", side_effect=lcn_connection_factory, ): await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() return lcn_connection def get_device( hass: HomeAssistant, entry: MockConfigEntry, address: AddressType ) -> dr.DeviceEntry: """Get LCN device for specified address.""" device_registry = dr.async_get(hass) identifiers = {(DOMAIN, generate_unique_id(entry.entry_id, address))} device = device_registry.async_get_device(identifiers=identifiers) assert device return device