Add tests for over switch AC mode
This commit is contained in:
@@ -5,7 +5,7 @@ from unittest.mock import patch, MagicMock
|
||||
import pytest # pylint: disable=unused-import
|
||||
|
||||
from homeassistant.core import HomeAssistant, Event, EVENT_STATE_CHANGED, State
|
||||
from homeassistant.const import UnitOfTemperature, STATE_ON, STATE_OFF
|
||||
from homeassistant.const import UnitOfTemperature, STATE_ON, STATE_OFF, ATTR_TEMPERATURE
|
||||
|
||||
from homeassistant.config_entries import ConfigEntryState
|
||||
from homeassistant.util import dt as dt_util
|
||||
@@ -29,14 +29,17 @@ from .const import ( # pylint: disable=unused-import
|
||||
MOCK_TH_OVER_4SWITCH_USER_CONFIG,
|
||||
MOCK_TH_OVER_CLIMATE_USER_CONFIG,
|
||||
MOCK_TH_OVER_SWITCH_TYPE_CONFIG,
|
||||
MOCK_TH_OVER_SWITCH_AC_TYPE_CONFIG,
|
||||
MOCK_TH_OVER_4SWITCH_TYPE_CONFIG,
|
||||
MOCK_TH_OVER_CLIMATE_TYPE_CONFIG,
|
||||
MOCK_TH_OVER_SWITCH_TPI_CONFIG,
|
||||
MOCK_PRESETS_CONFIG,
|
||||
MOCK_PRESETS_AC_CONFIG,
|
||||
MOCK_WINDOW_CONFIG,
|
||||
MOCK_MOTION_CONFIG,
|
||||
MOCK_POWER_CONFIG,
|
||||
MOCK_PRESENCE_CONFIG,
|
||||
MOCK_PRESENCE_AC_CONFIG,
|
||||
MOCK_ADVANCED_CONFIG,
|
||||
# MOCK_DEFAULT_FEATURE_CONFIG,
|
||||
PRESET_BOOST,
|
||||
@@ -58,6 +61,19 @@ FULL_SWITCH_CONFIG = (
|
||||
| MOCK_ADVANCED_CONFIG
|
||||
)
|
||||
|
||||
FULL_SWITCH_AC_CONFIG = (
|
||||
MOCK_TH_OVER_SWITCH_USER_CONFIG
|
||||
| MOCK_TH_OVER_SWITCH_AC_TYPE_CONFIG
|
||||
| MOCK_TH_OVER_SWITCH_TPI_CONFIG
|
||||
| MOCK_PRESETS_AC_CONFIG
|
||||
| MOCK_WINDOW_CONFIG
|
||||
| MOCK_MOTION_CONFIG
|
||||
| MOCK_POWER_CONFIG
|
||||
| MOCK_PRESENCE_AC_CONFIG
|
||||
| MOCK_ADVANCED_CONFIG
|
||||
)
|
||||
|
||||
|
||||
PARTIAL_CLIMATE_CONFIG = (
|
||||
MOCK_TH_OVER_CLIMATE_USER_CONFIG
|
||||
| MOCK_TH_OVER_CLIMATE_TYPE_CONFIG
|
||||
@@ -83,7 +99,7 @@ _LOGGER = logging.getLogger(__name__)
|
||||
class MockClimate(ClimateEntity):
|
||||
"""A Mock Climate class used for Underlying climate mode"""
|
||||
|
||||
def __init__(self, hass: HomeAssistant, unique_id, name, entry_infos, hvac_mode:HVACMode = HVACMode.OFF) -> None:
|
||||
def __init__(self, hass: HomeAssistant, unique_id, name, entry_infos, hvac_mode:HVACMode = HVACMode.OFF) -> None: # pylint: disable=unused-argument
|
||||
"""Initialize the thermostat."""
|
||||
|
||||
super().__init__()
|
||||
@@ -101,12 +117,13 @@ class MockClimate(ClimateEntity):
|
||||
self._attr_target_temperature = 20
|
||||
self._attr_current_temperature = 15
|
||||
|
||||
def set_temperature(self, temperature):
|
||||
def set_temperature(self, **kwargs):
|
||||
""" Set the target temperature"""
|
||||
temperature = kwargs.get(ATTR_TEMPERATURE)
|
||||
self._attr_target_temperature = temperature
|
||||
self.async_write_ha_state()
|
||||
|
||||
def async_set_hvac_mode(self, hvac_mode):
|
||||
async def async_set_hvac_mode(self, hvac_mode):
|
||||
""" The hvac mode"""
|
||||
self._attr_hvac_mode = hvac_mode
|
||||
self.async_write_ha_state()
|
||||
@@ -114,7 +131,7 @@ class MockClimate(ClimateEntity):
|
||||
class MockUnavailableClimate(ClimateEntity):
|
||||
"""A Mock Climate class used for Underlying climate mode"""
|
||||
|
||||
def __init__(self, hass: HomeAssistant, unique_id, name, entry_infos) -> None:
|
||||
def __init__(self, hass: HomeAssistant, unique_id, name, entry_infos) -> None: # pylint: disable=unused-argument
|
||||
"""Initialize the thermostat."""
|
||||
|
||||
super().__init__()
|
||||
|
||||
@@ -51,7 +51,6 @@ from custom_components.versatile_thermostat.const import (
|
||||
PRESET_AWAY_SUFFIX,
|
||||
CONF_CLIMATE,
|
||||
)
|
||||
|
||||
MOCK_TH_OVER_SWITCH_USER_CONFIG = {
|
||||
CONF_NAME: "TheOverSwitchMockName",
|
||||
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_SWITCH,
|
||||
@@ -100,6 +99,12 @@ MOCK_TH_OVER_SWITCH_TYPE_CONFIG = {
|
||||
CONF_AC_MODE: False,
|
||||
}
|
||||
|
||||
MOCK_TH_OVER_SWITCH_AC_TYPE_CONFIG = {
|
||||
CONF_HEATER: "switch.mock_air_conditioner",
|
||||
CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI,
|
||||
CONF_AC_MODE: True,
|
||||
}
|
||||
|
||||
MOCK_TH_OVER_4SWITCH_TYPE_CONFIG = {
|
||||
CONF_HEATER: "switch.mock_4switch0",
|
||||
CONF_HEATER_2: "switch.mock_4switch1",
|
||||
@@ -116,6 +121,7 @@ MOCK_TH_OVER_SWITCH_TPI_CONFIG = {
|
||||
|
||||
MOCK_TH_OVER_CLIMATE_TYPE_CONFIG = {
|
||||
CONF_CLIMATE: "climate.mock_climate",
|
||||
CONF_AC_MODE: False,
|
||||
}
|
||||
|
||||
MOCK_PRESETS_CONFIG = {
|
||||
@@ -124,6 +130,15 @@ MOCK_PRESETS_CONFIG = {
|
||||
PRESET_BOOST + "_temp": 18,
|
||||
}
|
||||
|
||||
MOCK_PRESETS_AC_CONFIG = {
|
||||
PRESET_ECO + "_temp": 17,
|
||||
PRESET_COMFORT + "_temp": 19,
|
||||
PRESET_BOOST + "_temp": 20,
|
||||
PRESET_ECO + "_ac_temp": 25,
|
||||
PRESET_COMFORT + "_ac_temp": 23,
|
||||
PRESET_BOOST + "_ac_temp": 21,
|
||||
}
|
||||
|
||||
MOCK_WINDOW_CONFIG = {
|
||||
CONF_WINDOW_SENSOR: "binary_sensor.window_sensor",
|
||||
CONF_WINDOW_DELAY: 10,
|
||||
@@ -156,6 +171,16 @@ MOCK_PRESENCE_CONFIG = {
|
||||
PRESET_BOOST + PRESET_AWAY_SUFFIX + "_temp": 18,
|
||||
}
|
||||
|
||||
MOCK_PRESENCE_AC_CONFIG = {
|
||||
CONF_PRESENCE_SENSOR: "person.presence_sensor",
|
||||
PRESET_ECO + PRESET_AWAY_SUFFIX + "_temp": 16,
|
||||
PRESET_COMFORT + PRESET_AWAY_SUFFIX + "_temp": 17,
|
||||
PRESET_BOOST + PRESET_AWAY_SUFFIX + "_temp": 18,
|
||||
PRESET_ECO + "_ac" + PRESET_AWAY_SUFFIX + "_temp": 27,
|
||||
PRESET_COMFORT + "_ac" + PRESET_AWAY_SUFFIX + "_temp": 26,
|
||||
PRESET_BOOST + "_ac" + PRESET_AWAY_SUFFIX + "_temp": 25,
|
||||
}
|
||||
|
||||
MOCK_ADVANCED_CONFIG = {
|
||||
CONF_MINIMAL_ACTIVATION_DELAY: 10,
|
||||
CONF_SECURITY_DELAY_MIN: 5,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
""" Test the Window management """
|
||||
import asyncio
|
||||
from datetime import datetime, timedelta
|
||||
import logging
|
||||
from unittest.mock import patch, call, PropertyMock
|
||||
from .commons import * # pylint: disable=wildcard-import, unused-wildcard-import
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import logging
|
||||
|
||||
logging.getLogger().setLevel(logging.DEBUG)
|
||||
|
||||
|
||||
140
tests/test_switch_ac.py
Normal file
140
tests/test_switch_ac.py
Normal file
@@ -0,0 +1,140 @@
|
||||
""" Test the normal start of a Switch AC Thermostat """
|
||||
from unittest.mock import patch, call
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.components.climate import HVACAction, HVACMode
|
||||
from homeassistant.config_entries import ConfigEntryState
|
||||
|
||||
from homeassistant.helpers.entity_component import EntityComponent
|
||||
from homeassistant.components.climate import ClimateEntity, DOMAIN as CLIMATE_DOMAIN
|
||||
|
||||
from pytest_homeassistant_custom_component.common import MockConfigEntry
|
||||
|
||||
from custom_components.versatile_thermostat.climate import VersatileThermostat
|
||||
|
||||
from .commons import * # pylint: disable=wildcard-import, unused-wildcard-import
|
||||
|
||||
@pytest.mark.parametrize("expected_lingering_tasks", [True])
|
||||
@pytest.mark.parametrize("expected_lingering_timers", [True])
|
||||
async def test_over_switch_ac_full_start(hass: HomeAssistant, skip_hass_states_is_state): # pylint: disable=unused-argument
|
||||
"""Test the normal full start of a thermostat in thermostat_over_switch type"""
|
||||
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
title="TheOverSwitchACMockName",
|
||||
unique_id="uniqueId",
|
||||
data=FULL_SWITCH_AC_CONFIG,
|
||||
)
|
||||
|
||||
tz = get_tz(hass) # pylint: disable=invalid-name
|
||||
now: datetime = datetime.now(tz=tz)
|
||||
|
||||
with patch(
|
||||
"custom_components.versatile_thermostat.climate.VersatileThermostat.send_event"
|
||||
) as mock_send_event:
|
||||
entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
assert entry.state is ConfigEntryState.LOADED
|
||||
|
||||
def find_my_entity(entity_id) -> ClimateEntity:
|
||||
"""Find my new entity"""
|
||||
component: EntityComponent[ClimateEntity] = hass.data[CLIMATE_DOMAIN]
|
||||
for entity in component.entities:
|
||||
if entity.entity_id == entity_id:
|
||||
return entity
|
||||
|
||||
# The name is in the CONF and not the title of the entry
|
||||
entity: VersatileThermostat = find_my_entity("climate.theoverswitchmockname")
|
||||
|
||||
assert entity
|
||||
|
||||
assert entity.name == "TheOverSwitchMockName"
|
||||
assert entity._is_over_climate is False # pylint: disable=protected-access
|
||||
assert entity.ac_mode is True
|
||||
assert entity.hvac_action is HVACAction.OFF
|
||||
assert entity.hvac_mode is HVACMode.OFF
|
||||
assert entity.hvac_modes == [HVACMode.COOL, HVACMode.OFF]
|
||||
assert entity.target_temperature == entity.max_temp
|
||||
assert entity.preset_modes == [
|
||||
PRESET_NONE,
|
||||
PRESET_ECO,
|
||||
PRESET_COMFORT,
|
||||
PRESET_BOOST,
|
||||
PRESET_ACTIVITY,
|
||||
]
|
||||
assert entity.preset_mode is PRESET_NONE
|
||||
assert entity._security_state is False # pylint: disable=protected-access
|
||||
assert entity._window_state is None # pylint: disable=protected-access
|
||||
assert entity._motion_state is None # pylint: disable=protected-access
|
||||
assert entity._presence_state is None # pylint: disable=protected-access
|
||||
assert entity._prop_algorithm is not None # pylint: disable=protected-access
|
||||
|
||||
# should have been called with EventType.PRESET_EVENT and EventType.HVAC_MODE_EVENT
|
||||
assert mock_send_event.call_count == 2
|
||||
|
||||
mock_send_event.assert_has_calls(
|
||||
[
|
||||
call.send_event(EventType.PRESET_EVENT, {"preset": PRESET_NONE}),
|
||||
call.send_event(
|
||||
EventType.HVAC_MODE_EVENT,
|
||||
{"hvac_mode": HVACMode.OFF},
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
# Select a hvacmode, presence and preset
|
||||
await entity.async_set_hvac_mode(HVACMode.COOL)
|
||||
assert entity.hvac_mode is HVACMode.COOL
|
||||
|
||||
event_timestamp = now - timedelta(minutes=4)
|
||||
await send_presence_change_event(entity, True, False, event_timestamp)
|
||||
assert entity._presence_state == STATE_ON # pylint: disable=protected-access
|
||||
|
||||
await entity.async_set_hvac_mode(HVACMode.COOL)
|
||||
assert entity.hvac_mode is HVACMode.COOL
|
||||
|
||||
await entity.async_set_preset_mode(PRESET_COMFORT)
|
||||
assert entity.preset_mode is PRESET_COMFORT
|
||||
assert entity.target_temperature == 23
|
||||
|
||||
# switch to Eco
|
||||
await entity.async_set_preset_mode(PRESET_ECO)
|
||||
assert entity.preset_mode is PRESET_ECO
|
||||
assert entity.target_temperature == 25
|
||||
|
||||
# Unset the presence
|
||||
event_timestamp = now - timedelta(minutes=3)
|
||||
await send_presence_change_event(entity, False, True, event_timestamp)
|
||||
assert entity._presence_state == STATE_OFF # pylint: disable=protected-access
|
||||
assert entity.target_temperature == 27 # eco_ac_away
|
||||
|
||||
# Open a window
|
||||
with patch(
|
||||
"homeassistant.helpers.condition.state", return_value=True
|
||||
):
|
||||
event_timestamp = now - timedelta(minutes=2)
|
||||
try_condition = await send_window_change_event(entity, True, False, event_timestamp)
|
||||
|
||||
# Confirme the window event
|
||||
await try_condition(None)
|
||||
|
||||
assert entity.hvac_mode is HVACMode.OFF
|
||||
assert entity.hvac_action is HVACAction.OFF
|
||||
assert entity.target_temperature == 27 # eco_ac_away
|
||||
|
||||
# Close a window
|
||||
with patch(
|
||||
"homeassistant.helpers.condition.state", return_value=True
|
||||
):
|
||||
event_timestamp = now - timedelta(minutes=2)
|
||||
try_condition = await send_window_change_event(entity, False, True, event_timestamp)
|
||||
|
||||
# Confirme the window event
|
||||
await try_condition(None)
|
||||
|
||||
assert entity.hvac_mode is HVACMode.COOL
|
||||
assert (entity.hvac_action is HVACAction.OFF or entity.hvac_action is HVACAction.IDLE)
|
||||
assert entity.target_temperature == 27 # eco_ac_away
|
||||
|
||||
|
||||
Reference in New Issue
Block a user