Add full test coverage for Comelit humidifier platform (#141852)

* Add full test coverage for Comelit humidifier platform

* clean

* update snapshot

* apply review comment
This commit is contained in:
Simone Chemelli 2025-04-11 18:23:03 +02:00 committed by GitHub
parent a4fac730d4
commit a3341c4330
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 428 additions and 3 deletions

View File

@ -38,7 +38,7 @@ BRIDGE_DEVICE_QUERY = {
type="climate",
val=[
[221, 0, "U", "M", 50, 0, 0, "U"],
[650, 0, "O", "M", 500, 0, 0, "N"],
[650, 0, "U", "M", 500, 0, 0, "U"],
[0, 0],
],
protected=0,

View File

@ -27,12 +27,12 @@
list([
650,
0,
'O',
'U',
'M',
500,
0,
0,
'N',
'U',
]),
list([
0,

View File

@ -0,0 +1,133 @@
# serializer version: 1
# name: test_all_entities[humidifier.climate0_dehumidifier-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'available_modes': list([
'normal',
'auto',
]),
'max_humidity': 90,
'min_humidity': 10,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'humidifier',
'entity_category': None,
'entity_id': 'humidifier.climate0_dehumidifier',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <HumidifierDeviceClass.DEHUMIDIFIER: 'dehumidifier'>,
'original_icon': None,
'original_name': 'Dehumidifier',
'platform': 'comelit',
'previous_unique_id': None,
'supported_features': <HumidifierEntityFeature: 1>,
'translation_key': 'dehumidifier',
'unique_id': 'serial_bridge_config_entry_id-0-dehumidifier',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[humidifier.climate0_dehumidifier-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'action': <HumidifierAction.OFF: 'off'>,
'available_modes': list([
'normal',
'auto',
]),
'current_humidity': 65.0,
'device_class': 'dehumidifier',
'friendly_name': 'Climate0 Dehumidifier',
'humidity': 50.0,
'max_humidity': 90,
'min_humidity': 10,
'mode': 'normal',
'supported_features': <HumidifierEntityFeature: 1>,
}),
'context': <ANY>,
'entity_id': 'humidifier.climate0_dehumidifier',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_all_entities[humidifier.climate0_humidifier-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'available_modes': list([
'normal',
'auto',
]),
'max_humidity': 90,
'min_humidity': 10,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'humidifier',
'entity_category': None,
'entity_id': 'humidifier.climate0_humidifier',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <HumidifierDeviceClass.HUMIDIFIER: 'humidifier'>,
'original_icon': None,
'original_name': 'Humidifier',
'platform': 'comelit',
'previous_unique_id': None,
'supported_features': <HumidifierEntityFeature: 1>,
'translation_key': 'humidifier',
'unique_id': 'serial_bridge_config_entry_id-0-humidifier',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[humidifier.climate0_humidifier-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'action': <HumidifierAction.IDLE: 'idle'>,
'available_modes': list([
'normal',
'auto',
]),
'current_humidity': 65.0,
'device_class': 'humidifier',
'friendly_name': 'Climate0 Humidifier',
'humidity': 50.0,
'max_humidity': 90,
'min_humidity': 10,
'mode': 'normal',
'supported_features': <HumidifierEntityFeature: 1>,
}),
'context': <ANY>,
'entity_id': 'humidifier.climate0_humidifier',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---

View File

@ -0,0 +1,292 @@
"""Tests for Comelit SimpleHome humidifier 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.comelit.const import DOMAIN, SCAN_INTERVAL
from homeassistant.components.humidifier import (
ATTR_HUMIDITY,
ATTR_MODE,
DOMAIN as HUMIDIFIER_DOMAIN,
MODE_AUTO,
MODE_NORMAL,
SERVICE_SET_HUMIDITY,
SERVICE_SET_MODE,
SERVICE_TURN_OFF,
SERVICE_TURN_ON,
)
from homeassistant.const import ATTR_ENTITY_ID, STATE_OFF, STATE_ON, Platform
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
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 = "humidifier.climate0_humidifier"
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.HUMIDIFIER]
):
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", "humidity"),
[
(
[
[100, 0, "U", "M", 210, 0, 0, "U"],
[650, 0, "U", "M", 500, 0, 0, "U"],
[0, 0],
],
STATE_ON,
50.0,
),
(
[
[100, 1, "U", "A", 210, 1, 0, "O"],
[650, 1, "U", "A", 500, 1, 0, "O"],
[0, 0],
],
STATE_ON,
50.0,
),
(
[
[100, 0, "O", "A", 210, 0, 0, "O"],
[650, 0, "O", "A", 500, 0, 0, "O"],
[0, 0],
],
STATE_OFF,
50.0,
),
],
)
async def test_humidifier_data_update(
hass: HomeAssistant,
freezer: FrozenDateTimeFactory,
mock_serial_bridge: AsyncMock,
mock_serial_bridge_config_entry: MockConfigEntry,
val: list[Any, Any],
mode: str,
humidity: float,
) -> None:
"""Test humidifier data update."""
await setup_integration(hass, mock_serial_bridge_config_entry)
assert (state := hass.states.get(ENTITY_ID))
assert state.state == STATE_ON
assert state.attributes[ATTR_HUMIDITY] == 50.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()
assert (state := hass.states.get(ENTITY_ID))
assert state.state == mode
assert state.attributes[ATTR_HUMIDITY] == humidity
async def test_humidifier_data_update_bad_data(
hass: HomeAssistant,
freezer: FrozenDateTimeFactory,
mock_serial_bridge: AsyncMock,
mock_serial_bridge_config_entry: MockConfigEntry,
) -> None:
"""Test humidifier data update."""
await setup_integration(hass, mock_serial_bridge_config_entry)
assert (state := hass.states.get(ENTITY_ID))
assert state.state == STATE_ON
assert state.attributes[ATTR_HUMIDITY] == 50.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()
assert (state := hass.states.get(ENTITY_ID))
assert state.state == STATE_ON
assert state.attributes[ATTR_HUMIDITY] == 50.0
async def test_humidifier_set_humidity(
hass: HomeAssistant,
mock_serial_bridge: AsyncMock,
mock_serial_bridge_config_entry: MockConfigEntry,
) -> None:
"""Test humidifier set humidity service."""
await setup_integration(hass, mock_serial_bridge_config_entry)
assert (state := hass.states.get(ENTITY_ID))
assert state.state == STATE_ON
assert state.attributes[ATTR_HUMIDITY] == 50.0
# Test set humidity
await hass.services.async_call(
HUMIDIFIER_DOMAIN,
SERVICE_SET_HUMIDITY,
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_HUMIDITY: 23},
blocking=True,
)
mock_serial_bridge.set_humidity_status.assert_called()
assert (state := hass.states.get(ENTITY_ID))
assert state.state == STATE_ON
assert state.attributes[ATTR_HUMIDITY] == 23.0
async def test_humidifier_set_humidity_while_off(
hass: HomeAssistant,
mock_serial_bridge: AsyncMock,
mock_serial_bridge_config_entry: MockConfigEntry,
) -> None:
"""Test humidifier set humidity service while off."""
await setup_integration(hass, mock_serial_bridge_config_entry)
assert (state := hass.states.get(ENTITY_ID))
assert state.state == STATE_ON
assert state.attributes[ATTR_HUMIDITY] == 50.0
# Switch humidifier off
await hass.services.async_call(
HUMIDIFIER_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: ENTITY_ID},
blocking=True,
)
mock_serial_bridge.set_humidity_status.assert_called()
assert (state := hass.states.get(ENTITY_ID))
assert state.state == STATE_OFF
# Try setting humidity
with pytest.raises(HomeAssistantError) as exc_info:
await hass.services.async_call(
HUMIDIFIER_DOMAIN,
SERVICE_SET_HUMIDITY,
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_HUMIDITY: 23},
blocking=True,
)
assert exc_info.value.translation_domain == DOMAIN
assert exc_info.value.translation_key == "humidity_while_off"
async def test_humidifier_set_mode(
hass: HomeAssistant,
mock_serial_bridge: AsyncMock,
mock_serial_bridge_config_entry: MockConfigEntry,
) -> None:
"""Test humidifier set mode service."""
await setup_integration(hass, mock_serial_bridge_config_entry)
assert (state := hass.states.get(ENTITY_ID))
assert state.state == STATE_ON
assert state.attributes[ATTR_HUMIDITY] == 50.0
assert state.attributes[ATTR_MODE] == MODE_NORMAL
await hass.services.async_call(
HUMIDIFIER_DOMAIN,
SERVICE_SET_MODE,
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_MODE: MODE_AUTO},
blocking=True,
)
mock_serial_bridge.set_humidity_status.assert_called()
assert (state := hass.states.get(ENTITY_ID))
assert state.state == STATE_ON
assert state.attributes[ATTR_MODE] == MODE_AUTO
async def test_humidifier_set_status(
hass: HomeAssistant,
mock_serial_bridge: AsyncMock,
mock_serial_bridge_config_entry: MockConfigEntry,
) -> None:
"""Test humidifier set status service."""
await setup_integration(hass, mock_serial_bridge_config_entry)
assert (state := hass.states.get(ENTITY_ID))
assert state.state == STATE_ON
assert state.attributes[ATTR_HUMIDITY] == 50.0
# Test turn off
await hass.services.async_call(
HUMIDIFIER_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: ENTITY_ID},
blocking=True,
)
mock_serial_bridge.set_humidity_status.assert_called()
assert (state := hass.states.get(ENTITY_ID))
assert state.state == STATE_OFF
# Test turn on
await hass.services.async_call(
HUMIDIFIER_DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: ENTITY_ID},
blocking=True,
)
mock_serial_bridge.set_humidity_status.assert_called()
assert (state := hass.states.get(ENTITY_ID))
assert state.state == STATE_ON