From b446eaf2d03302fb3bcf7e106dde9ef741edf1f3 Mon Sep 17 00:00:00 2001 From: Jan Bouwhuis Date: Thu, 16 Jan 2025 23:04:57 +0100 Subject: [PATCH] Improve incomfort test coverage (#135806) --- tests/components/incomfort/conftest.py | 19 +++++++- tests/components/incomfort/test_climate.py | 53 +++++++++++++++++++++- tests/components/incomfort/test_init.py | 53 +++++++++++++++++++++- 3 files changed, 121 insertions(+), 4 deletions(-) diff --git a/tests/components/incomfort/conftest.py b/tests/components/incomfort/conftest.py index a6acd79764c..a450b7e26d3 100644 --- a/tests/components/incomfort/conftest.py +++ b/tests/components/incomfort/conftest.py @@ -20,7 +20,7 @@ MOCK_CONFIG = { } MOCK_HEATER_STATUS = { - "display_code": DisplayCode(126), + "display_code": DisplayCode.STANDBY, "display_text": "standby", "fault_code": None, "is_burning": False, @@ -36,6 +36,23 @@ MOCK_HEATER_STATUS = { "rfstatus_cntr": 0, } +MOCK_HEATER_STATUS_HEATING = { + "display_code": DisplayCode.OPENTHERM, + "display_text": "opentherm", + "fault_code": None, + "is_burning": True, + "is_failed": False, + "is_pumping": True, + "is_tapping": False, + "heater_temp": 35.34, + "tap_temp": 30.21, + "pressure": 1.86, + "serial_no": "c0ffeec0ffee", + "nodenr": 249, + "rf_message_rssi": 30, + "rfstatus_cntr": 0, +} + @pytest.fixture def mock_setup_entry() -> Generator[AsyncMock]: diff --git a/tests/components/incomfort/test_climate.py b/tests/components/incomfort/test_climate.py index 06aa8fc056e..dbcf14e3bd7 100644 --- a/tests/components/incomfort/test_climate.py +++ b/tests/components/incomfort/test_climate.py @@ -1,15 +1,19 @@ """Climate sensor tests for Intergas InComfort integration.""" -from unittest.mock import MagicMock, patch +from unittest.mock import AsyncMock, MagicMock, patch import pytest from syrupy import SnapshotAssertion +from homeassistant.components import climate +from homeassistant.components.incomfort.coordinator import InComfortData from homeassistant.config_entries import ConfigEntry -from homeassistant.const import Platform +from homeassistant.const import ATTR_ENTITY_ID, ATTR_TEMPERATURE, Platform from homeassistant.core import HomeAssistant from homeassistant.helpers import entity_registry as er +from .conftest import MOCK_HEATER_STATUS, MOCK_HEATER_STATUS_HEATING + from tests.common import snapshot_platform @@ -42,3 +46,48 @@ async def test_setup_platform( """ await hass.config_entries.async_setup(mock_config_entry.entry_id) await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id) + + +@pytest.mark.parametrize( + ("mock_heater_status", "hvac_action"), + [ + (MOCK_HEATER_STATUS.copy(), climate.HVACAction.IDLE), + (MOCK_HEATER_STATUS_HEATING.copy(), climate.HVACAction.HEATING), + ], + ids=["idle", "heating"], +) +async def test_hvac_state( + hass: HomeAssistant, + mock_incomfort: MagicMock, + mock_config_entry: ConfigEntry, + hvac_action: climate.HVACAction, +) -> None: + """Test the HVAC state of the thermostat.""" + await hass.config_entries.async_setup(mock_config_entry.entry_id) + state = hass.states.get("climate.thermostat_1") + assert state is not None + assert state.attributes["hvac_action"] is hvac_action + + +async def test_target_temp( + hass: HomeAssistant, mock_incomfort: MagicMock, mock_config_entry: ConfigEntry +) -> None: + """Test changing the target temperature.""" + await hass.config_entries.async_setup(mock_config_entry.entry_id) + state = hass.states.get("climate.thermostat_1") + assert state is not None + + incomfort_data: InComfortData = mock_config_entry.runtime_data.incomfort_data + + with patch.object( + incomfort_data.heaters[0].rooms[0], "set_override", AsyncMock() + ) as mock_set_override: + await hass.services.async_call( + climate.DOMAIN, + climate.SERVICE_SET_TEMPERATURE, + service_data={ + ATTR_ENTITY_ID: "climate.thermostat_1", + ATTR_TEMPERATURE: 19.0, + }, + ) + mock_set_override.assert_called_once_with(19.0) diff --git a/tests/components/incomfort/test_init.py b/tests/components/incomfort/test_init.py index 504ab02ea81..7557e36219c 100644 --- a/tests/components/incomfort/test_init.py +++ b/tests/components/incomfort/test_init.py @@ -1,13 +1,14 @@ """Tests for Intergas InComfort integration.""" from datetime import timedelta -from unittest.mock import MagicMock, patch +from unittest.mock import AsyncMock, MagicMock, patch from aiohttp import ClientResponseError, RequestInfo from freezegun.api import FrozenDateTimeFactory from incomfortclient import IncomfortError import pytest +from homeassistant.components.incomfort import InvalidHeaterList from homeassistant.components.incomfort.coordinator import UPDATE_INTERVAL from homeassistant.config_entries import ConfigEntry, ConfigEntryState from homeassistant.const import STATE_UNAVAILABLE @@ -102,3 +103,53 @@ async def test_coordinator_update_fails( state = hass.states.get("sensor.boiler_pressure") assert state is not None assert state.state == STATE_UNAVAILABLE + + +@pytest.mark.parametrize( + ("exc", "config_entry_state"), + [ + ( + IncomfortError(ClientResponseError(None, None, status=401)), + ConfigEntryState.SETUP_ERROR, + ), + ( + IncomfortError(ClientResponseError(None, None, status=404)), + ConfigEntryState.SETUP_ERROR, + ), + (InvalidHeaterList, ConfigEntryState.SETUP_RETRY), + ( + IncomfortError( + ClientResponseError( + RequestInfo( + url="http://example.com", + method="GET", + headers=[], + real_url="http://example.com", + ), + None, + status=500, + ) + ), + ConfigEntryState.SETUP_RETRY, + ), + (IncomfortError(ValueError("some_error")), ConfigEntryState.SETUP_RETRY), + (TimeoutError, ConfigEntryState.SETUP_RETRY), + ], +) +async def test_entry_setup_fails( + hass: HomeAssistant, + mock_incomfort: MagicMock, + freezer: FrozenDateTimeFactory, + mock_config_entry: ConfigEntry, + exc: Exception, + config_entry_state: ConfigEntryState, +) -> None: + """Test the incomfort coordinator entry setup fails.""" + with patch( + "homeassistant.components.incomfort.async_connect_gateway", + AsyncMock(side_effect=exc), + ): + await hass.config_entries.async_setup(mock_config_entry.entry_id) + state = hass.states.get("sensor.boiler_pressure") + assert state is None + assert mock_config_entry.state is config_entry_state