From b69f2856bf54844c10eeb5ae3a91de9e737d4bb1 Mon Sep 17 00:00:00 2001
From: David Bonnes <zxdavb@bonnes.me>
Date: Sat, 5 Oct 2024 22:34:06 +0100
Subject: [PATCH] Add tests for evohome water_heater entities (#127611)

* initial commit

* move get_entity* helper to test

* parameterize with TEST_INSTALLS_WITH_DHW

* remove if from tests
---
 tests/components/evohome/const.py             |   2 +
 .../evohome/snapshots/test_water_heater.ambr  |  19 ++
 tests/components/evohome/test_water_heater.py | 209 ++++++++++++++++++
 3 files changed, 230 insertions(+)
 create mode 100644 tests/components/evohome/snapshots/test_water_heater.ambr
 create mode 100644 tests/components/evohome/test_water_heater.py

diff --git a/tests/components/evohome/const.py b/tests/components/evohome/const.py
index 0db7465e9e5..c3dc92c3fbc 100644
--- a/tests/components/evohome/const.py
+++ b/tests/components/evohome/const.py
@@ -18,3 +18,5 @@ TEST_INSTALLS: Final = (
     "sys_004",  # RoundModulation
 )
 #   "botched",  # as default: but with activeFaults, ghost zones & unknown types
+
+TEST_INSTALLS_WITH_DHW: Final = ("default",)
diff --git a/tests/components/evohome/snapshots/test_water_heater.ambr b/tests/components/evohome/snapshots/test_water_heater.ambr
new file mode 100644
index 00000000000..b521772e6c7
--- /dev/null
+++ b/tests/components/evohome/snapshots/test_water_heater.ambr
@@ -0,0 +1,19 @@
+# serializer version: 1
+# name: test_set_operation_mode[default]
+  list([
+    tuple(
+      dict({
+        'mode': <ZoneMode.TEMPORARY_OVERRIDE: 'TemporaryOverride'>,
+        'state': <DhwState.OFF: 'Off'>,
+        'untilTime': '2024-07-10T12:00:00Z',
+      }),
+    ),
+    tuple(
+      dict({
+        'mode': <ZoneMode.TEMPORARY_OVERRIDE: 'TemporaryOverride'>,
+        'state': <DhwState.ON: 'On'>,
+        'untilTime': '2024-07-10T12:00:00Z',
+      }),
+    ),
+  ])
+# ---
diff --git a/tests/components/evohome/test_water_heater.py b/tests/components/evohome/test_water_heater.py
new file mode 100644
index 00000000000..3dc1d961d29
--- /dev/null
+++ b/tests/components/evohome/test_water_heater.py
@@ -0,0 +1,209 @@
+"""The tests for water_heater entities of evohome.
+
+Not all evohome systems will have a DHW zone.
+"""
+
+from __future__ import annotations
+
+from unittest.mock import patch
+
+from freezegun.api import FrozenDateTimeFactory
+import pytest
+from syrupy import SnapshotAssertion
+
+from homeassistant.components.evohome import DOMAIN
+from homeassistant.components.evohome.coordinator import EvoBroker
+from homeassistant.components.evohome.water_heater import EvoDHW
+from homeassistant.const import Platform
+from homeassistant.core import HomeAssistant
+from homeassistant.helpers import entity_registry as er
+from homeassistant.helpers.entity_component import EntityComponent
+
+from .conftest import setup_evohome
+from .const import TEST_INSTALLS_WITH_DHW
+
+
+def get_dhw_entity(hass: HomeAssistant) -> EvoDHW | None:
+    """Return the DHW entity of the evohome system."""
+
+    broker: EvoBroker = hass.data[DOMAIN]["broker"]
+
+    if (dhw := broker.tcs.hotwater) is None:
+        return None
+
+    entity_registry = er.async_get(hass)
+    entity_id = entity_registry.async_get_entity_id(
+        Platform.WATER_HEATER, DOMAIN, dhw._id
+    )
+
+    component: EntityComponent = hass.data.get(Platform.WATER_HEATER)  # type: ignore[assignment]
+    return next(e for e in component.entities if e.entity_id == entity_id)  # type: ignore[return-value]
+
+
+@pytest.mark.parametrize("install", TEST_INSTALLS_WITH_DHW)
+async def test_set_operation_mode(
+    hass: HomeAssistant,
+    config: dict[str, str],
+    install: str,
+    freezer: FrozenDateTimeFactory,
+    snapshot: SnapshotAssertion,
+) -> None:
+    """Test water_heater services of a evohome-compatible DHW zone."""
+
+    freezer.move_to("2024-07-10T11:55:00Z")
+    results = []
+
+    async for _ in setup_evohome(hass, config, install=install):
+        dhw = get_dhw_entity(hass)
+
+        # set_operation_mode(auto): FollowSchedule
+        with patch("evohomeasync2.hotwater.HotWater._set_mode") as mock_fcn:
+            await dhw.async_set_operation_mode("auto")
+
+            assert mock_fcn.await_count == 1
+            assert mock_fcn.await_args.args == (
+                {
+                    "mode": "FollowSchedule",
+                    "state": None,
+                    "untilTime": None,
+                },
+            )
+            assert mock_fcn.await_args.kwargs == {}
+
+        # set_operation_mode(off): TemporaryOverride, advanced
+        with patch("evohomeasync2.hotwater.HotWater._set_mode") as mock_fcn:
+            await dhw.async_set_operation_mode("off")
+
+            assert mock_fcn.await_count == 1
+            assert install != "default" or mock_fcn.await_args.args == (
+                {
+                    "mode": "TemporaryOverride",
+                    "state": "Off",
+                    "untilTime": "2024-07-10T12:00:00Z",  # varies by install
+                },
+            )
+            assert mock_fcn.await_args.kwargs == {}
+
+            results.append(mock_fcn.await_args.args)
+
+        # set_operation_mode(on): TemporaryOverride, advanced
+        with patch("evohomeasync2.hotwater.HotWater._set_mode") as mock_fcn:
+            await dhw.async_set_operation_mode("on")
+
+            assert mock_fcn.await_count == 1
+            assert install != "default" or mock_fcn.await_args.args == (
+                {
+                    "mode": "TemporaryOverride",
+                    "state": "On",
+                    "untilTime": "2024-07-10T12:00:00Z",  # varies by install
+                },
+            )
+            assert mock_fcn.await_args.kwargs == {}
+
+            results.append(mock_fcn.await_args.args)
+
+    assert results == snapshot
+
+
+@pytest.mark.parametrize("install", TEST_INSTALLS_WITH_DHW)
+async def test_turn_away_mode_off(
+    hass: HomeAssistant,
+    config: dict[str, str],
+    install: str,
+) -> None:
+    """Test water_heater services of a evohome-compatible DHW zone."""
+
+    async for _ in setup_evohome(hass, config, install=install):
+        dhw = get_dhw_entity(hass)
+
+        # turn_away_mode_off(): FollowSchedule
+        with patch("evohomeasync2.hotwater.HotWater._set_mode") as mock_fcn:
+            await dhw.async_turn_away_mode_off()
+
+            assert mock_fcn.await_count == 1
+            assert mock_fcn.await_args.args == (
+                {
+                    "mode": "FollowSchedule",
+                    "state": None,
+                    "untilTime": None,
+                },
+            )
+            assert mock_fcn.await_args.kwargs == {}
+
+
+@pytest.mark.parametrize("install", TEST_INSTALLS_WITH_DHW)
+async def test_turn_away_mode_on(
+    hass: HomeAssistant,
+    config: dict[str, str],
+    install: str,
+) -> None:
+    """Test water_heater services of a evohome-compatible DHW zone."""
+
+    async for _ in setup_evohome(hass, config, install=install):
+        dhw = get_dhw_entity(hass)
+
+        # turn_away_mode_on(): PermanentOverride, Off
+        with patch("evohomeasync2.hotwater.HotWater._set_mode") as mock_fcn:
+            await dhw.async_turn_away_mode_on()
+
+            assert mock_fcn.await_count == 1
+            assert mock_fcn.await_args.args == (
+                {
+                    "mode": "PermanentOverride",
+                    "state": "Off",
+                    "untilTime": None,
+                },
+            )
+            assert mock_fcn.await_args.kwargs == {}
+
+
+@pytest.mark.parametrize("install", TEST_INSTALLS_WITH_DHW)
+async def test_turn_off(
+    hass: HomeAssistant,
+    config: dict[str, str],
+    install: str,
+) -> None:
+    """Test water_heater services of a evohome-compatible DHW zone."""
+
+    async for _ in setup_evohome(hass, config, install=install):
+        dhw = get_dhw_entity(hass)
+
+        # turn_off(): PermanentOverride, Off
+        with patch("evohomeasync2.hotwater.HotWater._set_mode") as mock_fcn:
+            await dhw.async_turn_off()
+
+            assert mock_fcn.await_count == 1
+            assert mock_fcn.await_args.args == (
+                {
+                    "mode": "PermanentOverride",
+                    "state": "Off",
+                    "untilTime": None,
+                },
+            )
+            assert mock_fcn.await_args.kwargs == {}
+
+
+@pytest.mark.parametrize("install", TEST_INSTALLS_WITH_DHW)
+async def test_turn_on(
+    hass: HomeAssistant,
+    config: dict[str, str],
+    install: str,
+) -> None:
+    """Test water_heater services of a evohome-compatible DHW zone."""
+
+    async for _ in setup_evohome(hass, config, install=install):
+        dhw = get_dhw_entity(hass)
+
+        # turn_on(): PermanentOverride, On
+        with patch("evohomeasync2.hotwater.HotWater._set_mode") as mock_fcn:
+            await dhw.async_turn_on()
+
+            assert mock_fcn.await_count == 1
+            assert mock_fcn.await_args.args == (
+                {
+                    "mode": "PermanentOverride",
+                    "state": "On",
+                    "untilTime": None,
+                },
+            )
+            assert mock_fcn.await_args.kwargs == {}
-- 
GitLab