diff --git a/tests/components/comelit/const.py b/tests/components/comelit/const.py index d1bd4f95da3..d06e6cfd8cb 100644 --- a/tests/components/comelit/const.py +++ b/tests/components/comelit/const.py @@ -29,7 +29,24 @@ VEDO_PIN = 5678 FAKE_PIN = 0000 BRIDGE_DEVICE_QUERY = { - CLIMATE: {}, + CLIMATE: { + 0: ComelitSerialBridgeObject( + index=0, + name="Climate0", + status=0, + human_status="off", + type="climate", + val=[ + [221, 0, "U", "M", 50, 0, 0, "U"], + [650, 0, "O", "M", 500, 0, 0, "N"], + [0, 0], + ], + protected=0, + zone="Living room", + power=0.0, + power_unit=WATT, + ), + }, COVER: { 0: ComelitSerialBridgeObject( index=0, diff --git a/tests/components/comelit/snapshots/test_climate.ambr b/tests/components/comelit/snapshots/test_climate.ambr new file mode 100644 index 00000000000..e5201067ee1 --- /dev/null +++ b/tests/components/comelit/snapshots/test_climate.ambr @@ -0,0 +1,71 @@ +# serializer version: 1 +# name: test_all_entities[climate.climate0-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'hvac_modes': list([ + , + , + , + , + ]), + 'max_temp': 30, + 'min_temp': 5, + 'target_temp_step': 0.1, + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'climate', + 'entity_category': None, + 'entity_id': 'climate.climate0', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': None, + 'platform': 'comelit', + 'previous_unique_id': None, + 'supported_features': , + 'translation_key': None, + 'unique_id': 'serial_bridge_config_entry_id-0', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[climate.climate0-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'current_temperature': 22.1, + 'friendly_name': 'Climate0', + 'hvac_action': , + 'hvac_modes': list([ + , + , + , + , + ]), + 'max_temp': 30, + 'min_temp': 5, + 'supported_features': , + 'target_temp_step': 0.1, + 'temperature': 5.0, + }), + 'context': , + 'entity_id': 'climate.climate0', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'heat', + }) +# --- diff --git a/tests/components/comelit/snapshots/test_diagnostics.ambr b/tests/components/comelit/snapshots/test_diagnostics.ambr index 3a6af9c3b73..51ea646df9f 100644 --- a/tests/components/comelit/snapshots/test_diagnostics.ambr +++ b/tests/components/comelit/snapshots/test_diagnostics.ambr @@ -5,6 +5,43 @@ 'devices': list([ dict({ 'clima': list([ + dict({ + '0': dict({ + 'human_status': 'off', + 'name': 'Climate0', + 'power': 0.0, + 'power_unit': 'W', + 'protected': 0, + 'status': 0, + 'val': list([ + list([ + 221, + 0, + 'U', + 'M', + 50, + 0, + 0, + 'U', + ]), + list([ + 650, + 0, + 'O', + 'M', + 500, + 0, + 0, + 'N', + ]), + list([ + 0, + 0, + ]), + ]), + 'zone': 'Living room', + }), + }), ]), }), dict({ diff --git a/tests/components/comelit/test_climate.py b/tests/components/comelit/test_climate.py new file mode 100644 index 00000000000..44478d154f4 --- /dev/null +++ b/tests/components/comelit/test_climate.py @@ -0,0 +1,282 @@ +"""Tests for Comelit SimpleHome climate platform.""" + +from typing import Any +from unittest.mock import AsyncMock, patch + +from aiocomelit.api import ComelitSerialBridgeObject +from aiocomelit.const import CLIMATE, WATT +from freezegun.api import FrozenDateTimeFactory +import pytest +from syrupy import SnapshotAssertion + +from homeassistant.components.climate import ( + ATTR_HVAC_MODE, + DOMAIN as CLIMATE_DOMAIN, + SERVICE_SET_HVAC_MODE, + SERVICE_SET_TEMPERATURE, + HVACMode, +) +from homeassistant.components.comelit.const import SCAN_INTERVAL +from homeassistant.const import ATTR_ENTITY_ID, ATTR_TEMPERATURE, Platform +from homeassistant.core import HomeAssistant +from homeassistant.helpers import entity_registry as er + +from . import setup_integration + +from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_platform + +ENTITY_ID = "climate.climate0" + + +async def test_all_entities( + hass: HomeAssistant, + snapshot: SnapshotAssertion, + mock_serial_bridge: AsyncMock, + mock_serial_bridge_config_entry: MockConfigEntry, + entity_registry: er.EntityRegistry, +) -> None: + """Test all entities.""" + with patch("homeassistant.components.comelit.BRIDGE_PLATFORMS", [Platform.CLIMATE]): + await setup_integration(hass, mock_serial_bridge_config_entry) + + await snapshot_platform( + hass, + entity_registry, + snapshot(), + mock_serial_bridge_config_entry.entry_id, + ) + + +@pytest.mark.parametrize( + ("val", "mode", "temp"), + [ + ( + [ + [100, 0, "U", "M", 210, 0, 0, "U"], + [650, 0, "O", "M", 500, 0, 0, "N"], + [0, 0], + ], + HVACMode.HEAT, + 21.0, + ), + ( + [ + [100, 1, "U", "A", 210, 1, 0, "O"], + [650, 0, "O", "M", 500, 0, 0, "N"], + [0, 0], + ], + HVACMode.HEAT, + 21.0, + ), + ( + [ + [100, 0, "O", "A", 210, 0, 0, "O"], + [650, 0, "O", "M", 500, 0, 0, "N"], + [0, 0], + ], + HVACMode.OFF, + 21.0, + ), + ], +) +async def test_climate_data_update( + hass: HomeAssistant, + freezer: FrozenDateTimeFactory, + mock_serial_bridge: AsyncMock, + mock_serial_bridge_config_entry: MockConfigEntry, + val: list[Any, Any], + mode: HVACMode, + temp: float, +) -> None: + """Test climate data update.""" + await setup_integration(hass, mock_serial_bridge_config_entry) + + assert (state := hass.states.get(ENTITY_ID)) + assert state.state == HVACMode.HEAT + assert state.attributes[ATTR_TEMPERATURE] == 5.0 + + mock_serial_bridge.get_all_devices.return_value[CLIMATE] = { + 0: ComelitSerialBridgeObject( + index=0, + name="Climate0", + status=0, + human_status="off", + type="climate", + val=val, + protected=0, + zone="Living room", + power=0.0, + power_unit=WATT, + ), + } + + freezer.tick(SCAN_INTERVAL) + async_fire_time_changed(hass) + await hass.async_block_till_done(wait_background_tasks=True) + + assert (state := hass.states.get(ENTITY_ID)) + assert state.state == mode + assert state.attributes[ATTR_TEMPERATURE] == temp + + +async def test_climate_data_update_bad_data( + hass: HomeAssistant, + freezer: FrozenDateTimeFactory, + mock_serial_bridge: AsyncMock, + mock_serial_bridge_config_entry: MockConfigEntry, +) -> None: + """Test climate data update.""" + await setup_integration(hass, mock_serial_bridge_config_entry) + + assert (state := hass.states.get(ENTITY_ID)) + assert state.state == HVACMode.HEAT + assert state.attributes[ATTR_TEMPERATURE] == 5.0 + + mock_serial_bridge.get_all_devices.return_value[CLIMATE] = { + 0: ComelitSerialBridgeObject( + index=0, + name="Climate0", + status=0, + human_status="off", + type="climate", + val="bad_data", + protected=0, + zone="Living room", + power=0.0, + power_unit=WATT, + ), + } + + freezer.tick(SCAN_INTERVAL) + async_fire_time_changed(hass) + await hass.async_block_till_done(wait_background_tasks=True) + + assert (state := hass.states.get(ENTITY_ID)) + assert state.state == HVACMode.HEAT + assert state.attributes[ATTR_TEMPERATURE] == 5.0 + + +async def test_climate_set_temperature( + hass: HomeAssistant, + mock_serial_bridge: AsyncMock, + mock_serial_bridge_config_entry: MockConfigEntry, +) -> None: + """Test climate set temperature service.""" + + await setup_integration(hass, mock_serial_bridge_config_entry) + + assert (state := hass.states.get(ENTITY_ID)) + assert state.state == HVACMode.HEAT + assert state.attributes[ATTR_TEMPERATURE] == 5.0 + + # Test set temperature + await hass.services.async_call( + CLIMATE_DOMAIN, + SERVICE_SET_TEMPERATURE, + {ATTR_ENTITY_ID: ENTITY_ID, ATTR_TEMPERATURE: 23}, + blocking=True, + ) + mock_serial_bridge.set_clima_status.assert_called() + + assert (state := hass.states.get(ENTITY_ID)) + assert state.state == HVACMode.HEAT + assert state.attributes[ATTR_TEMPERATURE] == 23.0 + + +async def test_climate_set_temperature_when_off( + hass: HomeAssistant, + mock_serial_bridge: AsyncMock, + mock_serial_bridge_config_entry: MockConfigEntry, +) -> None: + """Test climate set temperature service when off.""" + + await setup_integration(hass, mock_serial_bridge_config_entry) + + assert (state := hass.states.get(ENTITY_ID)) + assert state.state == HVACMode.HEAT + assert state.attributes[ATTR_TEMPERATURE] == 5.0 + + # Switch climate off + await hass.services.async_call( + CLIMATE_DOMAIN, + SERVICE_SET_HVAC_MODE, + {ATTR_ENTITY_ID: ENTITY_ID, ATTR_HVAC_MODE: HVACMode.OFF}, + blocking=True, + ) + mock_serial_bridge.set_clima_status.assert_called() + + assert (state := hass.states.get(ENTITY_ID)) + assert state.state == HVACMode.OFF + + # Test set temperature + await hass.services.async_call( + CLIMATE_DOMAIN, + SERVICE_SET_TEMPERATURE, + {ATTR_ENTITY_ID: ENTITY_ID, ATTR_TEMPERATURE: 23}, + blocking=True, + ) + mock_serial_bridge.set_clima_status.assert_called() + + assert (state := hass.states.get(ENTITY_ID)) + assert state.state == HVACMode.OFF + + +async def test_climate_hvac_mode( + hass: HomeAssistant, + mock_serial_bridge: AsyncMock, + mock_serial_bridge_config_entry: MockConfigEntry, +) -> None: + """Test climate hvac mode service.""" + + await setup_integration(hass, mock_serial_bridge_config_entry) + + assert (state := hass.states.get(ENTITY_ID)) + assert state.state == HVACMode.HEAT + assert state.attributes[ATTR_TEMPERATURE] == 5.0 + + await hass.services.async_call( + CLIMATE_DOMAIN, + SERVICE_SET_HVAC_MODE, + {ATTR_ENTITY_ID: ENTITY_ID, ATTR_HVAC_MODE: HVACMode.OFF}, + blocking=True, + ) + mock_serial_bridge.set_clima_status.assert_called() + + assert (state := hass.states.get(ENTITY_ID)) + assert state.state == HVACMode.OFF + + +async def test_climate_hvac_mode_when_off( + hass: HomeAssistant, + mock_serial_bridge: AsyncMock, + mock_serial_bridge_config_entry: MockConfigEntry, +) -> None: + """Test climate hvac mode service when off.""" + + await setup_integration(hass, mock_serial_bridge_config_entry) + + assert (state := hass.states.get(ENTITY_ID)) + assert state.state == HVACMode.HEAT + assert state.attributes[ATTR_TEMPERATURE] == 5.0 + + await hass.services.async_call( + CLIMATE_DOMAIN, + SERVICE_SET_HVAC_MODE, + {ATTR_ENTITY_ID: ENTITY_ID, ATTR_HVAC_MODE: HVACMode.OFF}, + blocking=True, + ) + mock_serial_bridge.set_clima_status.assert_called() + + assert (state := hass.states.get(ENTITY_ID)) + assert state.state == HVACMode.OFF + + await hass.services.async_call( + CLIMATE_DOMAIN, + SERVICE_SET_HVAC_MODE, + {ATTR_ENTITY_ID: ENTITY_ID, ATTR_HVAC_MODE: HVACMode.AUTO}, + blocking=True, + ) + mock_serial_bridge.set_clima_status.assert_called() + + assert (state := hass.states.get(ENTITY_ID)) + assert state.state == HVACMode.AUTO