diff --git a/homeassistant/components/eheimdigital/light.py b/homeassistant/components/eheimdigital/light.py index 7960e956859..4e148ee5204 100644 --- a/homeassistant/components/eheimdigital/light.py +++ b/homeassistant/components/eheimdigital/light.py @@ -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: diff --git a/tests/components/eheimdigital/conftest.py b/tests/components/eheimdigital/conftest.py index 5b828f830a4..c05e95701e1 100644 --- a/tests/components/eheimdigital/conftest.py +++ b/tests/components/eheimdigital/conftest.py @@ -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 diff --git a/tests/components/eheimdigital/fixtures/classic_led_ctrl/acclimate.json b/tests/components/eheimdigital/fixtures/classic_led_ctrl/acclimate.json new file mode 100644 index 00000000000..43159de0488 --- /dev/null +++ b/tests/components/eheimdigital/fixtures/classic_led_ctrl/acclimate.json @@ -0,0 +1,9 @@ +{ + "title": "ACCLIMATE", + "from": "00:00:00:00:00:01", + "duration": 30, + "intensityReduction": 99, + "currentAcclDay": 0, + "acclActive": 0, + "pause": 0 +} diff --git a/tests/components/eheimdigital/fixtures/classic_led_ctrl/ccv.json b/tests/components/eheimdigital/fixtures/classic_led_ctrl/ccv.json new file mode 100644 index 00000000000..68f07d97d64 --- /dev/null +++ b/tests/components/eheimdigital/fixtures/classic_led_ctrl/ccv.json @@ -0,0 +1 @@ +{ "title": "CCV", "from": "00:00:00:00:00:01", "currentValues": [10, 39] } diff --git a/tests/components/eheimdigital/fixtures/classic_led_ctrl/clock.json b/tests/components/eheimdigital/fixtures/classic_led_ctrl/clock.json new file mode 100644 index 00000000000..0606e0154b6 --- /dev/null +++ b/tests/components/eheimdigital/fixtures/classic_led_ctrl/clock.json @@ -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" +} diff --git a/tests/components/eheimdigital/fixtures/classic_led_ctrl/cloud.json b/tests/components/eheimdigital/fixtures/classic_led_ctrl/cloud.json new file mode 100644 index 00000000000..d7e18e75943 --- /dev/null +++ b/tests/components/eheimdigital/fixtures/classic_led_ctrl/cloud.json @@ -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 +} diff --git a/tests/components/eheimdigital/fixtures/classic_led_ctrl/moon.json b/tests/components/eheimdigital/fixtures/classic_led_ctrl/moon.json new file mode 100644 index 00000000000..6a8ba896902 --- /dev/null +++ b/tests/components/eheimdigital/fixtures/classic_led_ctrl/moon.json @@ -0,0 +1,8 @@ +{ + "title": "MOON", + "from": "00:00:00:00:00:01", + "maxmoonlight": 18, + "minmoonlight": 4, + "moonlightActive": 1, + "moonlightCycle": 1 +} diff --git a/tests/components/eheimdigital/fixtures/classic_led_ctrl/usrdta.json b/tests/components/eheimdigital/fixtures/classic_led_ctrl/usrdta.json new file mode 100644 index 00000000000..332e72faabd --- /dev/null +++ b/tests/components/eheimdigital/fixtures/classic_led_ctrl/usrdta.json @@ -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" +} diff --git a/tests/components/eheimdigital/fixtures/classic_vario/classic_vario_data.json b/tests/components/eheimdigital/fixtures/classic_vario/classic_vario_data.json new file mode 100644 index 00000000000..4065818483c --- /dev/null +++ b/tests/components/eheimdigital/fixtures/classic_vario/classic_vario_data.json @@ -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" +} diff --git a/tests/components/eheimdigital/fixtures/classic_vario/usrdta.json b/tests/components/eheimdigital/fixtures/classic_vario/usrdta.json new file mode 100644 index 00000000000..9c3535e9494 --- /dev/null +++ b/tests/components/eheimdigital/fixtures/classic_vario/usrdta.json @@ -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" +} diff --git a/tests/components/eheimdigital/fixtures/heater/heater_data.json b/tests/components/eheimdigital/fixtures/heater/heater_data.json new file mode 100644 index 00000000000..ad8ef1be17d --- /dev/null +++ b/tests/components/eheimdigital/fixtures/heater/heater_data.json @@ -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" +} diff --git a/tests/components/eheimdigital/fixtures/heater/usrdta.json b/tests/components/eheimdigital/fixtures/heater/usrdta.json new file mode 100644 index 00000000000..c243ebb03bd --- /dev/null +++ b/tests/components/eheimdigital/fixtures/heater/usrdta.json @@ -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" +} diff --git a/tests/components/eheimdigital/snapshots/test_light.ambr b/tests/components/eheimdigital/snapshots/test_light.ambr index a8b454f416e..b2398a6a419 100644 --- a/tests/components/eheimdigital/snapshots/test_light.ambr +++ b/tests/components/eheimdigital/snapshots/test_light.ambr @@ -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': , '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': , '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([ , ]), 'supported_features': , }), 'context': , - 'entity_id': 'light.mock_classicledcontrol_e_channel_0', + 'entity_id': 'light.mock_classicledcontrol_e_channel_1', 'last_changed': , 'last_reported': , 'last_updated': , diff --git a/tests/components/eheimdigital/test_climate.py b/tests/components/eheimdigital/test_climate.py index 4abc33e449e..492d001953c 100644 --- a/tests/components/eheimdigital/test_climate.py +++ b/tests/components/eheimdigital/test_climate.py @@ -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"]() diff --git a/tests/components/eheimdigital/test_light.py b/tests/components/eheimdigital/test_light.py index 81b63218085..c6b2063ec0c 100644 --- a/tests/components/eheimdigital/test_light.py +++ b/tests/components/eheimdigital/test_light.py @@ -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 ) diff --git a/tests/components/eheimdigital/test_number.py b/tests/components/eheimdigital/test_number.py index a23f461744a..5235dfcdb75 100644 --- a/tests/components/eheimdigital/test_number.py +++ b/tests/components/eheimdigital/test_number.py @@ -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]) diff --git a/tests/components/eheimdigital/test_select.py b/tests/components/eheimdigital/test_select.py index 89ec91b62a0..ab577bbe0aa 100644 --- a/tests/components/eheimdigital/test_select.py +++ b/tests/components/eheimdigital/test_select.py @@ -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] diff --git a/tests/components/eheimdigital/test_sensor.py b/tests/components/eheimdigital/test_sensor.py index ece4d3eb241..42df22368a9 100644 --- a/tests/components/eheimdigital/test_sensor.py +++ b/tests/components/eheimdigital/test_sensor.py @@ -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]) diff --git a/tests/components/eheimdigital/test_switch.py b/tests/components/eheimdigital/test_switch.py index 440e4776b37..4195c059504 100644 --- a/tests/components/eheimdigital/test_switch.py +++ b/tests/components/eheimdigital/test_switch.py @@ -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]) diff --git a/tests/components/eheimdigital/test_time.py b/tests/components/eheimdigital/test_time.py index acb96ae4023..990a086e633 100644 --- a/tests/components/eheimdigital/test_time.py +++ b/tests/components/eheimdigital/test_time.py @@ -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]