From 20639b0f023aabc4047c64bb51f3a07136e0b1e1 Mon Sep 17 00:00:00 2001 From: Andre Lengwenus Date: Fri, 6 Sep 2024 17:56:46 +0200 Subject: [PATCH] Add tests for LCN climate and scene platform (#124466) * Add tests for LCN climate and scene platform * Add type hints * Add snapshots for test_climate * Add snapshots for test_scene * Replace await_called assertion with snapshots * Remove snapshots for simple status changes * Test platform setup using snapshot_platform * Fix type hints * Patch homeassistant.components.lcn context instead of pypck module * Fix side effects caused by patching PchkConnectionManager in lcn platform context --- homeassistant/components/lcn/__init__.py | 3 +- tests/components/lcn/conftest.py | 23 +- tests/components/lcn/fixtures/config.json | 29 ++ .../lcn/fixtures/config_entry_pchk.json | 38 +++ .../lcn/snapshots/test_climate.ambr | 63 ++++ .../components/lcn/snapshots/test_scene.ambr | 93 ++++++ tests/components/lcn/test_climate.py | 287 ++++++++++++++++++ tests/components/lcn/test_init.py | 4 +- tests/components/lcn/test_scene.py | 64 ++++ tests/components/lcn/test_services.py | 111 ++++--- 10 files changed, 656 insertions(+), 59 deletions(-) create mode 100644 tests/components/lcn/snapshots/test_climate.ambr create mode 100644 tests/components/lcn/snapshots/test_scene.ambr create mode 100644 tests/components/lcn/test_climate.py create mode 100644 tests/components/lcn/test_scene.py diff --git a/homeassistant/components/lcn/__init__.py b/homeassistant/components/lcn/__init__.py index 75f417cb3a5..9817a254d59 100644 --- a/homeassistant/components/lcn/__init__.py +++ b/homeassistant/components/lcn/__init__.py @@ -7,6 +7,7 @@ from functools import partial import logging import pypck +from pypck.connection import PchkConnectionManager from homeassistant import config_entries from homeassistant.const import ( @@ -87,7 +88,7 @@ async def async_setup_entry( } # connect to PCHK - lcn_connection = pypck.connection.PchkConnectionManager( + lcn_connection = PchkConnectionManager( config_entry.data[CONF_IP_ADDRESS], config_entry.data[CONF_PORT], config_entry.data[CONF_USERNAME], diff --git a/tests/components/lcn/conftest.py b/tests/components/lcn/conftest.py index b1f28b28465..67c5b9c0b9c 100644 --- a/tests/components/lcn/conftest.py +++ b/tests/components/lcn/conftest.py @@ -1,16 +1,15 @@ """Test configuration and mocks for LCN component.""" -from collections.abc import AsyncGenerator import json from typing import Any from unittest.mock import AsyncMock, Mock, patch import pypck -from pypck.connection import PchkConnectionManager import pypck.module from pypck.module import GroupConnection, ModuleConnection import pytest +from homeassistant.components.lcn import PchkConnectionManager 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 @@ -76,11 +75,10 @@ def create_config_entry(name: str) -> MockConfigEntry: options = {} title = entry_data[CONF_HOST] - unique_id = fixture_filename return MockConfigEntry( + entry_id=fixture_filename, domain=DOMAIN, title=title, - unique_id=unique_id, data=entry_data, options=options, ) @@ -98,10 +96,9 @@ def create_config_entry_myhome() -> MockConfigEntry: return create_config_entry("myhome") -@pytest.fixture(name="lcn_connection") async def init_integration( hass: HomeAssistant, entry: MockConfigEntry -) -> AsyncGenerator[MockPchkConnectionManager]: +) -> 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 @@ -113,12 +110,22 @@ async def init_integration( entry.add_to_hass(hass) with patch( - "pypck.connection.PchkConnectionManager", + "homeassistant.components.lcn.PchkConnectionManager", side_effect=lcn_connection_factory, ): await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() - yield lcn_connection + + return lcn_connection + + +@pytest.fixture(name="lcn_connection") +async def init_lcn_connection( + hass: HomeAssistant, + entry: MockConfigEntry, +) -> MockPchkConnectionManager: + """Set up the LCN integration in Home Assistantand yield connection object.""" + return await init_integration(hass, entry) async def setup_component(hass: HomeAssistant) -> None: diff --git a/tests/components/lcn/fixtures/config.json b/tests/components/lcn/fixtures/config.json index 13b3dd5feed..ed3e3500900 100644 --- a/tests/components/lcn/fixtures/config.json +++ b/tests/components/lcn/fixtures/config.json @@ -91,6 +91,35 @@ "motor": "motor1" } ], + "climates": [ + { + "name": "Climate1", + "address": "s0.m7", + "source": "var1", + "setpoint": "r1varsetpoint", + "lockable": true, + "min_temp": 0, + "max_temp": 40, + "unit_of_measurement": "°C" + } + ], + "scenes": [ + { + "name": "Romantic", + "address": "s0.m7", + "register": 0, + "scene": 0, + "outputs": ["output1", "output2", "relay1"] + }, + { + "name": "Romantic Transition", + "address": "s0.m7", + "register": 0, + "scene": 1, + "outputs": ["output1", "output2", "relay1"], + "transition": 10 + } + ], "binary_sensors": [ { "name": "Sensor_LockRegulator1", diff --git a/tests/components/lcn/fixtures/config_entry_pchk.json b/tests/components/lcn/fixtures/config_entry_pchk.json index 08ccd194578..9a8095ff16d 100644 --- a/tests/components/lcn/fixtures/config_entry_pchk.json +++ b/tests/components/lcn/fixtures/config_entry_pchk.json @@ -121,6 +121,44 @@ "reverse_time": "RT1200" } }, + { + "address": [0, 7, false], + "name": "Climate1", + "resource": "var1.r1varsetpoint", + "domain": "climate", + "domain_data": { + "source": "VAR1", + "setpoint": "R1VARSETPOINT", + "lockable": true, + "min_temp": 0.0, + "max_temp": 40.0, + "unit_of_measurement": "°C" + } + }, + { + "address": [0, 7, false], + "name": "Romantic", + "resource": "0.0", + "domain": "scene", + "domain_data": { + "register": 0, + "scene": 0, + "outputs": ["OUTPUT1", "OUTPUT2", "RELAY1"], + "transition": null + } + }, + { + "address": [0, 7, false], + "name": "Romantic Transition", + "resource": "0.1", + "domain": "scene", + "domain_data": { + "register": 0, + "scene": 1, + "outputs": ["OUTPUT1", "OUTPUT2", "RELAY1"], + "transition": 10 + } + }, { "address": [0, 7, false], "name": "Sensor_LockRegulator1", diff --git a/tests/components/lcn/snapshots/test_climate.ambr b/tests/components/lcn/snapshots/test_climate.ambr new file mode 100644 index 00000000000..443b13312d1 --- /dev/null +++ b/tests/components/lcn/snapshots/test_climate.ambr @@ -0,0 +1,63 @@ +# serializer version: 1 +# name: test_setup_lcn_climate[climate.climate1-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'hvac_modes': list([ + , + , + ]), + 'max_temp': 40.0, + 'min_temp': 0.0, + }), + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'climate', + 'entity_category': None, + 'entity_id': 'climate.climate1', + 'has_entity_name': False, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Climate1', + 'platform': 'lcn', + 'previous_unique_id': None, + 'supported_features': , + 'translation_key': None, + 'unique_id': 'lcn/config_entry_pchk.json-m000007-var1.r1varsetpoint', + 'unit_of_measurement': None, + }) +# --- +# name: test_setup_lcn_climate[climate.climate1-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'current_temperature': None, + 'friendly_name': 'Climate1', + 'hvac_modes': list([ + , + , + ]), + 'max_temp': 40.0, + 'min_temp': 0.0, + 'supported_features': , + 'temperature': None, + }), + 'context': , + 'entity_id': 'climate.climate1', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'heat', + }) +# --- diff --git a/tests/components/lcn/snapshots/test_scene.ambr b/tests/components/lcn/snapshots/test_scene.ambr new file mode 100644 index 00000000000..c039c4ef951 --- /dev/null +++ b/tests/components/lcn/snapshots/test_scene.ambr @@ -0,0 +1,93 @@ +# serializer version: 1 +# name: test_setup_lcn_scene[scene.romantic-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'scene', + 'entity_category': None, + 'entity_id': 'scene.romantic', + 'has_entity_name': False, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Romantic', + 'platform': 'lcn', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': 'lcn/config_entry_pchk.json-m000007-0.0', + 'unit_of_measurement': None, + }) +# --- +# name: test_setup_lcn_scene[scene.romantic-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Romantic', + }), + 'context': , + 'entity_id': 'scene.romantic', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'unknown', + }) +# --- +# name: test_setup_lcn_scene[scene.romantic_transition-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'scene', + 'entity_category': None, + 'entity_id': 'scene.romantic_transition', + 'has_entity_name': False, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Romantic Transition', + 'platform': 'lcn', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': 'lcn/config_entry_pchk.json-m000007-0.1', + 'unit_of_measurement': None, + }) +# --- +# name: test_setup_lcn_scene[scene.romantic_transition-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Romantic Transition', + }), + 'context': , + 'entity_id': 'scene.romantic_transition', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'unknown', + }) +# --- diff --git a/tests/components/lcn/test_climate.py b/tests/components/lcn/test_climate.py new file mode 100644 index 00000000000..db9f137d6bf --- /dev/null +++ b/tests/components/lcn/test_climate.py @@ -0,0 +1,287 @@ +"""Test for the LCN climate platform.""" + +from unittest.mock import patch + +from pypck.inputs import ModStatusVar, Unknown +from pypck.lcn_addr import LcnAddr +from pypck.lcn_defs import Var, VarUnit, VarValue +from syrupy.assertion import SnapshotAssertion + +# pylint: disable=hass-component-root-import +from homeassistant.components.climate import DOMAIN as DOMAIN_CLIMATE +from homeassistant.components.climate.const import ( + ATTR_CURRENT_TEMPERATURE, + ATTR_HVAC_MODE, + ATTR_TARGET_TEMP_HIGH, + ATTR_TARGET_TEMP_LOW, + SERVICE_SET_HVAC_MODE, + SERVICE_SET_TEMPERATURE, + HVACMode, +) +from homeassistant.components.lcn.helpers import get_device_connection +from homeassistant.const import ( + ATTR_ENTITY_ID, + ATTR_TEMPERATURE, + STATE_UNAVAILABLE, + Platform, +) +from homeassistant.core import HomeAssistant +from homeassistant.helpers import entity_registry as er + +from .conftest import MockConfigEntry, MockModuleConnection, init_integration + +from tests.common import snapshot_platform + + +async def test_setup_lcn_climate( + hass: HomeAssistant, + entity_registry: er.EntityRegistry, + entry: MockConfigEntry, + snapshot: SnapshotAssertion, +) -> None: + """Test the setup of climate.""" + with patch("homeassistant.components.lcn.PLATFORMS", [Platform.CLIMATE]): + await init_integration(hass, entry) + + await snapshot_platform(hass, entity_registry, snapshot, entry.entry_id) + + +async def test_set_hvac_mode_heat(hass: HomeAssistant, entry: MockConfigEntry) -> None: + """Test the hvac mode is set to heat.""" + await init_integration(hass, entry) + + with patch.object(MockModuleConnection, "lock_regulator") as lock_regulator: + state = hass.states.get("climate.climate1") + state.state = HVACMode.OFF + + # command failed + lock_regulator.return_value = False + + await hass.services.async_call( + DOMAIN_CLIMATE, + SERVICE_SET_HVAC_MODE, + {ATTR_ENTITY_ID: "climate.climate1", ATTR_HVAC_MODE: HVACMode.HEAT}, + blocking=True, + ) + + lock_regulator.assert_awaited_with(0, False) + + state = hass.states.get("climate.climate1") + assert state is not None + assert state.state != HVACMode.HEAT + + # command success + lock_regulator.reset_mock(return_value=True) + lock_regulator.return_value = True + + await hass.services.async_call( + DOMAIN_CLIMATE, + SERVICE_SET_HVAC_MODE, + {ATTR_ENTITY_ID: "climate.climate1", ATTR_HVAC_MODE: HVACMode.HEAT}, + blocking=True, + ) + + lock_regulator.assert_awaited_with(0, False) + + state = hass.states.get("climate.climate1") + assert state is not None + assert state.state == HVACMode.HEAT + + +async def test_set_hvac_mode_off(hass: HomeAssistant, entry: MockConfigEntry) -> None: + """Test the hvac mode is set off.""" + await init_integration(hass, entry) + + with patch.object(MockModuleConnection, "lock_regulator") as lock_regulator: + state = hass.states.get("climate.climate1") + state.state = HVACMode.HEAT + + # command failed + lock_regulator.return_value = False + + await hass.services.async_call( + DOMAIN_CLIMATE, + SERVICE_SET_HVAC_MODE, + {ATTR_ENTITY_ID: "climate.climate1", ATTR_HVAC_MODE: HVACMode.OFF}, + blocking=True, + ) + + lock_regulator.assert_awaited_with(0, True) + + state = hass.states.get("climate.climate1") + assert state is not None + assert state.state != HVACMode.OFF + + # command success + lock_regulator.reset_mock(return_value=True) + lock_regulator.return_value = True + + await hass.services.async_call( + DOMAIN_CLIMATE, + SERVICE_SET_HVAC_MODE, + {ATTR_ENTITY_ID: "climate.climate1", ATTR_HVAC_MODE: HVACMode.OFF}, + blocking=True, + ) + + lock_regulator.assert_awaited_with(0, True) + + state = hass.states.get("climate.climate1") + assert state is not None + assert state.state == HVACMode.OFF + + +async def test_set_temperature(hass: HomeAssistant, entry: MockConfigEntry) -> None: + """Test the temperature is set.""" + await init_integration(hass, entry) + + with patch.object(MockModuleConnection, "var_abs") as var_abs: + state = hass.states.get("climate.climate1") + state.state = HVACMode.HEAT + + # wrong temperature set via service call with high/low attributes + var_abs.return_value = False + + await hass.services.async_call( + DOMAIN_CLIMATE, + SERVICE_SET_TEMPERATURE, + { + ATTR_ENTITY_ID: "climate.climate1", + ATTR_TARGET_TEMP_LOW: 24.5, + ATTR_TARGET_TEMP_HIGH: 25.5, + }, + blocking=True, + ) + + var_abs.assert_not_awaited() + + # command failed + var_abs.reset_mock(return_value=True) + var_abs.return_value = False + + await hass.services.async_call( + DOMAIN_CLIMATE, + SERVICE_SET_TEMPERATURE, + {ATTR_ENTITY_ID: "climate.climate1", ATTR_TEMPERATURE: 25.5}, + blocking=True, + ) + + var_abs.assert_awaited_with(Var.R1VARSETPOINT, 25.5, VarUnit.CELSIUS) + + state = hass.states.get("climate.climate1") + assert state is not None + assert state.attributes[ATTR_TEMPERATURE] != 25.5 + + # command success + var_abs.reset_mock(return_value=True) + var_abs.return_value = True + + await hass.services.async_call( + DOMAIN_CLIMATE, + SERVICE_SET_TEMPERATURE, + {ATTR_ENTITY_ID: "climate.climate1", ATTR_TEMPERATURE: 25.5}, + blocking=True, + ) + + var_abs.assert_awaited_with(Var.R1VARSETPOINT, 25.5, VarUnit.CELSIUS) + + state = hass.states.get("climate.climate1") + assert state is not None + assert state.attributes[ATTR_TEMPERATURE] == 25.5 + + +async def test_pushed_current_temperature_status_change( + hass: HomeAssistant, + entry: MockConfigEntry, +) -> None: + """Test the climate changes its current temperature on status received.""" + await init_integration(hass, entry) + + device_connection = get_device_connection(hass, (0, 7, False), entry) + address = LcnAddr(0, 7, False) + + temperature = VarValue.from_celsius(25.5) + + inp = ModStatusVar(address, Var.VAR1, temperature) + await device_connection.async_process_input(inp) + await hass.async_block_till_done() + + state = hass.states.get("climate.climate1") + assert state is not None + assert state.state == HVACMode.HEAT + assert state.attributes[ATTR_CURRENT_TEMPERATURE] == 25.5 + assert state.attributes[ATTR_TEMPERATURE] is None + + +async def test_pushed_setpoint_status_change( + hass: HomeAssistant, + entry: MockConfigEntry, +) -> None: + """Test the climate changes its setpoint on status received.""" + await init_integration(hass, entry) + + device_connection = get_device_connection(hass, (0, 7, False), entry) + address = LcnAddr(0, 7, False) + + temperature = VarValue.from_celsius(25.5) + + inp = ModStatusVar(address, Var.R1VARSETPOINT, temperature) + await device_connection.async_process_input(inp) + await hass.async_block_till_done() + + state = hass.states.get("climate.climate1") + assert state is not None + assert state.state == HVACMode.HEAT + assert state.attributes[ATTR_CURRENT_TEMPERATURE] is None + assert state.attributes[ATTR_TEMPERATURE] == 25.5 + + +async def test_pushed_lock_status_change( + hass: HomeAssistant, + entry: MockConfigEntry, +) -> None: + """Test the climate changes its setpoint on status received.""" + await init_integration(hass, entry) + + device_connection = get_device_connection(hass, (0, 7, False), entry) + address = LcnAddr(0, 7, False) + + temperature = VarValue(0x8000) + + inp = ModStatusVar(address, Var.R1VARSETPOINT, temperature) + await device_connection.async_process_input(inp) + await hass.async_block_till_done() + + state = hass.states.get("climate.climate1") + assert state is not None + assert state.state == HVACMode.OFF + assert state.attributes[ATTR_CURRENT_TEMPERATURE] is None + assert state.attributes[ATTR_TEMPERATURE] is None + + +async def test_pushed_wrong_input( + hass: HomeAssistant, + entry: MockConfigEntry, +) -> None: + """Test the climate handles wrong input correctly.""" + await init_integration(hass, entry) + + device_connection = get_device_connection(hass, (0, 7, False), entry) + + await device_connection.async_process_input(Unknown("input")) + await hass.async_block_till_done() + + state = hass.states.get("climate.climate1") + assert state.attributes[ATTR_CURRENT_TEMPERATURE] is None + assert state.attributes[ATTR_TEMPERATURE] is None + + +async def test_unload_config_entry( + hass: HomeAssistant, + entry: MockConfigEntry, +) -> None: + """Test the climate is removed when the config entry is unloaded.""" + await init_integration(hass, entry) + + await hass.config_entries.async_forward_entry_unload(entry, DOMAIN_CLIMATE) + state = hass.states.get("climate.climate1") + assert state.state == STATE_UNAVAILABLE diff --git a/tests/components/lcn/test_init.py b/tests/components/lcn/test_init.py index c118b98ecef..120db8a1333 100644 --- a/tests/components/lcn/test_init.py +++ b/tests/components/lcn/test_init.py @@ -32,7 +32,9 @@ async def test_async_setup_entry(hass: HomeAssistant, entry, lcn_connection) -> async def test_async_setup_multiple_entries(hass: HomeAssistant, entry, entry2) -> None: """Test a successful setup and unload of multiple entries.""" hass.http = Mock() - with patch("pypck.connection.PchkConnectionManager", MockPchkConnectionManager): + with patch( + "homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager + ): for config_entry in (entry, entry2): config_entry.add_to_hass(hass) await hass.config_entries.async_setup(config_entry.entry_id) diff --git a/tests/components/lcn/test_scene.py b/tests/components/lcn/test_scene.py new file mode 100644 index 00000000000..558893bb76f --- /dev/null +++ b/tests/components/lcn/test_scene.py @@ -0,0 +1,64 @@ +"""Test for the LCN scene platform.""" + +from unittest.mock import patch + +from pypck.lcn_defs import OutputPort, RelayPort +from syrupy.assertion import SnapshotAssertion + +from homeassistant.components.scene import DOMAIN as DOMAIN_SCENE +from homeassistant.const import ( + ATTR_ENTITY_ID, + SERVICE_TURN_ON, + STATE_UNAVAILABLE, + Platform, +) +from homeassistant.core import HomeAssistant +from homeassistant.helpers import entity_registry as er + +from .conftest import MockConfigEntry, MockModuleConnection, init_integration + +from tests.common import snapshot_platform + + +async def test_setup_lcn_scene( + hass: HomeAssistant, + entity_registry: er.EntityRegistry, + entry: MockConfigEntry, + snapshot: SnapshotAssertion, +) -> None: + """Test the setup of switch.""" + with patch("homeassistant.components.lcn.PLATFORMS", [Platform.SCENE]): + await init_integration(hass, entry) + + await snapshot_platform(hass, entity_registry, snapshot, entry.entry_id) + + +async def test_scene_activate( + hass: HomeAssistant, + entry: MockConfigEntry, +) -> None: + """Test the scene is activated.""" + await init_integration(hass, entry) + with patch.object(MockModuleConnection, "activate_scene") as activate_scene: + await hass.services.async_call( + DOMAIN_SCENE, + SERVICE_TURN_ON, + {ATTR_ENTITY_ID: "scene.romantic"}, + blocking=True, + ) + + state = hass.states.get("scene.romantic") + assert state is not None + + activate_scene.assert_awaited_with( + 0, 0, [OutputPort.OUTPUT1, OutputPort.OUTPUT2], [RelayPort.RELAY1], None + ) + + +async def test_unload_config_entry(hass: HomeAssistant, entry: MockConfigEntry) -> None: + """Test the scene is removed when the config entry is unloaded.""" + await init_integration(hass, entry) + await hass.config_entries.async_forward_entry_unload(entry, DOMAIN_SCENE) + + state = hass.states.get("scene.romantic") + assert state.state == STATE_UNAVAILABLE diff --git a/tests/components/lcn/test_services.py b/tests/components/lcn/test_services.py index 9cb53289065..27253a0c7e5 100644 --- a/tests/components/lcn/test_services.py +++ b/tests/components/lcn/test_services.py @@ -32,16 +32,21 @@ from homeassistant.const import ( from homeassistant.core import HomeAssistant from homeassistant.setup import async_setup_component -from .conftest import MockModuleConnection, MockPchkConnectionManager, setup_component +from .conftest import ( + MockConfigEntry, + MockModuleConnection, + MockPchkConnectionManager, + init_integration, +) -@patch("pypck.connection.PchkConnectionManager", MockPchkConnectionManager) +@patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager) async def test_service_output_abs( - hass: HomeAssistant, snapshot: SnapshotAssertion + hass: HomeAssistant, entry: MockConfigEntry, snapshot: SnapshotAssertion ) -> None: """Test output_abs service.""" await async_setup_component(hass, "persistent_notification", {}) - await setup_component(hass) + await init_integration(hass, entry) with patch.object(MockModuleConnection, "dim_output") as dim_output: await hass.services.async_call( @@ -59,13 +64,13 @@ async def test_service_output_abs( assert dim_output.await_args.args == snapshot() -@patch("pypck.connection.PchkConnectionManager", MockPchkConnectionManager) +@patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager) async def test_service_output_rel( - hass: HomeAssistant, snapshot: SnapshotAssertion + hass: HomeAssistant, entry: MockConfigEntry, snapshot: SnapshotAssertion ) -> None: """Test output_rel service.""" await async_setup_component(hass, "persistent_notification", {}) - await setup_component(hass) + await init_integration(hass, entry) with patch.object(MockModuleConnection, "rel_output") as rel_output: await hass.services.async_call( @@ -82,13 +87,13 @@ async def test_service_output_rel( assert rel_output.await_args.args == snapshot() -@patch("pypck.connection.PchkConnectionManager", MockPchkConnectionManager) +@patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager) async def test_service_output_toggle( - hass: HomeAssistant, snapshot: SnapshotAssertion + hass: HomeAssistant, entry: MockConfigEntry, snapshot: SnapshotAssertion ) -> None: """Test output_toggle service.""" await async_setup_component(hass, "persistent_notification", {}) - await setup_component(hass) + await init_integration(hass, entry) with patch.object(MockModuleConnection, "toggle_output") as toggle_output: await hass.services.async_call( @@ -105,11 +110,13 @@ async def test_service_output_toggle( assert toggle_output.await_args.args == snapshot() -@patch("pypck.connection.PchkConnectionManager", MockPchkConnectionManager) -async def test_service_relays(hass: HomeAssistant, snapshot: SnapshotAssertion) -> None: +@patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager) +async def test_service_relays( + hass: HomeAssistant, entry: MockConfigEntry, snapshot: SnapshotAssertion +) -> None: """Test relays service.""" await async_setup_component(hass, "persistent_notification", {}) - await setup_component(hass) + await init_integration(hass, entry) with patch.object(MockModuleConnection, "control_relays") as control_relays: await hass.services.async_call( @@ -122,11 +129,13 @@ async def test_service_relays(hass: HomeAssistant, snapshot: SnapshotAssertion) assert control_relays.await_args.args == snapshot() -@patch("pypck.connection.PchkConnectionManager", MockPchkConnectionManager) -async def test_service_led(hass: HomeAssistant, snapshot: SnapshotAssertion) -> None: +@patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager) +async def test_service_led( + hass: HomeAssistant, entry: MockConfigEntry, snapshot: SnapshotAssertion +) -> None: """Test led service.""" await async_setup_component(hass, "persistent_notification", {}) - await setup_component(hass) + await init_integration(hass, entry) with patch.object(MockModuleConnection, "control_led") as control_led: await hass.services.async_call( @@ -139,13 +148,13 @@ async def test_service_led(hass: HomeAssistant, snapshot: SnapshotAssertion) -> assert control_led.await_args.args == snapshot() -@patch("pypck.connection.PchkConnectionManager", MockPchkConnectionManager) +@patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager) async def test_service_var_abs( - hass: HomeAssistant, snapshot: SnapshotAssertion + hass: HomeAssistant, entry: MockConfigEntry, snapshot: SnapshotAssertion ) -> None: """Test var_abs service.""" await async_setup_component(hass, "persistent_notification", {}) - await setup_component(hass) + await init_integration(hass, entry) with patch.object(MockModuleConnection, "var_abs") as var_abs: await hass.services.async_call( @@ -163,13 +172,13 @@ async def test_service_var_abs( assert var_abs.await_args.args == snapshot() -@patch("pypck.connection.PchkConnectionManager", MockPchkConnectionManager) +@patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager) async def test_service_var_rel( - hass: HomeAssistant, snapshot: SnapshotAssertion + hass: HomeAssistant, entry: MockConfigEntry, snapshot: SnapshotAssertion ) -> None: """Test var_rel service.""" await async_setup_component(hass, "persistent_notification", {}) - await setup_component(hass) + await init_integration(hass, entry) with patch.object(MockModuleConnection, "var_rel") as var_rel: await hass.services.async_call( @@ -188,13 +197,13 @@ async def test_service_var_rel( assert var_rel.await_args.args == snapshot() -@patch("pypck.connection.PchkConnectionManager", MockPchkConnectionManager) +@patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager) async def test_service_var_reset( - hass: HomeAssistant, snapshot: SnapshotAssertion + hass: HomeAssistant, entry: MockConfigEntry, snapshot: SnapshotAssertion ) -> None: """Test var_reset service.""" await async_setup_component(hass, "persistent_notification", {}) - await setup_component(hass) + await init_integration(hass, entry) with patch.object(MockModuleConnection, "var_reset") as var_reset: await hass.services.async_call( @@ -207,13 +216,13 @@ async def test_service_var_reset( assert var_reset.await_args.args == snapshot() -@patch("pypck.connection.PchkConnectionManager", MockPchkConnectionManager) +@patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager) async def test_service_lock_regulator( - hass: HomeAssistant, snapshot: SnapshotAssertion + hass: HomeAssistant, entry: MockConfigEntry, snapshot: SnapshotAssertion ) -> None: """Test lock_regulator service.""" await async_setup_component(hass, "persistent_notification", {}) - await setup_component(hass) + await init_integration(hass, entry) with patch.object(MockModuleConnection, "lock_regulator") as lock_regulator: await hass.services.async_call( @@ -230,13 +239,13 @@ async def test_service_lock_regulator( assert lock_regulator.await_args.args == snapshot() -@patch("pypck.connection.PchkConnectionManager", MockPchkConnectionManager) +@patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager) async def test_service_send_keys( - hass: HomeAssistant, snapshot: SnapshotAssertion + hass: HomeAssistant, entry: MockConfigEntry, snapshot: SnapshotAssertion ) -> None: """Test send_keys service.""" await async_setup_component(hass, "persistent_notification", {}) - await setup_component(hass) + await init_integration(hass, entry) with patch.object(MockModuleConnection, "send_keys") as send_keys: await hass.services.async_call( @@ -254,13 +263,13 @@ async def test_service_send_keys( assert send_keys.await_args.args == snapshot() -@patch("pypck.connection.PchkConnectionManager", MockPchkConnectionManager) +@patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager) async def test_service_send_keys_hit_deferred( - hass: HomeAssistant, snapshot: SnapshotAssertion + hass: HomeAssistant, entry: MockConfigEntry, snapshot: SnapshotAssertion ) -> None: """Test send_keys (hit_deferred) service.""" await async_setup_component(hass, "persistent_notification", {}) - await setup_component(hass) + await init_integration(hass, entry) keys = [[False] * 8 for i in range(4)] keys[0][0] = True @@ -306,13 +315,13 @@ async def test_service_send_keys_hit_deferred( ) -@patch("pypck.connection.PchkConnectionManager", MockPchkConnectionManager) +@patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager) async def test_service_lock_keys( - hass: HomeAssistant, snapshot: SnapshotAssertion + hass: HomeAssistant, entry: MockConfigEntry, snapshot: SnapshotAssertion ) -> None: """Test lock_keys service.""" await async_setup_component(hass, "persistent_notification", {}) - await setup_component(hass) + await init_integration(hass, entry) with patch.object(MockModuleConnection, "lock_keys") as lock_keys: await hass.services.async_call( @@ -325,13 +334,13 @@ async def test_service_lock_keys( assert lock_keys.await_args.args == snapshot() -@patch("pypck.connection.PchkConnectionManager", MockPchkConnectionManager) +@patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager) async def test_service_lock_keys_tab_a_temporary( - hass: HomeAssistant, snapshot: SnapshotAssertion + hass: HomeAssistant, entry: MockConfigEntry, snapshot: SnapshotAssertion ) -> None: """Test lock_keys (tab_a_temporary) service.""" await async_setup_component(hass, "persistent_notification", {}) - await setup_component(hass) + await init_integration(hass, entry) # success with patch.object( @@ -372,13 +381,13 @@ async def test_service_lock_keys_tab_a_temporary( ) -@patch("pypck.connection.PchkConnectionManager", MockPchkConnectionManager) +@patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager) async def test_service_dyn_text( - hass: HomeAssistant, snapshot: SnapshotAssertion + hass: HomeAssistant, entry: MockConfigEntry, snapshot: SnapshotAssertion ) -> None: """Test dyn_text service.""" await async_setup_component(hass, "persistent_notification", {}) - await setup_component(hass) + await init_integration(hass, entry) with patch.object(MockModuleConnection, "dyn_text") as dyn_text: await hass.services.async_call( @@ -391,11 +400,13 @@ async def test_service_dyn_text( assert dyn_text.await_args.args == snapshot() -@patch("pypck.connection.PchkConnectionManager", MockPchkConnectionManager) -async def test_service_pck(hass: HomeAssistant, snapshot: SnapshotAssertion) -> None: +@patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager) +async def test_service_pck( + hass: HomeAssistant, entry: MockConfigEntry, snapshot: SnapshotAssertion +) -> None: """Test pck service.""" await async_setup_component(hass, "persistent_notification", {}) - await setup_component(hass) + await init_integration(hass, entry) with patch.object(MockModuleConnection, "pck") as pck: await hass.services.async_call( @@ -408,11 +419,13 @@ async def test_service_pck(hass: HomeAssistant, snapshot: SnapshotAssertion) -> assert pck.await_args.args == snapshot() -@patch("pypck.connection.PchkConnectionManager", MockPchkConnectionManager) -async def test_service_called_with_invalid_host_id(hass: HomeAssistant) -> None: +@patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager) +async def test_service_called_with_invalid_host_id( + hass: HomeAssistant, entry: MockConfigEntry +) -> None: """Test service was called with non existing host id.""" await async_setup_component(hass, "persistent_notification", {}) - await setup_component(hass) + await init_integration(hass, entry) with patch.object(MockModuleConnection, "pck") as pck, pytest.raises(ValueError): await hass.services.async_call(