diff --git a/.coveragerc b/.coveragerc index 5b5096ee582..507e0dc8953 100644 --- a/.coveragerc +++ b/.coveragerc @@ -198,7 +198,6 @@ omit = homeassistant/components/denonavr/__init__.py homeassistant/components/denonavr/media_player.py homeassistant/components/denonavr/receiver.py - homeassistant/components/devolo_home_control/switch.py homeassistant/components/digital_ocean/* homeassistant/components/discogs/sensor.py homeassistant/components/discord/__init__.py diff --git a/tests/components/devolo_home_control/mocks.py b/tests/components/devolo_home_control/mocks.py index 0fc01d61841..aef687936e4 100644 --- a/tests/components/devolo_home_control/mocks.py +++ b/tests/components/devolo_home_control/mocks.py @@ -42,6 +42,7 @@ class BinarySwitchPropertyMock(BinarySwitchProperty): """Initialize the mock.""" self._logger = MagicMock() self.element_uid = "Test" + self.state = False class ConsumptionPropertyMock(ConsumptionProperty): @@ -233,6 +234,17 @@ class SensorMock(DeviceMock): } +class SwitchMock(DeviceMock): + """devolo Home Control switch device mock.""" + + def __init__(self) -> None: + """Initialize the mock.""" + super().__init__() + self.binary_switch_property = { + "devolo.BinarySwitch:Test": BinarySwitchPropertyMock() + } + + class HomeControlMock(HomeControl): """devolo Home Control gateway mock.""" @@ -353,3 +365,14 @@ class HomeControlMockSiren(HomeControlMock): self.devices = {"Test": SirenMock()} self.publisher = Publisher(self.devices.keys()) self.publisher.unregister = MagicMock() + + +class HomeControlMockSwitch(HomeControlMock): + """devolo Home Control gateway mock with switch device.""" + + def __init__(self, **kwargs: Any) -> None: + """Initialize the mock.""" + super().__init__() + self.devices = {"Test": SwitchMock()} + self.publisher = Publisher(self.devices.keys()) + self.publisher.unregister = MagicMock() diff --git a/tests/components/devolo_home_control/test_switch.py b/tests/components/devolo_home_control/test_switch.py new file mode 100644 index 00000000000..62de9038483 --- /dev/null +++ b/tests/components/devolo_home_control/test_switch.py @@ -0,0 +1,86 @@ +"""Tests for the devolo Home Control switch platform.""" +from unittest.mock import patch + +from homeassistant.components.switch import DOMAIN +from homeassistant.const import ( + ATTR_ENTITY_ID, + SERVICE_TURN_OFF, + SERVICE_TURN_ON, + STATE_OFF, + STATE_ON, + STATE_UNAVAILABLE, +) +from homeassistant.core import HomeAssistant + +from . import configure_integration +from .mocks import HomeControlMock, HomeControlMockSwitch + + +async def test_switch(hass: HomeAssistant): + """Test setup and state change of a switch device.""" + entry = configure_integration(hass) + test_gateway = HomeControlMockSwitch() + 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_OFF + + # Emulate websocket message: switched on + test_gateway.devices["Test"].binary_switch_property[ + "devolo.BinarySwitch:Test" + ].state = True + test_gateway.publisher.dispatch("Test", ("devolo.BinarySwitch:Test", True)) + await hass.async_block_till_done() + assert hass.states.get(f"{DOMAIN}.test").state == STATE_ON + + with patch( + "devolo_home_control_api.properties.binary_switch_property.BinarySwitchProperty.set" + ) as set_value: + await hass.services.async_call( + DOMAIN, + SERVICE_TURN_ON, + {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(state=True) + + set_value.reset_mock() + await hass.services.async_call( + DOMAIN, + SERVICE_TURN_OFF, + {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(state=False) + + # 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 = HomeControlMockSwitch() + 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