From 8dd5f25da988dc933a95ee176703b887def3047c Mon Sep 17 00:00:00 2001
From: Guido Schmitz <Shutgun@users.noreply.github.com>
Date: Wed, 29 Jun 2022 15:46:32 +0200
Subject: [PATCH] Add cover tests for devolo_home_control (#72428)

---
 .coveragerc                                   |   1 -
 tests/components/devolo_home_control/mocks.py |  26 ++++-
 .../devolo_home_control/test_cover.py         | 103 ++++++++++++++++++
 3 files changed, 128 insertions(+), 2 deletions(-)
 create mode 100644 tests/components/devolo_home_control/test_cover.py

diff --git a/.coveragerc b/.coveragerc
index 02c643ae757..eae8060449a 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -210,7 +210,6 @@ omit =
     homeassistant/components/denonavr/media_player.py
     homeassistant/components/denonavr/receiver.py
     homeassistant/components/deutsche_bahn/sensor.py
-    homeassistant/components/devolo_home_control/cover.py
     homeassistant/components/devolo_home_control/light.py
     homeassistant/components/devolo_home_control/sensor.py
     homeassistant/components/devolo_home_control/switch.py
diff --git a/tests/components/devolo_home_control/mocks.py b/tests/components/devolo_home_control/mocks.py
index b43cb77ad71..e9dae0b70b1 100644
--- a/tests/components/devolo_home_control/mocks.py
+++ b/tests/components/devolo_home_control/mocks.py
@@ -51,7 +51,6 @@ class MultiLevelSwitchPropertyMock(MultiLevelSwitchProperty):
         self.element_uid = "Test"
         self.min = 4
         self.max = 24
-        self.switch_type = "temperature"
         self._value = 20
         self._logger = MagicMock()
 
@@ -120,9 +119,21 @@ class ClimateMock(DeviceMock):
         super().__init__()
         self.device_model_uid = "devolo.model.Room:Thermostat"
         self.multi_level_switch_property = {"Test": MultiLevelSwitchPropertyMock()}
+        self.multi_level_switch_property["Test"].switch_type = "temperature"
         self.multi_level_sensor_property = {"Test": MultiLevelSensorPropertyMock()}
 
 
+class CoverMock(DeviceMock):
+    """devolo Home Control cover device mock."""
+
+    def __init__(self) -> None:
+        """Initialize the mock."""
+        super().__init__()
+        self.multi_level_switch_property = {
+            "devolo.Blinds": MultiLevelSwitchPropertyMock()
+        }
+
+
 class RemoteControlMock(DeviceMock):
     """devolo Home Control remote control device mock."""
 
@@ -195,6 +206,19 @@ class HomeControlMockClimate(HomeControlMock):
         self.publisher.unregister = MagicMock()
 
 
+class HomeControlMockCover(HomeControlMock):
+    """devolo Home Control gateway mock with cover devices."""
+
+    def __init__(self, **kwargs: Any) -> None:
+        """Initialize the mock."""
+        super().__init__()
+        self.devices = {
+            "Test": CoverMock(),
+        }
+        self.publisher = Publisher(self.devices.keys())
+        self.publisher.unregister = MagicMock()
+
+
 class HomeControlMockRemoteControl(HomeControlMock):
     """devolo Home Control gateway mock with remote control device."""
 
diff --git a/tests/components/devolo_home_control/test_cover.py b/tests/components/devolo_home_control/test_cover.py
new file mode 100644
index 00000000000..1c05c00370b
--- /dev/null
+++ b/tests/components/devolo_home_control/test_cover.py
@@ -0,0 +1,103 @@
+"""Tests for the devolo Home Control cover platform."""
+from unittest.mock import patch
+
+from homeassistant.components.cover import ATTR_CURRENT_POSITION, ATTR_POSITION, DOMAIN
+from homeassistant.const import (
+    ATTR_ENTITY_ID,
+    SERVICE_CLOSE_COVER,
+    SERVICE_OPEN_COVER,
+    SERVICE_SET_COVER_POSITION,
+    STATE_CLOSED,
+    STATE_OPEN,
+    STATE_UNAVAILABLE,
+)
+from homeassistant.core import HomeAssistant
+
+from . import configure_integration
+from .mocks import HomeControlMock, HomeControlMockCover
+
+
+async def test_cover(hass: HomeAssistant):
+    """Test setup and state change of a cover device."""
+    entry = configure_integration(hass)
+    test_gateway = HomeControlMockCover()
+    test_gateway.devices["Test"].multi_level_switch_property["devolo.Blinds"].value = 20
+    with patch(
+        "homeassistant.components.devolo_home_control.HomeControl",
+        side_effect=[test_gateway, HomeControlMock()],
+    ):
+        await hass.config_entries.async_setup(entry.entry_id)
+        await hass.async_block_till_done()
+
+    state = hass.states.get(f"{DOMAIN}.test")
+    assert state is not None
+    assert state.state == STATE_OPEN
+    assert (
+        state.attributes[ATTR_CURRENT_POSITION]
+        == test_gateway.devices["Test"]
+        .multi_level_switch_property["devolo.Blinds"]
+        .value
+    )
+
+    # Emulate websocket message: position changed
+    test_gateway.publisher.dispatch("Test", ("devolo.Blinds", 0.0))
+    await hass.async_block_till_done()
+    state = hass.states.get(f"{DOMAIN}.test")
+    assert state.state == STATE_CLOSED
+    assert state.attributes[ATTR_CURRENT_POSITION] == 0.0
+
+    # Test setting position
+    with patch(
+        "devolo_home_control_api.properties.multi_level_switch_property.MultiLevelSwitchProperty.set"
+    ) as set_value:
+        await hass.services.async_call(
+            DOMAIN,
+            SERVICE_OPEN_COVER,
+            {ATTR_ENTITY_ID: f"{DOMAIN}.test"},
+            blocking=True,
+        )  # In reality, this leads to a websocket message like already tested above
+        set_value.assert_called_once_with(100)
+
+        set_value.reset_mock()
+        await hass.services.async_call(
+            DOMAIN,
+            SERVICE_CLOSE_COVER,
+            {ATTR_ENTITY_ID: f"{DOMAIN}.test"},
+            blocking=True,
+        )  # In reality, this leads to a websocket message like already tested above
+        set_value.assert_called_once_with(0)
+
+        set_value.reset_mock()
+        await hass.services.async_call(
+            DOMAIN,
+            SERVICE_SET_COVER_POSITION,
+            {ATTR_ENTITY_ID: f"{DOMAIN}.test", ATTR_POSITION: 50},
+            blocking=True,
+        )  # In reality, this leads to a websocket message like already tested above
+        set_value.assert_called_once_with(50)
+
+    # Emulate websocket message: device went offline
+    test_gateway.devices["Test"].status = 1
+    test_gateway.publisher.dispatch("Test", ("Status", False, "status"))
+    await hass.async_block_till_done()
+    assert hass.states.get(f"{DOMAIN}.test").state == STATE_UNAVAILABLE
+
+
+async def test_remove_from_hass(hass: HomeAssistant):
+    """Test removing entity."""
+    entry = configure_integration(hass)
+    test_gateway = HomeControlMockCover()
+    with patch(
+        "homeassistant.components.devolo_home_control.HomeControl",
+        side_effect=[test_gateway, HomeControlMock()],
+    ):
+        await hass.config_entries.async_setup(entry.entry_id)
+        await hass.async_block_till_done()
+
+    state = hass.states.get(f"{DOMAIN}.test")
+    assert state is not None
+    await hass.config_entries.async_remove(entry.entry_id)
+    await hass.async_block_till_done()
+
+    assert len(hass.states.async_all()) == 0
+    assert test_gateway.publisher.unregister.call_count == 1
-- 
GitLab