From 77a91f5a8f473585fb8d635058c1b398a54441a0 Mon Sep 17 00:00:00 2001 From: David Bonnes Date: Thu, 24 Oct 2024 15:01:29 +0100 Subject: [PATCH] Switch to using a fixture for evohome WaterHeater tests (#127701) Co-authored-by: Christopher Fenner <9592452+CFenner@users.noreply.github.com> Co-authored-by: Joost Lekkerkerker Co-authored-by: Erik Montnemery Co-authored-by: Robert Resch Co-authored-by: thecem <46648579+thecem@users.noreply.github.com> Co-authored-by: Franck Nijhof Co-authored-by: Jan-Philipp Benecke Co-authored-by: G Johansson Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: epenet <6771947+epenet@users.noreply.github.com> --- tests/components/evohome/conftest.py | 24 +- .../evohome/snapshots/test_water_heater.ambr | 10 - tests/components/evohome/test_water_heater.py | 273 ++++++++---------- 3 files changed, 136 insertions(+), 171 deletions(-) diff --git a/tests/components/evohome/conftest.py b/tests/components/evohome/conftest.py index b46c62f8651..85ef0b5756d 100644 --- a/tests/components/evohome/conftest.py +++ b/tests/components/evohome/conftest.py @@ -138,7 +138,14 @@ async def setup_evohome( patch("homeassistant.components.evohome.ev1.EvohomeClient", return_value=None), patch("evohomeasync2.broker.Broker.get", mock_get_factory(install)), ): - mock_client.side_effect = EvohomeClient + evo: EvohomeClient | None = None + + def evohome_client(*args, **kwargs) -> EvohomeClient: + nonlocal evo + evo = EvohomeClient(*args, **kwargs) + return evo + + mock_client.side_effect = evohome_client assert await async_setup_component(hass, DOMAIN, {DOMAIN: config}) await hass.async_block_till_done() @@ -150,6 +157,19 @@ async def setup_evohome( assert isinstance(mock_client.call_args.kwargs["session"], ClientSession) - assert mock_client.account_info is not None + assert evo and evo.account_info is not None + mock_client.return_value = evo + yield mock_client + + +@pytest.fixture +async def evohome( + hass: HomeAssistant, + config: dict[str, str], + install: str, +) -> AsyncGenerator[MagicMock]: + """Return the mocked evohome client for this install fixture.""" + + async for mock_client in setup_evohome(hass, config, install=install): yield mock_client diff --git a/tests/components/evohome/snapshots/test_water_heater.ambr b/tests/components/evohome/snapshots/test_water_heater.ambr index b521772e6c7..ccef7ab3fae 100644 --- a/tests/components/evohome/snapshots/test_water_heater.ambr +++ b/tests/components/evohome/snapshots/test_water_heater.ambr @@ -2,18 +2,8 @@ # name: test_set_operation_mode[default] list([ tuple( - dict({ - 'mode': , - 'state': , - 'untilTime': '2024-07-10T12:00:00Z', - }), ), tuple( - dict({ - 'mode': , - 'state': , - 'untilTime': '2024-07-10T12:00:00Z', - }), ), ]) # --- diff --git a/tests/components/evohome/test_water_heater.py b/tests/components/evohome/test_water_heater.py index 3dc1d961d29..b0eaba106a1 100644 --- a/tests/components/evohome/test_water_heater.py +++ b/tests/components/evohome/test_water_heater.py @@ -7,203 +7,158 @@ from __future__ import annotations from unittest.mock import patch +from evohomeasync2 import EvohomeClient 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.components.water_heater import ( + ATTR_AWAY_MODE, + ATTR_OPERATION_MODE, + SERVICE_SET_AWAY_MODE, + SERVICE_SET_OPERATION_MODE, +) +from homeassistant.const import ( + ATTR_ENTITY_ID, + SERVICE_TURN_OFF, + SERVICE_TURN_ON, + Platform, +) from homeassistant.core import HomeAssistant -from homeassistant.helpers import entity_registry as er -from homeassistant.helpers.entity_component import EntityComponent +from homeassistant.exceptions import HomeAssistantError -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] +DHW_ENTITY_ID = "water_heater.domestic_hot_water" @pytest.mark.parametrize("install", TEST_INSTALLS_WITH_DHW) async def test_set_operation_mode( hass: HomeAssistant, - config: dict[str, str], - install: str, + evohome: EvohomeClient, freezer: FrozenDateTimeFactory, snapshot: SnapshotAssertion, ) -> None: - """Test water_heater services of a evohome-compatible DHW zone.""" + """Test SERVICE_SET_OPERATION_MODE of a evohome HotWater entity.""" freezer.move_to("2024-07-10T11:55:00Z") results = [] - async for _ in setup_evohome(hass, config, install=install): - dhw = get_dhw_entity(hass) + # SERVICE_SET_OPERATION_MODE: auto + with patch("evohomeasync2.hotwater.HotWater.reset_mode") as mock_fcn: + await hass.services.async_call( + Platform.WATER_HEATER, + SERVICE_SET_OPERATION_MODE, + { + ATTR_ENTITY_ID: DHW_ENTITY_ID, + ATTR_OPERATION_MODE: "auto", + }, + blocking=True, + ) - # 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 == () + assert mock_fcn.await_args.kwargs == {} - assert mock_fcn.await_count == 1 - assert mock_fcn.await_args.args == ( - { - "mode": "FollowSchedule", - "state": None, - "untilTime": None, - }, - ) - assert mock_fcn.await_args.kwargs == {} + # SERVICE_SET_OPERATION_MODE: off (until next scheduled setpoint) + with patch("evohomeasync2.hotwater.HotWater.set_off") as mock_fcn: + await hass.services.async_call( + Platform.WATER_HEATER, + SERVICE_SET_OPERATION_MODE, + { + ATTR_ENTITY_ID: DHW_ENTITY_ID, + ATTR_OPERATION_MODE: "off", + }, + blocking=True, + ) - # 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 mock_fcn.await_args.args == () + results.append(mock_fcn.await_args.args) - 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 == {} + # SERVICE_SET_OPERATION_MODE: on (until next scheduled setpoint) + with patch("evohomeasync2.hotwater.HotWater.set_on") as mock_fcn: + await hass.services.async_call( + Platform.WATER_HEATER, + SERVICE_SET_OPERATION_MODE, + { + ATTR_ENTITY_ID: DHW_ENTITY_ID, + ATTR_OPERATION_MODE: "on", + }, + blocking=True, + ) - 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 mock_fcn.await_count == 1 + assert mock_fcn.await_args.args == () + 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 def test_set_away_mode(hass: HomeAssistant, evohome: EvohomeClient) -> None: + """Test SERVICE_SET_AWAY_MODE of a evohome HotWater entity.""" - async for _ in setup_evohome(hass, config, install=install): - dhw = get_dhw_entity(hass) + # set_away_mode: off + with patch("evohomeasync2.hotwater.HotWater.reset_mode") as mock_fcn: + await hass.services.async_call( + Platform.WATER_HEATER, + SERVICE_SET_AWAY_MODE, + { + ATTR_ENTITY_ID: DHW_ENTITY_ID, + ATTR_AWAY_MODE: "off", + }, + blocking=True, + ) - # 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 == () + assert mock_fcn.await_args.kwargs == {} - 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_away_mode: off + with patch("evohomeasync2.hotwater.HotWater.set_off") as mock_fcn: + await hass.services.async_call( + Platform.WATER_HEATER, + SERVICE_SET_AWAY_MODE, + { + ATTR_ENTITY_ID: DHW_ENTITY_ID, + ATTR_AWAY_MODE: "on", + }, + blocking=True, + ) + + assert mock_fcn.await_count == 1 + assert mock_fcn.await_args.args == () + 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 def test_turn_off(hass: HomeAssistant, evohome: EvohomeClient) -> None: + """Test SERVICE_TURN_OFF of a evohome HotWater entity.""" - 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 == {} + # Entity water_heater.domestic_hot_water does not support this service + with pytest.raises(HomeAssistantError): + await hass.services.async_call( + Platform.WATER_HEATER, + SERVICE_TURN_OFF, + { + ATTR_ENTITY_ID: DHW_ENTITY_ID, + }, + blocking=True, + ) @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 def test_turn_on(hass: HomeAssistant, evohome: EvohomeClient) -> None: + """Test SERVICE_TURN_ON of a evohome HotWater entity.""" - 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 == {} + # Entity water_heater.domestic_hot_water does not support this service + with pytest.raises(HomeAssistantError): + await hass.services.async_call( + Platform.WATER_HEATER, + SERVICE_TURN_ON, + { + ATTR_ENTITY_ID: DHW_ENTITY_ID, + }, + blocking=True, + )