Refactor eheimdigital tests to use fixtures (#145428)

This commit is contained in:
Sid 2025-05-26 19:13:20 +02:00 committed by GitHub
parent 99ebac5452
commit 03a26836ed
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 462 additions and 197 deletions

View File

@ -94,8 +94,6 @@ class EheimDigitalClassicLEDControlLight(
await self._device.set_light_mode(EFFECT_TO_LIGHT_MODE[kwargs[ATTR_EFFECT]])
return
if ATTR_BRIGHTNESS in kwargs:
if self._device.light_mode == LightMode.DAYCL_MODE:
await self._device.set_light_mode(LightMode.MAN_MODE)
await self._device.turn_on(
int(brightness_to_value(BRIGHTNESS_SCALE, kwargs[ATTR_BRIGHTNESS])),
self._channel,
@ -104,8 +102,6 @@ class EheimDigitalClassicLEDControlLight(
@exception_handler
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn off the light."""
if self._device.light_mode == LightMode.DAYCL_MODE:
await self._device.set_light_mode(LightMode.MAN_MODE)
await self._device.turn_off(self._channel)
def _async_update_attrs(self) -> None:

View File

@ -1,7 +1,6 @@
"""Configurations for the EHEIM Digital tests."""
from collections.abc import Generator
from datetime import time, timedelta, timezone
from unittest.mock import AsyncMock, MagicMock, patch
from eheimdigital.classic_led_ctrl import EheimDigitalClassicLEDControl
@ -9,12 +8,13 @@ from eheimdigital.classic_vario import EheimDigitalClassicVario
from eheimdigital.heater import EheimDigitalHeater
from eheimdigital.hub import EheimDigitalHub
from eheimdigital.types import (
EheimDeviceType,
FilterErrorCode,
FilterMode,
HeaterMode,
HeaterUnit,
LightMode,
AcclimatePacket,
CCVPacket,
ClassicVarioDataPacket,
ClockPacket,
CloudPacket,
MoonPacket,
UsrDtaPacket,
)
import pytest
@ -22,7 +22,7 @@ from homeassistant.components.eheimdigital.const import DOMAIN
from homeassistant.const import CONF_HOST
from homeassistant.core import HomeAssistant
from tests.common import MockConfigEntry
from tests.common import MockConfigEntry, load_json_object_fixture
@pytest.fixture
@ -36,66 +36,50 @@ def mock_config_entry() -> MockConfigEntry:
@pytest.fixture
def classic_led_ctrl_mock():
"""Mock a classicLEDcontrol device."""
classic_led_ctrl_mock = MagicMock(spec=EheimDigitalClassicLEDControl)
classic_led_ctrl_mock.tankconfig = [["CLASSIC_DAYLIGHT"], []]
classic_led_ctrl_mock.mac_address = "00:00:00:00:00:01"
classic_led_ctrl_mock.device_type = (
EheimDeviceType.VERSION_EHEIM_CLASSIC_LED_CTRL_PLUS_E
classic_led_ctrl = EheimDigitalClassicLEDControl(
MagicMock(spec=EheimDigitalHub),
UsrDtaPacket(load_json_object_fixture("classic_led_ctrl/usrdta.json", DOMAIN)),
)
classic_led_ctrl_mock.name = "Mock classicLEDcontrol+e"
classic_led_ctrl_mock.aquarium_name = "Mock Aquarium"
classic_led_ctrl_mock.sw_version = "1.0.0_1.0.0"
classic_led_ctrl_mock.light_mode = LightMode.DAYCL_MODE
classic_led_ctrl_mock.light_level = (10, 39)
classic_led_ctrl_mock.sys_led = 20
return classic_led_ctrl_mock
classic_led_ctrl.ccv = CCVPacket(
load_json_object_fixture("classic_led_ctrl/ccv.json", DOMAIN)
)
classic_led_ctrl.moon = MoonPacket(
load_json_object_fixture("classic_led_ctrl/moon.json", DOMAIN)
)
classic_led_ctrl.acclimate = AcclimatePacket(
load_json_object_fixture("classic_led_ctrl/acclimate.json", DOMAIN)
)
classic_led_ctrl.cloud = CloudPacket(
load_json_object_fixture("classic_led_ctrl/cloud.json", DOMAIN)
)
classic_led_ctrl.clock = ClockPacket(
load_json_object_fixture("classic_led_ctrl/clock.json", DOMAIN)
)
return classic_led_ctrl
@pytest.fixture
def heater_mock():
"""Mock a Heater device."""
heater_mock = MagicMock(spec=EheimDigitalHeater)
heater_mock.mac_address = "00:00:00:00:00:02"
heater_mock.device_type = EheimDeviceType.VERSION_EHEIM_EXT_HEATER
heater_mock.name = "Mock Heater"
heater_mock.aquarium_name = "Mock Aquarium"
heater_mock.sw_version = "1.0.0_1.0.0"
heater_mock.temperature_unit = HeaterUnit.CELSIUS
heater_mock.current_temperature = 24.2
heater_mock.target_temperature = 25.5
heater_mock.temperature_offset = 0.1
heater_mock.night_temperature_offset = -0.2
heater_mock.is_heating = True
heater_mock.is_active = True
heater_mock.operation_mode = HeaterMode.MANUAL
heater_mock.day_start_time = time(8, 0, tzinfo=timezone(timedelta(hours=1)))
heater_mock.night_start_time = time(20, 0, tzinfo=timezone(timedelta(hours=1)))
heater_mock.sys_led = 20
return heater_mock
heater = EheimDigitalHeater(
MagicMock(spec=EheimDigitalHub),
load_json_object_fixture("heater/usrdta.json", DOMAIN),
)
heater.heater_data = load_json_object_fixture("heater/heater_data.json", DOMAIN)
return heater
@pytest.fixture
def classic_vario_mock():
"""Mock a classicVARIO device."""
classic_vario_mock = MagicMock(spec=EheimDigitalClassicVario)
classic_vario_mock.mac_address = "00:00:00:00:00:03"
classic_vario_mock.device_type = EheimDeviceType.VERSION_EHEIM_CLASSIC_VARIO
classic_vario_mock.name = "Mock classicVARIO"
classic_vario_mock.aquarium_name = "Mock Aquarium"
classic_vario_mock.sw_version = "1.0.0_1.0.0"
classic_vario_mock.current_speed = 75
classic_vario_mock.manual_speed = 75
classic_vario_mock.day_speed = 80
classic_vario_mock.day_start_time = time(8, 0, tzinfo=timezone(timedelta(hours=1)))
classic_vario_mock.night_start_time = time(
20, 0, tzinfo=timezone(timedelta(hours=1))
classic_vario = EheimDigitalClassicVario(
MagicMock(spec=EheimDigitalHub),
UsrDtaPacket(load_json_object_fixture("classic_vario/usrdta.json", DOMAIN)),
)
classic_vario_mock.night_speed = 20
classic_vario_mock.is_active = True
classic_vario_mock.filter_mode = FilterMode.MANUAL
classic_vario_mock.error_code = FilterErrorCode.NO_ERROR
classic_vario_mock.service_hours = 360
return classic_vario_mock
classic_vario.classic_vario_data = ClassicVarioDataPacket(
load_json_object_fixture("classic_vario/classic_vario_data.json", DOMAIN)
)
return classic_vario
@pytest.fixture

View File

@ -0,0 +1,9 @@
{
"title": "ACCLIMATE",
"from": "00:00:00:00:00:01",
"duration": 30,
"intensityReduction": 99,
"currentAcclDay": 0,
"acclActive": 0,
"pause": 0
}

View File

@ -0,0 +1 @@
{ "title": "CCV", "from": "00:00:00:00:00:01", "currentValues": [10, 39] }

View File

@ -0,0 +1,13 @@
{
"title": "CLOCK",
"from": "00:00:00:00:00:01",
"year": 2025,
"month": 5,
"day": 22,
"hour": 5,
"min": 53,
"sec": 22,
"mode": "DAYCL_MODE",
"valid": 1,
"to": "USER"
}

View File

@ -0,0 +1,12 @@
{
"title": "CLOUD",
"from": "00:00:00:00:00:01",
"probability": 50,
"maxAmount": 90,
"minIntensity": 60,
"maxIntensity": 100,
"minDuration": 600,
"maxDuration": 1500,
"cloudActive": 1,
"mode": 2
}

View File

@ -0,0 +1,8 @@
{
"title": "MOON",
"from": "00:00:00:00:00:01",
"maxmoonlight": 18,
"minmoonlight": 4,
"moonlightActive": 1,
"moonlightCycle": 1
}

View File

@ -0,0 +1,35 @@
{
"title": "USRDTA",
"from": "00:00:00:00:00:01",
"name": "Mock classicLEDcontrol+e",
"aqName": "Mock Aquarium",
"mode": "DAYCL_MODE",
"version": 17,
"language": "EN",
"timezone": 60,
"tID": 30,
"dst": 1,
"tankconfig": "[[],[\"CLASSIC_DAYLIGHT\"]]",
"power": "[[],[14]]",
"netmode": "ST",
"host": "eheimdigital",
"groupID": 0,
"meshing": 1,
"firstStart": 0,
"revision": [2034, 2034],
"build": ["1722600896000", "1722596503307"],
"latestAvailableRevision": [-1, -1, -1, -1],
"firmwareAvailable": 0,
"softChange": 0,
"emailAddr": "",
"stMail": 0,
"stMailMode": 0,
"fstTime": 0,
"sstTime": 0,
"liveTime": 832140,
"usrName": "",
"unit": 0,
"demoUse": 0,
"sysLED": 20,
"to": "USER"
}

View File

@ -0,0 +1,22 @@
{
"title": "CLASSIC_VARIO_DATA",
"from": "00:00:00:00:00:03",
"rel_speed": 75,
"pumpMode": 16,
"filterActive": 1,
"turnOffTime": 0,
"serviceHour": 360,
"rel_manual_motor_speed": 75,
"rel_motor_speed_day": 80,
"rel_motor_speed_night": 20,
"startTime_day": 480,
"startTime_night": 1200,
"pulse_motorSpeed_High": 100,
"pulse_motorSpeed_Low": 20,
"pulse_Time_High": 100,
"pulse_Time_Low": 50,
"turnTimeFeeding": 0,
"errorCode": 0,
"version": 0,
"to": "USER"
}

View File

@ -0,0 +1,34 @@
{
"title": "USRDTA",
"from": "00:00:00:00:00:03",
"name": "Mock classicVARIO",
"aqName": "Mock Aquarium",
"version": 18,
"language": "EN",
"timezone": 60,
"tID": 30,
"dst": 1,
"tankconfig": "CLASSIC-VARIO",
"power": "9",
"netmode": "ST",
"host": "eheimdigital",
"groupID": 0,
"meshing": 1,
"firstStart": 0,
"revision": [2034, 2034],
"build": ["1722600896000", "1722596503307"],
"latestAvailableRevision": [1024, 1028, 2036, 2036],
"firmwareAvailable": 1,
"softChange": 0,
"emailAddr": "",
"stMail": 0,
"stMailMode": 0,
"fstTime": 720,
"sstTime": 0,
"liveTime": 444600,
"usrName": "",
"unit": 0,
"demoUse": 0,
"sysLED": 100,
"to": "USER"
}

View File

@ -0,0 +1,20 @@
{
"title": "HEATER_DATA",
"from": "00:00:00:00:00:02",
"mUnit": 0,
"sollTemp": 255,
"isTemp": 242,
"hystLow": 5,
"hystHigh": 5,
"offset": 1,
"active": 1,
"isHeating": 1,
"mode": 0,
"sync": "",
"partnerName": "",
"dayStartT": 480,
"nightStartT": 1200,
"nReduce": -2,
"alertState": 0,
"to": "USER"
}

View File

@ -0,0 +1,34 @@
{
"title": "USRDTA",
"from": "00:00:00:00:00:02",
"name": "Mock Heater",
"aqName": "Mock Aquarium",
"version": 5,
"language": "EN",
"timezone": 60,
"tID": 30,
"dst": 1,
"tankconfig": "HEAT400",
"power": "9",
"netmode": "ST",
"host": "eheimdigital",
"groupID": 0,
"meshing": 1,
"firstStart": 0,
"remote": 0,
"revision": [1021, 1024],
"build": ["1718889198000", "1718868200327"],
"latestAvailableRevision": [-1, -1, -1, -1],
"firmwareAvailable": 0,
"emailAddr": "",
"stMail": 0,
"stMailMode": 0,
"fstTime": 0,
"sstTime": 0,
"liveTime": 302580,
"usrName": "",
"unit": 0,
"demoUse": 0,
"sysLED": 20,
"to": "USER"
}

View File

@ -1,5 +1,5 @@
# serializer version: 1
# name: test_dynamic_new_devices[light.mock_classicledcontrol_e_channel_0-entry]
# name: test_dynamic_new_devices[light.mock_classicledcontrol_e_channel_1-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -19,7 +19,7 @@
'disabled_by': None,
'domain': 'light',
'entity_category': None,
'entity_id': 'light.mock_classicledcontrol_e_channel_0',
'entity_id': 'light.mock_classicledcontrol_e_channel_1',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
@ -31,32 +31,32 @@
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Channel 0',
'original_name': 'Channel 1',
'platform': 'eheimdigital',
'previous_unique_id': None,
'supported_features': <LightEntityFeature: 4>,
'translation_key': 'channel',
'unique_id': '00:00:00:00:00:01_0',
'unique_id': '00:00:00:00:00:01_1',
'unit_of_measurement': None,
})
# ---
# name: test_dynamic_new_devices[light.mock_classicledcontrol_e_channel_0-state]
# name: test_dynamic_new_devices[light.mock_classicledcontrol_e_channel_1-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'brightness': 26,
'brightness': 99,
'color_mode': <ColorMode.BRIGHTNESS: 'brightness'>,
'effect': 'daycl_mode',
'effect_list': list([
'daycl_mode',
]),
'friendly_name': 'Mock classicLEDcontrol+e Channel 0',
'friendly_name': 'Mock classicLEDcontrol+e Channel 1',
'supported_color_modes': list([
<ColorMode.BRIGHTNESS: 'brightness'>,
]),
'supported_features': <LightEntityFeature: 4>,
}),
'context': <ANY>,
'entity_id': 'light.mock_classicledcontrol_e_channel_0',
'entity_id': 'light.mock_classicledcontrol_e_channel_1',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,

View File

@ -2,6 +2,7 @@
from unittest.mock import AsyncMock, MagicMock, patch
from eheimdigital.heater import EheimDigitalHeater
from eheimdigital.types import (
EheimDeviceType,
EheimDigitalClientError,
@ -67,7 +68,7 @@ async def test_setup_heater(
async def test_dynamic_new_devices(
hass: HomeAssistant,
eheimdigital_hub_mock: MagicMock,
heater_mock: MagicMock,
heater_mock: EheimDigitalHeater,
entity_registry: er.EntityRegistry,
snapshot: SnapshotAssertion,
mock_config_entry: MockConfigEntry,
@ -116,7 +117,7 @@ async def test_dynamic_new_devices(
async def test_set_preset_mode(
hass: HomeAssistant,
eheimdigital_hub_mock: MagicMock,
heater_mock: MagicMock,
heater_mock: EheimDigitalHeater,
mock_config_entry: MockConfigEntry,
preset_mode: str,
heater_mode: HeaterMode,
@ -129,7 +130,7 @@ async def test_set_preset_mode(
)
await hass.async_block_till_done()
heater_mock.set_operation_mode.side_effect = EheimDigitalClientError
heater_mock.hub.send_packet.side_effect = EheimDigitalClientError
with pytest.raises(HomeAssistantError):
await hass.services.async_call(
@ -139,7 +140,7 @@ async def test_set_preset_mode(
blocking=True,
)
heater_mock.set_operation_mode.side_effect = None
heater_mock.hub.send_packet.side_effect = None
await hass.services.async_call(
CLIMATE_DOMAIN,
@ -148,7 +149,8 @@ async def test_set_preset_mode(
blocking=True,
)
heater_mock.set_operation_mode.assert_awaited_with(heater_mode)
calls = [call for call in heater_mock.hub.mock_calls if call[0] == "send_packet"]
assert len(calls) == 2 and calls[1][1][0]["mode"] == int(heater_mode)
async def test_set_temperature(
@ -165,7 +167,7 @@ async def test_set_temperature(
)
await hass.async_block_till_done()
heater_mock.set_target_temperature.side_effect = EheimDigitalClientError
heater_mock.hub.send_packet.side_effect = EheimDigitalClientError
with pytest.raises(HomeAssistantError):
await hass.services.async_call(
@ -175,7 +177,7 @@ async def test_set_temperature(
blocking=True,
)
heater_mock.set_target_temperature.side_effect = None
heater_mock.hub.send_packet.side_effect = None
await hass.services.async_call(
CLIMATE_DOMAIN,
@ -184,7 +186,8 @@ async def test_set_temperature(
blocking=True,
)
heater_mock.set_target_temperature.assert_awaited_with(26.0)
calls = [call for call in heater_mock.hub.mock_calls if call[0] == "send_packet"]
assert len(calls) == 2 and calls[1][1][0]["sollTemp"] == 260
@pytest.mark.parametrize(
@ -206,7 +209,7 @@ async def test_set_hvac_mode(
)
await hass.async_block_till_done()
heater_mock.set_active.side_effect = EheimDigitalClientError
heater_mock.hub.send_packet.side_effect = EheimDigitalClientError
with pytest.raises(HomeAssistantError):
await hass.services.async_call(
@ -216,7 +219,7 @@ async def test_set_hvac_mode(
blocking=True,
)
heater_mock.set_active.side_effect = None
heater_mock.hub.send_packet.side_effect = None
await hass.services.async_call(
CLIMATE_DOMAIN,
@ -225,19 +228,20 @@ async def test_set_hvac_mode(
blocking=True,
)
heater_mock.set_active.assert_awaited_with(active=active)
calls = [call for call in heater_mock.hub.mock_calls if call[0] == "send_packet"]
assert len(calls) == 2 and calls[1][1][0]["active"] == int(active)
async def test_state_update(
hass: HomeAssistant,
eheimdigital_hub_mock: MagicMock,
mock_config_entry: MockConfigEntry,
heater_mock: MagicMock,
heater_mock: EheimDigitalHeater,
) -> None:
"""Test the climate state update."""
heater_mock.temperature_unit = HeaterUnit.FAHRENHEIT
heater_mock.is_heating = False
heater_mock.operation_mode = HeaterMode.BIO
heater_mock.heater_data["mUnit"] = int(HeaterUnit.FAHRENHEIT)
heater_mock.heater_data["isHeating"] = int(False)
heater_mock.heater_data["mode"] = int(HeaterMode.BIO)
await init_integration(hass, mock_config_entry)
@ -251,8 +255,8 @@ async def test_state_update(
assert state.attributes["hvac_action"] == HVACAction.IDLE
assert state.attributes["preset_mode"] == HEATER_BIO_MODE
heater_mock.is_active = False
heater_mock.operation_mode = HeaterMode.SMART
heater_mock.heater_data["active"] = int(False)
heater_mock.heater_data["mode"] = int(HeaterMode.SMART)
await eheimdigital_hub_mock.call_args.kwargs["receive_callback"]()

View File

@ -4,7 +4,8 @@ from datetime import timedelta
from unittest.mock import AsyncMock, MagicMock, patch
from aiohttp import ClientError
from eheimdigital.types import EheimDeviceType, LightMode
from eheimdigital.classic_led_ctrl import EheimDigitalClassicLEDControl
from eheimdigital.types import EheimDeviceType
from freezegun.api import FrozenDateTimeFactory
import pytest
from syrupy.assertion import SnapshotAssertion
@ -117,7 +118,7 @@ async def test_dynamic_new_devices(
async def test_turn_off(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
classic_led_ctrl_mock: MagicMock,
classic_led_ctrl_mock: EheimDigitalClassicLEDControl,
) -> None:
"""Test turning off the light."""
await init_integration(hass, mock_config_entry)
@ -130,12 +131,18 @@ async def test_turn_off(
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: "light.mock_classicledcontrol_e_channel_0"},
{ATTR_ENTITY_ID: "light.mock_classicledcontrol_e_channel_1"},
blocking=True,
)
classic_led_ctrl_mock.set_light_mode.assert_awaited_once_with(LightMode.MAN_MODE)
classic_led_ctrl_mock.turn_off.assert_awaited_once_with(0)
calls = [
call
for call in classic_led_ctrl_mock.hub.mock_calls
if call[0] == "send_packet"
]
assert len(calls) == 2
assert calls[0][1][0].get("title") == "MAN_MODE"
assert calls[1][1][0]["currentValues"][1] == 0
@pytest.mark.parametrize(
@ -150,7 +157,7 @@ async def test_turn_on_brightness(
hass: HomeAssistant,
eheimdigital_hub_mock: MagicMock,
mock_config_entry: MockConfigEntry,
classic_led_ctrl_mock: MagicMock,
classic_led_ctrl_mock: EheimDigitalClassicLEDControl,
dim_input: int,
expected_dim_value: int,
) -> None:
@ -166,24 +173,30 @@ async def test_turn_on_brightness(
LIGHT_DOMAIN,
SERVICE_TURN_ON,
{
ATTR_ENTITY_ID: "light.mock_classicledcontrol_e_channel_0",
ATTR_ENTITY_ID: "light.mock_classicledcontrol_e_channel_1",
ATTR_BRIGHTNESS: dim_input,
},
blocking=True,
)
classic_led_ctrl_mock.set_light_mode.assert_awaited_once_with(LightMode.MAN_MODE)
classic_led_ctrl_mock.turn_on.assert_awaited_once_with(expected_dim_value, 0)
calls = [
call
for call in classic_led_ctrl_mock.hub.mock_calls
if call[0] == "send_packet"
]
assert len(calls) == 2
assert calls[0][1][0].get("title") == "MAN_MODE"
assert calls[1][1][0]["currentValues"][1] == expected_dim_value
async def test_turn_on_effect(
hass: HomeAssistant,
eheimdigital_hub_mock: MagicMock,
mock_config_entry: MockConfigEntry,
classic_led_ctrl_mock: MagicMock,
classic_led_ctrl_mock: EheimDigitalClassicLEDControl,
) -> None:
"""Test turning on the light with an effect value."""
classic_led_ctrl_mock.light_mode = LightMode.MAN_MODE
classic_led_ctrl_mock.clock["mode"] = "MAN_MODE"
await init_integration(hass, mock_config_entry)
@ -196,20 +209,26 @@ async def test_turn_on_effect(
LIGHT_DOMAIN,
SERVICE_TURN_ON,
{
ATTR_ENTITY_ID: "light.mock_classicledcontrol_e_channel_0",
ATTR_ENTITY_ID: "light.mock_classicledcontrol_e_channel_1",
ATTR_EFFECT: EFFECT_DAYCL_MODE,
},
blocking=True,
)
classic_led_ctrl_mock.set_light_mode.assert_awaited_once_with(LightMode.DAYCL_MODE)
calls = [
call
for call in classic_led_ctrl_mock.hub.mock_calls
if call[0] == "send_packet"
]
assert len(calls) == 1
assert calls[0][1][0].get("title") == "DAYCL_MODE"
async def test_state_update(
hass: HomeAssistant,
eheimdigital_hub_mock: MagicMock,
mock_config_entry: MockConfigEntry,
classic_led_ctrl_mock: MagicMock,
classic_led_ctrl_mock: EheimDigitalClassicLEDControl,
) -> None:
"""Test the light state update."""
await init_integration(hass, mock_config_entry)
@ -219,11 +238,11 @@ async def test_state_update(
)
await hass.async_block_till_done()
classic_led_ctrl_mock.light_level = (20, 30)
classic_led_ctrl_mock.ccv["currentValues"] = [30, 20]
await eheimdigital_hub_mock.call_args.kwargs["receive_callback"]()
assert (state := hass.states.get("light.mock_classicledcontrol_e_channel_0"))
assert (state := hass.states.get("light.mock_classicledcontrol_e_channel_1"))
assert state.attributes["brightness"] == value_to_brightness((1, 100), 20)
@ -248,6 +267,6 @@ async def test_update_failed(
await hass.async_block_till_done()
assert (
hass.states.get("light.mock_classicledcontrol_e_channel_0").state
hass.states.get("light.mock_classicledcontrol_e_channel_1").state
== STATE_UNAVAILABLE
)

View File

@ -58,20 +58,20 @@ async def test_setup(
(
"number.mock_heater_temperature_offset",
0.4,
"set_temperature_offset",
(0.4,),
"offset",
4,
),
(
"number.mock_heater_night_temperature_offset",
0.4,
"set_night_temperature_offset",
(0.4,),
"nReduce",
4,
),
(
"number.mock_heater_system_led_brightness",
20,
"set_sys_led",
(20,),
"sysLED",
20,
),
],
),
@ -81,26 +81,26 @@ async def test_setup(
(
"number.mock_classicvario_manual_speed",
72.1,
"set_manual_speed",
(int(72.1),),
"rel_manual_motor_speed",
int(72.1),
),
(
"number.mock_classicvario_day_speed",
72.1,
"set_day_speed",
(int(72.1),),
"rel_motor_speed_day",
int(72.1),
),
(
"number.mock_classicvario_night_speed",
72.1,
"set_night_speed",
(int(72.1),),
"rel_motor_speed_night",
int(72.1),
),
(
"number.mock_classicvario_system_led_brightness",
20,
"set_sys_led",
(20,),
"sysLED",
20,
),
],
),
@ -131,8 +131,8 @@ async def test_set_value(
{ATTR_ENTITY_ID: item[0], ATTR_VALUE: item[1]},
blocking=True,
)
calls = [call for call in device.mock_calls if call[0] == item[2]]
assert len(calls) == 1 and calls[0][1] == item[3]
calls = [call for call in device.hub.mock_calls if call[0] == "send_packet"]
assert calls[-1][1][0][item[2]] == item[3]
@pytest.mark.usefixtures("classic_vario_mock", "heater_mock")
@ -144,17 +144,23 @@ async def test_set_value(
[
(
"number.mock_heater_temperature_offset",
"temperature_offset",
"heater_data",
"offset",
-11,
-1.1,
),
(
"number.mock_heater_night_temperature_offset",
"night_temperature_offset",
2.3,
"heater_data",
"nReduce",
-23,
-2.3,
),
(
"number.mock_heater_system_led_brightness",
"sys_led",
"usrdta",
"sysLED",
87,
87,
),
],
@ -164,23 +170,31 @@ async def test_set_value(
[
(
"number.mock_classicvario_manual_speed",
"manual_speed",
"classic_vario_data",
"rel_manual_motor_speed",
34,
34,
),
(
"number.mock_classicvario_day_speed",
"day_speed",
79,
"classic_vario_data",
"rel_motor_speed_day",
72,
72,
),
(
"number.mock_classicvario_night_speed",
"night_speed",
12,
"classic_vario_data",
"rel_motor_speed_night",
20,
20,
),
(
"number.mock_classicvario_system_led_brightness",
"sys_led",
35,
"usrdta",
"sysLED",
20,
20,
),
],
),
@ -191,7 +205,7 @@ async def test_state_update(
eheimdigital_hub_mock: MagicMock,
mock_config_entry: MockConfigEntry,
device_name: str,
entity_list: list[tuple[str, str, float]],
entity_list: list[tuple[str, str, str, float, float]],
request: pytest.FixtureRequest,
) -> None:
"""Test state updates."""
@ -205,7 +219,7 @@ async def test_state_update(
await hass.async_block_till_done()
for item in entity_list:
setattr(device, item[1], item[2])
getattr(device, item[1])[item[2]] = item[3]
await eheimdigital_hub_mock.call_args.kwargs["receive_callback"]()
assert (state := hass.states.get(item[0]))
assert state.state == str(item[2])
assert state.state == str(item[4])

View File

@ -59,8 +59,8 @@ async def test_setup(
(
"select.mock_classicvario_filter_mode",
"manual",
"set_filter_mode",
(FilterMode.MANUAL,),
"pumpMode",
int(FilterMode.MANUAL),
),
],
),
@ -71,7 +71,7 @@ async def test_set_value(
eheimdigital_hub_mock: MagicMock,
mock_config_entry: MockConfigEntry,
device_name: str,
entity_list: list[tuple[str, float, str, tuple[FilterMode]]],
entity_list: list[tuple[str, str, str, int]],
request: pytest.FixtureRequest,
) -> None:
"""Test setting a value."""
@ -91,8 +91,8 @@ async def test_set_value(
{ATTR_ENTITY_ID: item[0], ATTR_OPTION: item[1]},
blocking=True,
)
calls = [call for call in device.mock_calls if call[0] == item[2]]
assert len(calls) == 1 and calls[0][1] == item[3]
calls = [call for call in device.hub.mock_calls if call[0] == "send_packet"]
assert calls[-1][1][0][item[2]] == item[3]
@pytest.mark.usefixtures("classic_vario_mock", "heater_mock")
@ -104,8 +104,10 @@ async def test_set_value(
[
(
"select.mock_classicvario_filter_mode",
"filter_mode",
FilterMode.BIO,
"classic_vario_data",
"pumpMode",
int(FilterMode.BIO),
"bio",
),
],
),
@ -116,7 +118,7 @@ async def test_state_update(
eheimdigital_hub_mock: MagicMock,
mock_config_entry: MockConfigEntry,
device_name: str,
entity_list: list[tuple[str, str, FilterMode]],
entity_list: list[tuple[str, str, str, int, str]],
request: pytest.FixtureRequest,
) -> None:
"""Test state updates."""
@ -130,7 +132,7 @@ async def test_state_update(
await hass.async_block_till_done()
for item in entity_list:
setattr(device, item[1], item[2])
getattr(device, item[1])[item[2]] = item[3]
await eheimdigital_hub_mock.call_args.kwargs["receive_callback"]()
assert (state := hass.states.get(item[0]))
assert state.state == item[2].name.lower()
assert state.state == item[4]

View File

@ -43,35 +43,58 @@ async def test_setup_classic_vario(
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
@pytest.mark.usefixtures("classic_vario_mock")
@pytest.mark.parametrize(
("device_name", "entity_list"),
[
(
"classic_vario_mock",
[
(
"sensor.mock_classicvario_current_speed",
"classic_vario_data",
"rel_speed",
10,
10,
),
(
"sensor.mock_classicvario_error_code",
"classic_vario_data",
"errorCode",
int(FilterErrorCode.ROTOR_STUCK),
"rotor_stuck",
),
(
"sensor.mock_classicvario_remaining_hours_until_service",
"classic_vario_data",
"serviceHour",
100,
str(round(100 / 24, 1)),
),
],
),
],
)
async def test_state_update(
hass: HomeAssistant,
eheimdigital_hub_mock: MagicMock,
mock_config_entry: MockConfigEntry,
classic_vario_mock: MagicMock,
device_name: str,
entity_list: list[tuple[str, str, str, float, float]],
request: pytest.FixtureRequest,
) -> None:
"""Test the sensor state update."""
device: MagicMock = request.getfixturevalue(device_name)
await init_integration(hass, mock_config_entry)
await eheimdigital_hub_mock.call_args.kwargs["device_found_callback"](
"00:00:00:00:00:03", EheimDeviceType.VERSION_EHEIM_CLASSIC_VARIO
device.mac_address, device.device_type
)
await hass.async_block_till_done()
classic_vario_mock.current_speed = 10
classic_vario_mock.error_code = FilterErrorCode.ROTOR_STUCK
classic_vario_mock.service_hours = 100
await eheimdigital_hub_mock.call_args.kwargs["receive_callback"]()
assert (state := hass.states.get("sensor.mock_classicvario_current_speed"))
assert state.state == "10"
assert (state := hass.states.get("sensor.mock_classicvario_error_code"))
assert state.state == "rotor_stuck"
assert (
state := hass.states.get(
"sensor.mock_classicvario_remaining_hours_until_service"
)
)
assert state.state == str(round(100 / 24, 1))
for item in entity_list:
getattr(device, item[1])[item[2]] = item[3]
await eheimdigital_hub_mock.call_args.kwargs["receive_callback"]()
assert (state := hass.states.get(item[0]))
assert state.state == str(item[4])

View File

@ -11,8 +11,6 @@ from homeassistant.const import (
ATTR_ENTITY_ID,
SERVICE_TURN_OFF,
SERVICE_TURN_ON,
STATE_OFF,
STATE_ON,
Platform,
)
from homeassistant.core import HomeAssistant
@ -77,29 +75,58 @@ async def test_turn_on_off(
blocking=True,
)
classic_vario_mock.set_active.assert_awaited_once_with(active=active)
calls = [
call for call in classic_vario_mock.hub.mock_calls if call[0] == "send_packet"
]
assert len(calls) == 1
assert calls[0][1][0].get("filterActive") == int(active)
@pytest.mark.usefixtures("classic_vario_mock")
@pytest.mark.parametrize(
("device_name", "entity_list"),
[
(
"classic_vario_mock",
[
(
"switch.mock_classicvario",
"classic_vario_data",
"filterActive",
1,
"on",
),
(
"switch.mock_classicvario",
"classic_vario_data",
"filterActive",
0,
"off",
),
],
),
],
)
async def test_state_update(
hass: HomeAssistant,
eheimdigital_hub_mock: MagicMock,
mock_config_entry: MockConfigEntry,
classic_vario_mock: MagicMock,
device_name: str,
entity_list: list[tuple[str, str, str, float, float]],
request: pytest.FixtureRequest,
) -> None:
"""Test the switch state update."""
device: MagicMock = request.getfixturevalue(device_name)
await init_integration(hass, mock_config_entry)
await eheimdigital_hub_mock.call_args.kwargs["device_found_callback"](
"00:00:00:00:00:03", EheimDeviceType.VERSION_EHEIM_CLASSIC_VARIO
device.mac_address, device.device_type
)
await hass.async_block_till_done()
assert (state := hass.states.get("switch.mock_classicvario"))
assert state.state == STATE_ON
classic_vario_mock.is_active = False
await eheimdigital_hub_mock.call_args.kwargs["receive_callback"]()
assert (state := hass.states.get("switch.mock_classicvario"))
assert state.state == STATE_OFF
for item in entity_list:
getattr(device, item[1])[item[2]] = item[3]
await eheimdigital_hub_mock.call_args.kwargs["receive_callback"]()
assert (state := hass.states.get(item[0]))
assert state.state == str(item[4])

View File

@ -59,14 +59,14 @@ async def test_setup(
(
"time.mock_heater_day_start_time",
time(9, 0, tzinfo=timezone(timedelta(hours=1))),
"set_day_start_time",
(time(9, 0, tzinfo=timezone(timedelta(hours=1))),),
"dayStartT",
9 * 60,
),
(
"time.mock_heater_night_start_time",
time(19, 0, tzinfo=timezone(timedelta(hours=1))),
"set_night_start_time",
(time(19, 0, tzinfo=timezone(timedelta(hours=1))),),
"nightStartT",
19 * 60,
),
],
),
@ -76,14 +76,14 @@ async def test_setup(
(
"time.mock_classicvario_day_start_time",
time(9, 0, tzinfo=timezone(timedelta(hours=1))),
"set_day_start_time",
(time(9, 0, tzinfo=timezone(timedelta(hours=1))),),
"startTime_day",
9 * 60,
),
(
"time.mock_classicvario_night_start_time",
time(19, 0, tzinfo=timezone(timedelta(hours=1))),
"set_night_start_time",
(time(19, 0, tzinfo=timezone(timedelta(hours=1))),),
"startTime_night",
19 * 60,
),
],
),
@ -114,8 +114,8 @@ async def test_set_value(
{ATTR_ENTITY_ID: item[0], ATTR_TIME: item[1]},
blocking=True,
)
calls = [call for call in device.mock_calls if call[0] == item[2]]
assert len(calls) == 1 and calls[0][1] == item[3]
calls = [call for call in device.hub.mock_calls if call[0] == "send_packet"]
assert calls[-1][1][0][item[2]] == item[3]
@pytest.mark.usefixtures("classic_vario_mock", "heater_mock")
@ -127,13 +127,17 @@ async def test_set_value(
[
(
"time.mock_heater_day_start_time",
"day_start_time",
time(9, 0, tzinfo=timezone(timedelta(hours=3))),
"heater_data",
"dayStartT",
540,
time(9, 0, tzinfo=timezone(timedelta(hours=1))).isoformat(),
),
(
"time.mock_heater_night_start_time",
"night_start_time",
time(19, 0, tzinfo=timezone(timedelta(hours=3))),
"heater_data",
"nightStartT",
1140,
time(19, 0, tzinfo=timezone(timedelta(hours=1))).isoformat(),
),
],
),
@ -142,13 +146,17 @@ async def test_set_value(
[
(
"time.mock_classicvario_day_start_time",
"day_start_time",
time(9, 0, tzinfo=timezone(timedelta(hours=1))),
"classic_vario_data",
"startTime_day",
540,
time(9, 0, tzinfo=timezone(timedelta(hours=1))).isoformat(),
),
(
"time.mock_classicvario_night_start_time",
"night_start_time",
time(22, 0, tzinfo=timezone(timedelta(hours=1))),
"classic_vario_data",
"startTime_night",
1320,
time(22, 0, tzinfo=timezone(timedelta(hours=1))).isoformat(),
),
],
),
@ -159,7 +167,7 @@ async def test_state_update(
eheimdigital_hub_mock: MagicMock,
mock_config_entry: MockConfigEntry,
device_name: str,
entity_list: list[tuple[str, str, time]],
entity_list: list[tuple[str, str, str, float, str]],
request: pytest.FixtureRequest,
) -> None:
"""Test state updates."""
@ -173,7 +181,7 @@ async def test_state_update(
await hass.async_block_till_done()
for item in entity_list:
setattr(device, item[1], item[2])
getattr(device, item[1])[item[2]] = item[3]
await eheimdigital_hub_mock.call_args.kwargs["receive_callback"]()
assert (state := hass.states.get(item[0]))
assert state.state == item[2].isoformat()
assert state.state == item[4]