From dab5289177c7486dd2c0a350127cba01aba1294e Mon Sep 17 00:00:00 2001 From: rappenze Date: Fri, 25 Oct 2024 15:10:20 +0200 Subject: [PATCH] Add opening closing state to fibaro cover (#126958) --- homeassistant/components/fibaro/cover.py | 22 ++++++ tests/components/fibaro/conftest.py | 30 ++++++++ tests/components/fibaro/test_cover.py | 98 ++++++++++++++++++++++++ 3 files changed, 150 insertions(+) create mode 100644 tests/components/fibaro/test_cover.py diff --git a/homeassistant/components/fibaro/cover.py b/homeassistant/components/fibaro/cover.py index fc28e57af70..c787ca70272 100644 --- a/homeassistant/components/fibaro/cover.py +++ b/homeassistant/components/fibaro/cover.py @@ -79,6 +79,28 @@ class FibaroCover(FibaroEntity, CoverEntity): """Return the current tilt position for venetian blinds.""" return self.bound(self.level2) + @property + def is_opening(self) -> bool | None: + """Return if the cover is opening or not. + + Be aware that this property is only available for some modern devices. + For example the Fibaro Roller Shutter 4 reports this correctly. + """ + if self.fibaro_device.state.has_value: + return self.fibaro_device.state.str_value().lower() == "opening" + return None + + @property + def is_closing(self) -> bool | None: + """Return if the cover is closing or not. + + Be aware that this property is only available for some modern devices. + For example the Fibaro Roller Shutter 4 reports this correctly. + """ + if self.fibaro_device.state.has_value: + return self.fibaro_device.state.str_value().lower() == "closing" + return None + def set_cover_position(self, **kwargs: Any) -> None: """Move the cover to a specific position.""" self.set_level(cast(int, kwargs.get(ATTR_POSITION))) diff --git a/tests/components/fibaro/conftest.py b/tests/components/fibaro/conftest.py index df8b12e2167..ac10d4fc79d 100644 --- a/tests/components/fibaro/conftest.py +++ b/tests/components/fibaro/conftest.py @@ -76,6 +76,36 @@ def mock_power_sensor() -> Mock: return sensor +@pytest.fixture +def mock_cover() -> Mock: + """Fixture for a cover.""" + cover = Mock() + cover.fibaro_id = 3 + cover.parent_fibaro_id = 0 + cover.name = "Test cover" + cover.room_id = 1 + cover.dead = False + cover.visible = True + cover.enabled = True + cover.type = "com.fibaro.FGR" + cover.base_type = "com.fibaro.device" + cover.properties = {"manufacturer": ""} + cover.actions = {"open": 0, "close": 0} + cover.supported_features = {} + value_mock = Mock() + value_mock.has_value = True + value_mock.int_value.return_value = 20 + cover.value = value_mock + value2_mock = Mock() + value2_mock.has_value = False + cover.value_2 = value2_mock + state_mock = Mock() + state_mock.has_value = True + state_mock.str_value.return_value = "opening" + cover.state = state_mock + return cover + + @pytest.fixture def mock_config_entry(hass: HomeAssistant) -> MockConfigEntry: """Return the default mocked config entry.""" diff --git a/tests/components/fibaro/test_cover.py b/tests/components/fibaro/test_cover.py new file mode 100644 index 00000000000..d5b08f7d1f8 --- /dev/null +++ b/tests/components/fibaro/test_cover.py @@ -0,0 +1,98 @@ +"""Test the Fibaro cover platform.""" + +from unittest.mock import Mock, patch + +from homeassistant.components.cover import CoverState +from homeassistant.const import Platform +from homeassistant.core import HomeAssistant +from homeassistant.helpers import entity_registry as er + +from .conftest import init_integration + +from tests.common import MockConfigEntry + + +async def test_cover_setup( + hass: HomeAssistant, + entity_registry: er.EntityRegistry, + mock_fibaro_client: Mock, + mock_config_entry: MockConfigEntry, + mock_cover: Mock, + mock_room: Mock, +) -> None: + """Test that the cover creates an entity.""" + + # Arrange + mock_fibaro_client.read_rooms.return_value = [mock_room] + mock_fibaro_client.read_devices.return_value = [mock_cover] + + with patch("homeassistant.components.fibaro.PLATFORMS", [Platform.COVER]): + # Act + await init_integration(hass, mock_config_entry) + # Assert + entry = entity_registry.async_get("cover.room_1_test_cover_3") + assert entry + assert entry.unique_id == "hc2_111111.3" + assert entry.original_name == "Room 1 Test cover" + + +async def test_cover_opening( + hass: HomeAssistant, + mock_fibaro_client: Mock, + mock_config_entry: MockConfigEntry, + mock_cover: Mock, + mock_room: Mock, +) -> None: + """Test that the cover opening state is reported.""" + + # Arrange + mock_fibaro_client.read_rooms.return_value = [mock_room] + mock_fibaro_client.read_devices.return_value = [mock_cover] + + with patch("homeassistant.components.fibaro.PLATFORMS", [Platform.COVER]): + # Act + await init_integration(hass, mock_config_entry) + # Assert + assert hass.states.get("cover.room_1_test_cover_3").state == CoverState.OPENING + + +async def test_cover_opening_closing_none( + hass: HomeAssistant, + mock_fibaro_client: Mock, + mock_config_entry: MockConfigEntry, + mock_cover: Mock, + mock_room: Mock, +) -> None: + """Test that the cover opening closing states return None if not available.""" + + # Arrange + mock_fibaro_client.read_rooms.return_value = [mock_room] + mock_cover.state.has_value = False + mock_fibaro_client.read_devices.return_value = [mock_cover] + + with patch("homeassistant.components.fibaro.PLATFORMS", [Platform.COVER]): + # Act + await init_integration(hass, mock_config_entry) + # Assert + assert hass.states.get("cover.room_1_test_cover_3").state == CoverState.OPEN + + +async def test_cover_closing( + hass: HomeAssistant, + mock_fibaro_client: Mock, + mock_config_entry: MockConfigEntry, + mock_cover: Mock, + mock_room: Mock, +) -> None: + """Test that the cover closing state is reported.""" + + # Arrange + mock_fibaro_client.read_rooms.return_value = [mock_room] + mock_cover.state.str_value.return_value = "closing" + mock_fibaro_client.read_devices.return_value = [mock_cover] + + with patch("homeassistant.components.fibaro.PLATFORMS", [Platform.COVER]): + # Act + await init_integration(hass, mock_config_entry) + # Assert + assert hass.states.get("cover.room_1_test_cover_3").state == CoverState.CLOSING