From 3d7860391a4be9cba357e7de2544ebe7a8c01b52 Mon Sep 17 00:00:00 2001 From: SukramJ Date: Tue, 15 Oct 2019 12:12:58 +0200 Subject: [PATCH] Improve code coverage for HomematicIP Cloud (#27606) * Improve tests for HomematicIP Cloud * create fixtures remove decorators * removed further decorators * remove last decorator * improve exception handling * removed not required coroutine * use the correct place for mock --- .coveragerc | 1 - .../components/homematicip_cloud/__init__.py | 4 +- .../components/homematicip_cloud/hap.py | 2 +- .../components/homematicip_cloud/light.py | 8 +- .../components/homematicip_cloud/conftest.py | 86 ++++++++++---- tests/components/homematicip_cloud/helper.py | 9 +- .../test_alarm_control_panel.py | 18 +++ .../homematicip_cloud/test_binary_sensor.py | 16 +++ .../homematicip_cloud/test_climate.py | 36 ++++++ .../homematicip_cloud/test_cover.py | 14 +++ .../homematicip_cloud/test_device.py | 21 ++++ .../components/homematicip_cloud/test_hap.py | 108 +++++++++++++++++- .../homematicip_cloud/test_light.py | 29 ++++- .../homematicip_cloud/test_sensor.py | 26 +++++ .../homematicip_cloud/test_switch.py | 19 ++- .../homematicip_cloud/test_weather.py | 14 +++ 16 files changed, 372 insertions(+), 39 deletions(-) diff --git a/.coveragerc b/.coveragerc index 145350b6b19..69ce7f8322c 100644 --- a/.coveragerc +++ b/.coveragerc @@ -290,7 +290,6 @@ omit = homeassistant/components/homematic/climate.py homeassistant/components/homematic/cover.py homeassistant/components/homematic/notify.py - homeassistant/components/homematicip_cloud/* homeassistant/components/homeworks/* homeassistant/components/honeywell/climate.py homeassistant/components/hook/switch.py diff --git a/homeassistant/components/homematicip_cloud/__init__.py b/homeassistant/components/homematicip_cloud/__init__.py index c8fb31998ef..139565bf249 100644 --- a/homeassistant/components/homematicip_cloud/__init__.py +++ b/homeassistant/components/homematicip_cloud/__init__.py @@ -213,9 +213,11 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: def _get_home(hapid: str): """Return a HmIP home.""" - hap = hass.data[DOMAIN][hapid] + hap = hass.data[DOMAIN].get(hapid) if hap: return hap.home + + _LOGGER.info("No matching access point found for access point id %s", hapid) return None return True diff --git a/homeassistant/components/homematicip_cloud/hap.py b/homeassistant/components/homematicip_cloud/hap.py index f6727f91c7e..64fbd4fd079 100644 --- a/homeassistant/components/homematicip_cloud/hap.py +++ b/homeassistant/components/homematicip_cloud/hap.py @@ -53,7 +53,7 @@ class HomematicipAuth: except HmipConnectionError: return False - async def get_auth(self, hass, hapid, pin): + async def get_auth(self, hass: HomeAssistant, hapid, pin): """Create a HomematicIP access point object.""" auth = AsyncAuth(hass.loop, async_get_clientsession(hass)) try: diff --git a/homeassistant/components/homematicip_cloud/light.py b/homeassistant/components/homematicip_cloud/light.py index 80ee4cc5743..bc704e2ef06 100644 --- a/homeassistant/components/homematicip_cloud/light.py +++ b/homeassistant/components/homematicip_cloud/light.py @@ -119,9 +119,7 @@ class HomematicipDimmer(HomematicipGenericDevice, Light): @property def brightness(self) -> int: """Return the brightness of this light between 0..255.""" - if self._device.dimLevel: - return int(self._device.dimLevel * 255) - return 0 + return int((self._device.dimLevel or 0.0) * 255) @property def supported_features(self) -> int: @@ -176,9 +174,7 @@ class HomematicipNotificationLight(HomematicipGenericDevice, Light): @property def brightness(self) -> int: """Return the brightness of this light between 0..255.""" - if self._func_channel.dimLevel: - return int(self._func_channel.dimLevel * 255) - return 0 + return int((self._func_channel.dimLevel or 0.0) * 255) @property def hs_color(self) -> tuple: diff --git a/tests/components/homematicip_cloud/conftest.py b/tests/components/homematicip_cloud/conftest.py index 2c2b020f3a0..b2fc53a28ec 100644 --- a/tests/components/homematicip_cloud/conftest.py +++ b/tests/components/homematicip_cloud/conftest.py @@ -1,22 +1,20 @@ """Initializer helpers for HomematicIP fake server.""" -from unittest.mock import MagicMock, patch - +from asynctest import MagicMock, Mock, patch +from homematicip.aio.auth import AsyncAuth from homematicip.aio.connection import AsyncConnection +from homematicip.aio.home import AsyncHome import pytest from homeassistant import config_entries from homeassistant.components.homematicip_cloud import ( - CONF_ACCESSPOINT, - CONF_AUTHTOKEN, DOMAIN as HMIPC_DOMAIN, async_setup as hmip_async_setup, const as hmipc, hap as hmip_hap, ) -from homeassistant.const import CONF_NAME from homeassistant.core import HomeAssistant -from .helper import AUTH_TOKEN, HAPID, HomeTemplate +from .helper import AUTH_TOKEN, HAPID, HAPPIN, HomeTemplate from tests.common import MockConfigEntry, mock_coro @@ -31,16 +29,11 @@ def mock_connection_fixture(): connection._restCall.side_effect = _rest_call_side_effect # pylint: disable=W0212 connection.api_call.return_value = mock_coro(True) + connection.init.side_effect = mock_coro(True) return connection -@pytest.fixture(name="default_mock_home") -def default_mock_home_fixture(mock_connection): - """Create a fake homematic async home.""" - return HomeTemplate(connection=mock_connection).init_home().get_async_home_mock() - - @pytest.fixture(name="hmip_config_entry") def hmip_config_entry_fixture(): """Create a mock config entriy for homematic ip cloud.""" @@ -48,6 +41,7 @@ def hmip_config_entry_fixture(): hmipc.HMIPC_HAPID: HAPID, hmipc.HMIPC_AUTHTOKEN: AUTH_TOKEN, hmipc.HMIPC_NAME: "", + hmipc.HMIPC_PIN: HAPPIN, } config_entry = MockConfigEntry( version=1, @@ -62,17 +56,34 @@ def hmip_config_entry_fixture(): return config_entry +@pytest.fixture(name="default_mock_home") +def default_mock_home_fixture(mock_connection): + """Create a fake homematic async home.""" + return HomeTemplate(connection=mock_connection).init_home().get_async_home_mock() + + @pytest.fixture(name="default_mock_hap") async def default_mock_hap_fixture( - hass: HomeAssistant, default_mock_home, hmip_config_entry + hass: HomeAssistant, mock_connection, hmip_config_entry ): - """Create a fake homematic access point.""" + """Create a mocked homematic access point.""" + return await get_mock_hap(hass, mock_connection, hmip_config_entry) + + +async def get_mock_hap(hass: HomeAssistant, mock_connection, hmip_config_entry): + """Create a mocked homematic access point.""" hass.config.components.add(HMIPC_DOMAIN) hap = hmip_hap.HomematicipHAP(hass, hmip_config_entry) - with patch.object(hap, "get_hap", return_value=mock_coro(default_mock_home)): + home_name = hmip_config_entry.data["name"] + mock_home = ( + HomeTemplate(connection=mock_connection, home_name=home_name) + .init_home() + .get_async_home_mock() + ) + with patch.object(hap, "get_hap", return_value=mock_coro(mock_home)): assert await hap.async_setup() is True - default_mock_home.on_update(hap.async_update) - default_mock_home.on_create(hap.async_create_entity) + mock_home.on_update(hap.async_update) + mock_home.on_create(hap.async_create_entity) hass.data[HMIPC_DOMAIN] = {HAPID: hap} @@ -85,18 +96,49 @@ async def default_mock_hap_fixture( def hmip_config_fixture(): """Create a config for homematic ip cloud.""" - entry_data = {CONF_ACCESSPOINT: HAPID, CONF_AUTHTOKEN: AUTH_TOKEN, CONF_NAME: ""} + entry_data = { + hmipc.HMIPC_HAPID: HAPID, + hmipc.HMIPC_AUTHTOKEN: AUTH_TOKEN, + hmipc.HMIPC_NAME: "", + hmipc.HMIPC_PIN: HAPPIN, + } - return {hmipc.DOMAIN: [entry_data]} + return {HMIPC_DOMAIN: [entry_data]} + + +@pytest.fixture(name="dummy_config") +def dummy_config_fixture(): + """Create a dummy config.""" + return {"blabla": None} @pytest.fixture(name="mock_hap_with_service") async def mock_hap_with_service_fixture( - hass: HomeAssistant, default_mock_hap, hmip_config + hass: HomeAssistant, default_mock_hap, dummy_config ): """Create a fake homematic access point with hass services.""" - - await hmip_async_setup(hass, hmip_config) + await hmip_async_setup(hass, dummy_config) await hass.async_block_till_done() hass.data[HMIPC_DOMAIN] = {HAPID: default_mock_hap} return default_mock_hap + + +@pytest.fixture(name="simple_mock_home") +def simple_mock_home_fixture(): + """Return a simple AsyncHome Mock.""" + return Mock( + spec=AsyncHome, + devices=[], + groups=[], + location=Mock(), + weather=Mock(create=True), + id=42, + dutyCycle=88, + connected=True, + ) + + +@pytest.fixture(name="simple_mock_auth") +def simple_mock_auth_fixture(): + """Return a simple AsyncAuth Mock.""" + return Mock(spec=AsyncAuth, pin=HAPPIN, create=True) diff --git a/tests/components/homematicip_cloud/helper.py b/tests/components/homematicip_cloud/helper.py index e5c5c4569d7..78c78ec0ab9 100644 --- a/tests/components/homematicip_cloud/helper.py +++ b/tests/components/homematicip_cloud/helper.py @@ -1,7 +1,7 @@ """Helper for HomematicIP Cloud Tests.""" import json -from asynctest import Mock +from asynctest import Mock from homematicip.aio.class_maps import ( TYPE_CLASS_MAP, TYPE_GROUP_MAP, @@ -20,6 +20,7 @@ from homeassistant.components.homematicip_cloud.device import ( from tests.common import load_fixture HAPID = "3014F7110000000000000001" +HAPPIN = "5678" AUTH_TOKEN = "1234" HOME_JSON = "homematicip_cloud.json" @@ -81,10 +82,11 @@ class HomeTemplate(Home): _typeGroupMap = TYPE_GROUP_MAP _typeSecurityEventMap = TYPE_SECURITY_EVENT_MAP - def __init__(self, connection=None): + def __init__(self, connection=None, home_name=""): """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 @@ -121,13 +123,12 @@ class HomeTemplate(Home): 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 reuired attributes. + and sets required attributes. """ mock_home = Mock( spec=AsyncHome, wraps=self, label="Access Point", modelType="HmIP-HAP" ) mock_home.__dict__.update(self.__dict__) - mock_home.name = "" return mock_home diff --git a/tests/components/homematicip_cloud/test_alarm_control_panel.py b/tests/components/homematicip_cloud/test_alarm_control_panel.py index 0a68ac6d509..2798a0879b7 100644 --- a/tests/components/homematicip_cloud/test_alarm_control_panel.py +++ b/tests/components/homematicip_cloud/test_alarm_control_panel.py @@ -2,12 +2,17 @@ from homematicip.base.enums import WindowState from homematicip.group import SecurityZoneGroup +from homeassistant.components.alarm_control_panel import ( + DOMAIN as ALARM_CONTROL_PANEL_DOMAIN, +) +from homeassistant.components.homematicip_cloud import DOMAIN as HMIPC_DOMAIN from homeassistant.const import ( STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED, STATE_ALARM_TRIGGERED, ) +from homeassistant.setup import async_setup_component from .helper import get_and_check_entity_basics @@ -38,6 +43,19 @@ async def _async_manipulate_security_zones( await hass.async_block_till_done() +async def test_manually_configured_platform(hass): + """Test that we do not set up an access point.""" + assert ( + await async_setup_component( + hass, + ALARM_CONTROL_PANEL_DOMAIN, + {ALARM_CONTROL_PANEL_DOMAIN: {"platform": HMIPC_DOMAIN}}, + ) + is True + ) + assert not hass.data.get(HMIPC_DOMAIN) + + async def test_hmip_alarm_control_panel(hass, default_mock_hap): """Test HomematicipAlarmControlPanel.""" entity_id = "alarm_control_panel.hmip_alarm_control_panel" diff --git a/tests/components/homematicip_cloud/test_binary_sensor.py b/tests/components/homematicip_cloud/test_binary_sensor.py index 0de2101d287..0760518171e 100644 --- a/tests/components/homematicip_cloud/test_binary_sensor.py +++ b/tests/components/homematicip_cloud/test_binary_sensor.py @@ -1,6 +1,8 @@ """Tests for HomematicIP Cloud binary sensor.""" from homematicip.base.enums import SmokeDetectorAlarmType, WindowState +from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN +from homeassistant.components.homematicip_cloud import DOMAIN as HMIPC_DOMAIN from homeassistant.components.homematicip_cloud.binary_sensor import ( ATTR_ACCELERATION_SENSOR_MODE, ATTR_ACCELERATION_SENSOR_NEUTRAL_POSITION, @@ -10,10 +12,24 @@ from homeassistant.components.homematicip_cloud.binary_sensor import ( ATTR_MOTION_DETECTED, ) from homeassistant.const import STATE_OFF, STATE_ON +from homeassistant.setup import async_setup_component from .helper import async_manipulate_test_data, get_and_check_entity_basics +async def test_manually_configured_platform(hass): + """Test that we do not set up an access point.""" + assert ( + await async_setup_component( + hass, + BINARY_SENSOR_DOMAIN, + {BINARY_SENSOR_DOMAIN: {"platform": HMIPC_DOMAIN}}, + ) + is True + ) + assert not hass.data.get(HMIPC_DOMAIN) + + async def test_hmip_acceleration_sensor(hass, default_mock_hap): """Test HomematicipAccelerationSensor.""" entity_id = "binary_sensor.garagentor" diff --git a/tests/components/homematicip_cloud/test_climate.py b/tests/components/homematicip_cloud/test_climate.py index 8f8a681fad8..bdfd26319e6 100644 --- a/tests/components/homematicip_cloud/test_climate.py +++ b/tests/components/homematicip_cloud/test_climate.py @@ -4,6 +4,7 @@ import datetime from homematicip.base.enums import AbsenceType from homematicip.functionalHomes import IndoorClimateHome +from homeassistant.components.climate import DOMAIN as CLIMATE_DOMAIN from homeassistant.components.climate.const import ( ATTR_CURRENT_TEMPERATURE, ATTR_PRESET_MODE, @@ -15,10 +16,23 @@ from homeassistant.components.climate.const import ( PRESET_ECO, PRESET_NONE, ) +from homeassistant.components.homematicip_cloud import DOMAIN as HMIPC_DOMAIN +from homeassistant.setup import async_setup_component from .helper import HAPID, async_manipulate_test_data, get_and_check_entity_basics +async def test_manually_configured_platform(hass): + """Test that we do not set up an access point.""" + assert ( + await async_setup_component( + hass, CLIMATE_DOMAIN, {CLIMATE_DOMAIN: {"platform": HMIPC_DOMAIN}} + ) + is True + ) + assert not hass.data.get(HMIPC_DOMAIN) + + async def test_hmip_heating_group(hass, default_mock_hap): """Test HomematicipHeatingGroup.""" entity_id = "climate.badezimmer" @@ -153,6 +167,7 @@ async def test_hmip_climate_services(hass, mock_hap_with_service): ) assert home.mock_calls[-1][0] == "activate_absence_with_duration" assert home.mock_calls[-1][1] == (60,) + assert len(home._connection.mock_calls) == 1 # pylint: disable=W0212 await hass.services.async_call( "homematicip_cloud", @@ -162,6 +177,7 @@ async def test_hmip_climate_services(hass, mock_hap_with_service): ) assert home.mock_calls[-1][0] == "activate_absence_with_duration" assert home.mock_calls[-1][1] == (60,) + assert len(home._connection.mock_calls) == 2 # pylint: disable=W0212 await hass.services.async_call( "homematicip_cloud", @@ -171,6 +187,7 @@ async def test_hmip_climate_services(hass, mock_hap_with_service): ) assert home.mock_calls[-1][0] == "activate_absence_with_period" assert home.mock_calls[-1][1] == (datetime.datetime(2019, 2, 17, 14, 0),) + assert len(home._connection.mock_calls) == 3 # pylint: disable=W0212 await hass.services.async_call( "homematicip_cloud", @@ -180,6 +197,7 @@ async def test_hmip_climate_services(hass, mock_hap_with_service): ) assert home.mock_calls[-1][0] == "activate_absence_with_period" assert home.mock_calls[-1][1] == (datetime.datetime(2019, 2, 17, 14, 0),) + assert len(home._connection.mock_calls) == 4 # pylint: disable=W0212 await hass.services.async_call( "homematicip_cloud", @@ -189,6 +207,7 @@ async def test_hmip_climate_services(hass, mock_hap_with_service): ) assert home.mock_calls[-1][0] == "activate_vacation" assert home.mock_calls[-1][1] == (datetime.datetime(2019, 2, 17, 14, 0), 18.5) + assert len(home._connection.mock_calls) == 5 # pylint: disable=W0212 await hass.services.async_call( "homematicip_cloud", @@ -198,6 +217,7 @@ async def test_hmip_climate_services(hass, mock_hap_with_service): ) assert home.mock_calls[-1][0] == "activate_vacation" assert home.mock_calls[-1][1] == (datetime.datetime(2019, 2, 17, 14, 0), 18.5) + assert len(home._connection.mock_calls) == 6 # pylint: disable=W0212 await hass.services.async_call( "homematicip_cloud", @@ -207,12 +227,14 @@ async def test_hmip_climate_services(hass, mock_hap_with_service): ) assert home.mock_calls[-1][0] == "deactivate_absence" assert home.mock_calls[-1][1] == () + assert len(home._connection.mock_calls) == 7 # pylint: disable=W0212 await hass.services.async_call( "homematicip_cloud", "deactivate_eco_mode", blocking=True ) assert home.mock_calls[-1][0] == "deactivate_absence" assert home.mock_calls[-1][1] == () + assert len(home._connection.mock_calls) == 8 # pylint: disable=W0212 await hass.services.async_call( "homematicip_cloud", @@ -222,9 +244,23 @@ async def test_hmip_climate_services(hass, mock_hap_with_service): ) assert home.mock_calls[-1][0] == "deactivate_vacation" assert home.mock_calls[-1][1] == () + assert len(home._connection.mock_calls) == 9 # pylint: disable=W0212 await hass.services.async_call( "homematicip_cloud", "deactivate_vacation", blocking=True ) assert home.mock_calls[-1][0] == "deactivate_vacation" assert home.mock_calls[-1][1] == () + assert len(home._connection.mock_calls) == 10 # pylint: disable=W0212 + + not_existing_hap_id = "5555F7110000000000000001" + await hass.services.async_call( + "homematicip_cloud", + "deactivate_vacation", + {"accesspoint_id": not_existing_hap_id}, + blocking=True, + ) + assert home.mock_calls[-1][0] == "deactivate_vacation" + assert home.mock_calls[-1][1] == () + # There is no further call on connection. + assert len(home._connection.mock_calls) == 10 # pylint: disable=W0212 diff --git a/tests/components/homematicip_cloud/test_cover.py b/tests/components/homematicip_cloud/test_cover.py index 7bfb842a0df..22922303f9e 100644 --- a/tests/components/homematicip_cloud/test_cover.py +++ b/tests/components/homematicip_cloud/test_cover.py @@ -2,12 +2,26 @@ from homeassistant.components.cover import ( ATTR_CURRENT_POSITION, ATTR_CURRENT_TILT_POSITION, + DOMAIN as COVER_DOMAIN, ) +from homeassistant.components.homematicip_cloud import DOMAIN as HMIPC_DOMAIN from homeassistant.const import STATE_CLOSED, STATE_OPEN +from homeassistant.setup import async_setup_component from .helper import async_manipulate_test_data, get_and_check_entity_basics +async def test_manually_configured_platform(hass): + """Test that we do not set up an access point.""" + assert ( + await async_setup_component( + hass, COVER_DOMAIN, {COVER_DOMAIN: {"platform": HMIPC_DOMAIN}} + ) + is True + ) + assert not hass.data.get(HMIPC_DOMAIN) + + async def test_hmip_cover_shutter(hass, default_mock_hap): """Test HomematicipCoverShutte.""" entity_id = "cover.sofa_links" diff --git a/tests/components/homematicip_cloud/test_device.py b/tests/components/homematicip_cloud/test_device.py index 81c35f8e2a9..812f32a3344 100644 --- a/tests/components/homematicip_cloud/test_device.py +++ b/tests/components/homematicip_cloud/test_device.py @@ -2,6 +2,7 @@ from homeassistant.const import STATE_ON, STATE_UNAVAILABLE from homeassistant.helpers import device_registry as dr, entity_registry as er +from .conftest import get_mock_hap from .helper import async_manipulate_test_data, get_and_check_entity_basics @@ -109,3 +110,23 @@ async def test_hap_reconnected(hass, default_mock_hap): await hass.async_block_till_done() ha_state = hass.states.get(entity_id) assert ha_state.state == STATE_ON + + +async def test_hap_with_name(hass, mock_connection, hmip_config_entry): + """Test hap with name.""" + home_name = "TestName" + entity_id = f"light.{home_name.lower()}_treppe" + entity_name = f"{home_name} Treppe" + device_model = "HmIP-BSL" + + hmip_config_entry.data["name"] = home_name + mock_hap = await get_mock_hap(hass, mock_connection, hmip_config_entry) + assert mock_hap + + ha_state, hmip_device = get_and_check_entity_basics( + hass, mock_hap, entity_id, entity_name, device_model + ) + + assert hmip_device + assert ha_state.state == STATE_ON + assert ha_state.attributes["friendly_name"] == entity_name diff --git a/tests/components/homematicip_cloud/test_hap.py b/tests/components/homematicip_cloud/test_hap.py index cd8ead40c43..90f557b1f93 100644 --- a/tests/components/homematicip_cloud/test_hap.py +++ b/tests/components/homematicip_cloud/test_hap.py @@ -1,11 +1,24 @@ """Test HomematicIP Cloud accesspoint.""" -from unittest.mock import Mock, patch +from asynctest import Mock, patch +from homematicip.aio.auth import AsyncAuth +from homematicip.base.base_connection import HmipConnectionError import pytest -from homeassistant.components.homematicip_cloud import const, errors, hap as hmipc +from homeassistant.components.homematicip_cloud import ( + DOMAIN as HMIPC_DOMAIN, + const, + errors, + hap as hmipc, +) +from homeassistant.components.homematicip_cloud.hap import ( + HomematicipAuth, + HomematicipHAP, +) from homeassistant.exceptions import ConfigEntryNotReady +from .helper import HAPID, HAPPIN + from tests.common import mock_coro, mock_coro_func @@ -53,6 +66,22 @@ async def test_auth_auth_check_and_register(hass): assert await hap.async_register() == "ABC" +async def test_auth_auth_check_and_register_with_exception(hass): + """Test auth client registration.""" + config = { + const.HMIPC_HAPID: "ABC123", + const.HMIPC_PIN: "123", + const.HMIPC_NAME: "hmip", + } + hap = hmipc.HomematicipAuth(hass, config) + hap.auth = Mock(spec=AsyncAuth) + with patch.object( + hap.auth, "isRequestAcknowledged", side_effect=HmipConnectionError + ), patch.object(hap.auth, "requestAuthToken", side_effect=HmipConnectionError): + assert await hap.async_checkbutton() is False + assert await hap.async_register() is False + + async def test_hap_setup_works(aioclient_mock): """Test a successful setup of a accesspoint.""" hass = Mock() @@ -121,3 +150,78 @@ async def test_hap_reset_unloads_entry_if_setup(): await hap.async_reset() assert len(hass.config_entries.async_forward_entry_unload.mock_calls) == 8 + + +async def test_hap_create(hass, hmip_config_entry, simple_mock_home): + """Mock AsyncHome to execute get_hap.""" + hass.config.components.add(HMIPC_DOMAIN) + hap = HomematicipHAP(hass, hmip_config_entry) + assert hap + with patch( + "homeassistant.components.homematicip_cloud.hap.AsyncHome", + return_value=simple_mock_home, + ), patch.object(hap, "async_connect", return_value=mock_coro(None)): + assert await hap.async_setup() is True + + +async def test_hap_create_exception(hass, hmip_config_entry, simple_mock_home): + """Mock AsyncHome to execute get_hap.""" + hass.config.components.add(HMIPC_DOMAIN) + hap = HomematicipHAP(hass, hmip_config_entry) + assert hap + + with patch.object(hap, "get_hap", side_effect=HmipConnectionError), pytest.raises( + HmipConnectionError + ): + await hap.async_setup() + + simple_mock_home.init.side_effect = HmipConnectionError + with patch( + "homeassistant.components.homematicip_cloud.hap.AsyncHome", + return_value=simple_mock_home, + ), pytest.raises(ConfigEntryNotReady): + await hap.async_setup() + + +async def test_auth_create(hass, simple_mock_auth): + """Mock AsyncAuth to execute get_auth.""" + config = { + const.HMIPC_HAPID: HAPID, + const.HMIPC_PIN: HAPPIN, + const.HMIPC_NAME: "hmip", + } + hmip_auth = HomematicipAuth(hass, config) + assert hmip_auth + + with patch( + "homeassistant.components.homematicip_cloud.hap.AsyncAuth", + return_value=simple_mock_auth, + ): + assert await hmip_auth.async_setup() is True + await hass.async_block_till_done() + assert hmip_auth.auth.pin == HAPPIN + + +async def test_auth_create_exception(hass, simple_mock_auth): + """Mock AsyncAuth to execute get_auth.""" + config = { + const.HMIPC_HAPID: HAPID, + const.HMIPC_PIN: HAPPIN, + const.HMIPC_NAME: "hmip", + } + hmip_auth = HomematicipAuth(hass, config) + simple_mock_auth.connectionRequest.side_effect = HmipConnectionError + assert hmip_auth + with patch( + "homeassistant.components.homematicip_cloud.hap.AsyncAuth", + return_value=simple_mock_auth, + ): + assert await hmip_auth.async_setup() is True + await hass.async_block_till_done() + assert hmip_auth.auth is False + + with patch( + "homeassistant.components.homematicip_cloud.hap.AsyncAuth", + return_value=simple_mock_auth, + ): + assert await hmip_auth.get_auth(hass, HAPID, HAPPIN) is False diff --git a/tests/components/homematicip_cloud/test_light.py b/tests/components/homematicip_cloud/test_light.py index a8d4984520c..17e92d9d99d 100644 --- a/tests/components/homematicip_cloud/test_light.py +++ b/tests/components/homematicip_cloud/test_light.py @@ -1,16 +1,33 @@ """Tests for HomematicIP Cloud light.""" from homematicip.base.enums import RGBColorState +from homeassistant.components.homematicip_cloud import DOMAIN as HMIPC_DOMAIN from homeassistant.components.homematicip_cloud.light import ( ATTR_ENERGY_COUNTER, ATTR_POWER_CONSUMPTION, ) -from homeassistant.components.light import ATTR_BRIGHTNESS, ATTR_COLOR_NAME +from homeassistant.components.light import ( + ATTR_BRIGHTNESS, + ATTR_COLOR_NAME, + DOMAIN as LIGHT_DOMAIN, +) from homeassistant.const import STATE_OFF, STATE_ON +from homeassistant.setup import async_setup_component from .helper import async_manipulate_test_data, get_and_check_entity_basics +async def test_manually_configured_platform(hass): + """Test that we do not set up an access point.""" + assert ( + await async_setup_component( + hass, LIGHT_DOMAIN, {LIGHT_DOMAIN: {"platform": HMIPC_DOMAIN}} + ) + is True + ) + assert not hass.data.get(HMIPC_DOMAIN) + + async def test_hmip_light(hass, default_mock_hap): """Test HomematicipLight.""" entity_id = "light.treppe" @@ -114,6 +131,11 @@ async def test_hmip_notification_light(hass, default_mock_hap): ha_state = hass.states.get(entity_id) assert ha_state.state == STATE_OFF + await async_manipulate_test_data(hass, hmip_device, "dimLevel", None, 2) + ha_state = hass.states.get(entity_id) + assert ha_state.state == STATE_OFF + assert not ha_state.attributes.get(ATTR_BRIGHTNESS) + async def test_hmip_dimmer(hass, default_mock_hap): """Test HomematicipDimmer.""" @@ -158,6 +180,11 @@ async def test_hmip_dimmer(hass, default_mock_hap): ha_state = hass.states.get(entity_id) assert ha_state.state == STATE_OFF + await async_manipulate_test_data(hass, hmip_device, "dimLevel", None) + ha_state = hass.states.get(entity_id) + assert ha_state.state == STATE_OFF + assert not ha_state.attributes.get(ATTR_BRIGHTNESS) + async def test_hmip_light_measuring(hass, default_mock_hap): """Test HomematicipLightMeasuring.""" diff --git a/tests/components/homematicip_cloud/test_sensor.py b/tests/components/homematicip_cloud/test_sensor.py index d4307477975..8412cd19f4d 100644 --- a/tests/components/homematicip_cloud/test_sensor.py +++ b/tests/components/homematicip_cloud/test_sensor.py @@ -1,4 +1,7 @@ """Tests for HomematicIP Cloud sensor.""" +from homematicip.base.enums import ValveState + +from homeassistant.components.homematicip_cloud import DOMAIN as HMIPC_DOMAIN from homeassistant.components.homematicip_cloud.sensor import ( ATTR_LEFT_COUNTER, ATTR_RIGHT_COUNTER, @@ -6,11 +9,24 @@ from homeassistant.components.homematicip_cloud.sensor import ( ATTR_WIND_DIRECTION, ATTR_WIND_DIRECTION_VARIATION, ) +from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN from homeassistant.const import ATTR_UNIT_OF_MEASUREMENT, POWER_WATT, TEMP_CELSIUS +from homeassistant.setup import async_setup_component from .helper import async_manipulate_test_data, get_and_check_entity_basics +async def test_manually_configured_platform(hass): + """Test that we do not set up an access point.""" + assert ( + await async_setup_component( + hass, SENSOR_DOMAIN, {SENSOR_DOMAIN: {"platform": HMIPC_DOMAIN}} + ) + is True + ) + assert not hass.data.get(HMIPC_DOMAIN) + + async def test_hmip_accesspoint_status(hass, default_mock_hap): """Test HomematicipSwitch.""" entity_id = "sensor.access_point" @@ -50,6 +66,16 @@ async def test_hmip_heating_thermostat(hass, default_mock_hap): ha_state = hass.states.get(entity_id) assert ha_state.state == "nn" + await async_manipulate_test_data( + hass, hmip_device, "valveState", ValveState.ADAPTION_DONE + ) + ha_state = hass.states.get(entity_id) + assert ha_state.state == "37" + + await async_manipulate_test_data(hass, hmip_device, "lowBat", True) + ha_state = hass.states.get(entity_id) + assert ha_state.attributes["icon"] == "mdi:battery-outline" + async def test_hmip_humidity_sensor(hass, default_mock_hap): """Test HomematicipHumiditySensor.""" diff --git a/tests/components/homematicip_cloud/test_switch.py b/tests/components/homematicip_cloud/test_switch.py index 15eaf6da04c..9e33d1d9587 100644 --- a/tests/components/homematicip_cloud/test_switch.py +++ b/tests/components/homematicip_cloud/test_switch.py @@ -1,13 +1,30 @@ """Tests for HomematicIP Cloud switch.""" +from homeassistant.components.homematicip_cloud import DOMAIN as HMIPC_DOMAIN from homeassistant.components.homematicip_cloud.device import ( ATTR_GROUP_MEMBER_UNREACHABLE, ) -from homeassistant.components.switch import ATTR_CURRENT_POWER_W, ATTR_TODAY_ENERGY_KWH +from homeassistant.components.switch import ( + ATTR_CURRENT_POWER_W, + ATTR_TODAY_ENERGY_KWH, + DOMAIN as SWITCH_DOMAIN, +) from homeassistant.const import STATE_OFF, STATE_ON +from homeassistant.setup import async_setup_component from .helper import async_manipulate_test_data, get_and_check_entity_basics +async def test_manually_configured_platform(hass): + """Test that we do not set up an access point.""" + assert ( + await async_setup_component( + hass, SWITCH_DOMAIN, {SWITCH_DOMAIN: {"platform": HMIPC_DOMAIN}} + ) + is True + ) + assert not hass.data.get(HMIPC_DOMAIN) + + async def test_hmip_switch(hass, default_mock_hap): """Test HomematicipSwitch.""" entity_id = "switch.schrank" diff --git a/tests/components/homematicip_cloud/test_weather.py b/tests/components/homematicip_cloud/test_weather.py index 0b5d59215bb..9427a2d05bf 100644 --- a/tests/components/homematicip_cloud/test_weather.py +++ b/tests/components/homematicip_cloud/test_weather.py @@ -1,15 +1,29 @@ """Tests for HomematicIP Cloud weather.""" +from homeassistant.components.homematicip_cloud import DOMAIN as HMIPC_DOMAIN from homeassistant.components.weather import ( ATTR_WEATHER_ATTRIBUTION, ATTR_WEATHER_HUMIDITY, ATTR_WEATHER_TEMPERATURE, ATTR_WEATHER_WIND_BEARING, ATTR_WEATHER_WIND_SPEED, + DOMAIN as WEATHER_DOMAIN, ) +from homeassistant.setup import async_setup_component from .helper import async_manipulate_test_data, get_and_check_entity_basics +async def test_manually_configured_platform(hass): + """Test that we do not set up an access point.""" + assert ( + await async_setup_component( + hass, WEATHER_DOMAIN, {WEATHER_DOMAIN: {"platform": HMIPC_DOMAIN}} + ) + is True + ) + assert not hass.data.get(HMIPC_DOMAIN) + + async def test_hmip_weather_sensor(hass, default_mock_hap): """Test HomematicipWeatherSensor.""" entity_id = "weather.weather_sensor_plus"