mirror of https://github.com/home-assistant/core
260 lines
9.6 KiB
Python
260 lines
9.6 KiB
Python
"""Test the BryantEvolutionClient type."""
|
|
|
|
from collections.abc import Generator
|
|
from datetime import timedelta
|
|
import logging
|
|
from unittest.mock import AsyncMock
|
|
|
|
from freezegun.api import FrozenDateTimeFactory
|
|
import pytest
|
|
from syrupy.assertion import SnapshotAssertion
|
|
|
|
from homeassistant.components.bryant_evolution.climate import SCAN_INTERVAL
|
|
from homeassistant.components.climate import (
|
|
ATTR_FAN_MODE,
|
|
ATTR_HVAC_ACTION,
|
|
ATTR_HVAC_MODE,
|
|
ATTR_TEMPERATURE,
|
|
DOMAIN as CLIMATE_DOMAIN,
|
|
SERVICE_SET_FAN_MODE,
|
|
SERVICE_SET_HVAC_MODE,
|
|
SERVICE_SET_TEMPERATURE,
|
|
HVACAction,
|
|
)
|
|
from homeassistant.const import ATTR_ENTITY_ID
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.helpers import entity_registry as er
|
|
|
|
from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_platform
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
|
|
async def trigger_polling(hass: HomeAssistant, freezer: FrozenDateTimeFactory) -> None:
|
|
"""Trigger a polling event."""
|
|
freezer.tick(SCAN_INTERVAL + timedelta(seconds=1))
|
|
async_fire_time_changed(hass)
|
|
await hass.async_block_till_done()
|
|
|
|
|
|
async def test_setup_integration_success(
|
|
hass: HomeAssistant,
|
|
entity_registry: er.EntityRegistry,
|
|
mock_evolution_entry: MockConfigEntry,
|
|
snapshot: SnapshotAssertion,
|
|
) -> None:
|
|
"""Test that an instance can be constructed."""
|
|
await snapshot_platform(
|
|
hass, entity_registry, snapshot, mock_evolution_entry.entry_id
|
|
)
|
|
|
|
|
|
async def test_set_temperature_mode_cool(
|
|
hass: HomeAssistant,
|
|
mock_evolution_entry: MockConfigEntry,
|
|
mock_evolution_client_factory: Generator[AsyncMock],
|
|
freezer: FrozenDateTimeFactory,
|
|
) -> None:
|
|
"""Test setting the temperature in cool mode."""
|
|
# Start with known initial conditions
|
|
client = await mock_evolution_client_factory(1, 1, "/dev/unused")
|
|
client.read_hvac_mode.return_value = ("COOL", False)
|
|
client.read_cooling_setpoint.return_value = 75
|
|
await trigger_polling(hass, freezer)
|
|
state = hass.states.get("climate.system_1_zone_1")
|
|
assert state.attributes["temperature"] == 75, state.attributes
|
|
|
|
# Make the call, modifting the mock client to throw an exception on
|
|
# read to ensure that the update is visible iff we call
|
|
# async_update_ha_state.
|
|
data = {ATTR_TEMPERATURE: 70}
|
|
data[ATTR_ENTITY_ID] = "climate.system_1_zone_1"
|
|
client.read_cooling_setpoint.side_effect = Exception("fake failure")
|
|
await hass.services.async_call(
|
|
CLIMATE_DOMAIN, SERVICE_SET_TEMPERATURE, data, blocking=True
|
|
)
|
|
|
|
# Verify effect.
|
|
client.set_cooling_setpoint.assert_called_once_with(70)
|
|
state = hass.states.get("climate.system_1_zone_1")
|
|
assert state.attributes["temperature"] == 70
|
|
|
|
|
|
async def test_set_temperature_mode_heat(
|
|
hass: HomeAssistant,
|
|
mock_evolution_entry: MockConfigEntry,
|
|
mock_evolution_client_factory: Generator[AsyncMock],
|
|
freezer: FrozenDateTimeFactory,
|
|
) -> None:
|
|
"""Test setting the temperature in heat mode."""
|
|
|
|
# Start with known initial conditions
|
|
client = await mock_evolution_client_factory(1, 1, "/dev/unused")
|
|
client.read_hvac_mode.return_value = ("HEAT", False)
|
|
client.read_heating_setpoint.return_value = 60
|
|
await trigger_polling(hass, freezer)
|
|
|
|
# Make the call, modifting the mock client to throw an exception on
|
|
# read to ensure that the update is visible iff we call
|
|
# async_update_ha_state.
|
|
data = {"temperature": 65}
|
|
data[ATTR_ENTITY_ID] = "climate.system_1_zone_1"
|
|
client.read_heating_setpoint.side_effect = Exception("fake failure")
|
|
await hass.services.async_call(
|
|
CLIMATE_DOMAIN, SERVICE_SET_TEMPERATURE, data, blocking=True
|
|
)
|
|
# Verify effect.
|
|
state = hass.states.get("climate.system_1_zone_1")
|
|
assert state.attributes["temperature"] == 65, state.attributes
|
|
|
|
|
|
async def test_set_temperature_mode_heat_cool(
|
|
hass: HomeAssistant,
|
|
mock_evolution_entry: MockConfigEntry,
|
|
mock_evolution_client_factory: Generator[AsyncMock],
|
|
freezer: FrozenDateTimeFactory,
|
|
) -> None:
|
|
"""Test setting the temperature in heat_cool mode."""
|
|
|
|
# Enter heat_cool with known setpoints
|
|
mock_client = await mock_evolution_client_factory(1, 1, "/dev/unused")
|
|
mock_client.read_hvac_mode.return_value = ("AUTO", False)
|
|
mock_client.read_cooling_setpoint.return_value = 90
|
|
mock_client.read_heating_setpoint.return_value = 40
|
|
await trigger_polling(hass, freezer)
|
|
state = hass.states.get("climate.system_1_zone_1")
|
|
assert state.state == "heat_cool"
|
|
assert state.attributes["target_temp_low"] == 40
|
|
assert state.attributes["target_temp_high"] == 90
|
|
|
|
# Make the call, modifting the mock client to throw an exception on
|
|
# read to ensure that the update is visible iff we call
|
|
# async_update_ha_state.
|
|
mock_client.read_heating_setpoint.side_effect = Exception("fake failure")
|
|
mock_client.read_cooling_setpoint.side_effect = Exception("fake failure")
|
|
data = {"target_temp_low": 70, "target_temp_high": 80}
|
|
data[ATTR_ENTITY_ID] = "climate.system_1_zone_1"
|
|
await hass.services.async_call(
|
|
CLIMATE_DOMAIN, SERVICE_SET_TEMPERATURE, data, blocking=True
|
|
)
|
|
state = hass.states.get("climate.system_1_zone_1")
|
|
assert state.attributes["target_temp_low"] == 70, state.attributes
|
|
assert state.attributes["target_temp_high"] == 80, state.attributes
|
|
mock_client.set_cooling_setpoint.assert_called_once_with(80)
|
|
mock_client.set_heating_setpoint.assert_called_once_with(70)
|
|
|
|
|
|
async def test_set_fan_mode(
|
|
hass: HomeAssistant,
|
|
mock_evolution_entry: MockConfigEntry,
|
|
mock_evolution_client_factory: Generator[AsyncMock],
|
|
) -> None:
|
|
"""Test that setting fan mode works."""
|
|
mock_client = await mock_evolution_client_factory(1, 1, "/dev/unused")
|
|
fan_modes = ["auto", "low", "med", "high"]
|
|
for mode in fan_modes:
|
|
# Make the call, modifting the mock client to throw an exception on
|
|
# read to ensure that the update is visible iff we call
|
|
# async_update_ha_state.
|
|
mock_client.read_fan_mode.side_effect = Exception("fake failure")
|
|
data = {ATTR_FAN_MODE: mode}
|
|
data[ATTR_ENTITY_ID] = "climate.system_1_zone_1"
|
|
await hass.services.async_call(
|
|
CLIMATE_DOMAIN, SERVICE_SET_FAN_MODE, data, blocking=True
|
|
)
|
|
assert (
|
|
hass.states.get("climate.system_1_zone_1").attributes[ATTR_FAN_MODE] == mode
|
|
)
|
|
mock_client.set_fan_mode.assert_called_with(mode)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("hvac_mode", "evolution_mode"),
|
|
[("heat_cool", "auto"), ("heat", "heat"), ("cool", "cool"), ("off", "off")],
|
|
)
|
|
async def test_set_hvac_mode(
|
|
hass: HomeAssistant,
|
|
mock_evolution_entry: MockConfigEntry,
|
|
mock_evolution_client_factory: Generator[AsyncMock],
|
|
hvac_mode,
|
|
evolution_mode,
|
|
) -> None:
|
|
"""Test that setting HVAC mode works."""
|
|
mock_client = await mock_evolution_client_factory(1, 1, "/dev/unused")
|
|
|
|
# Make the call, modifting the mock client to throw an exception on
|
|
# read to ensure that the update is visible iff we call
|
|
# async_update_ha_state.
|
|
data = {ATTR_HVAC_MODE: hvac_mode}
|
|
data[ATTR_ENTITY_ID] = "climate.system_1_zone_1"
|
|
mock_client.read_hvac_mode.side_effect = Exception("fake failure")
|
|
await hass.services.async_call(
|
|
CLIMATE_DOMAIN, SERVICE_SET_HVAC_MODE, data, blocking=True
|
|
)
|
|
await hass.async_block_till_done()
|
|
assert hass.states.get("climate.system_1_zone_1").state == evolution_mode
|
|
mock_client.set_hvac_mode.assert_called_with(evolution_mode)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("curr_temp", "expected_action"),
|
|
[(62, HVACAction.HEATING), (70, HVACAction.OFF), (80, HVACAction.COOLING)],
|
|
)
|
|
async def test_read_hvac_action_heat_cool(
|
|
hass: HomeAssistant,
|
|
mock_evolution_entry: MockConfigEntry,
|
|
mock_evolution_client_factory: Generator[AsyncMock],
|
|
freezer: FrozenDateTimeFactory,
|
|
curr_temp: int,
|
|
expected_action: HVACAction,
|
|
) -> None:
|
|
"""Test that we can read the current HVAC action in heat_cool mode."""
|
|
htsp = 68
|
|
clsp = 72
|
|
|
|
mock_client = await mock_evolution_client_factory(1, 1, "/dev/unused")
|
|
mock_client.read_heating_setpoint.return_value = htsp
|
|
mock_client.read_cooling_setpoint.return_value = clsp
|
|
is_active = curr_temp < htsp or curr_temp > clsp
|
|
mock_client.read_hvac_mode.return_value = ("auto", is_active)
|
|
mock_client.read_current_temperature.return_value = curr_temp
|
|
await trigger_polling(hass, freezer)
|
|
state = hass.states.get("climate.system_1_zone_1")
|
|
assert state.attributes[ATTR_HVAC_ACTION] == expected_action
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("mode", "active", "expected_action"),
|
|
[
|
|
("heat", True, "heating"),
|
|
("heat", False, "off"),
|
|
("cool", True, "cooling"),
|
|
("cool", False, "off"),
|
|
("off", False, "off"),
|
|
],
|
|
)
|
|
async def test_read_hvac_action(
|
|
hass: HomeAssistant,
|
|
mock_evolution_entry: MockConfigEntry,
|
|
mock_evolution_client_factory: Generator[AsyncMock],
|
|
freezer: FrozenDateTimeFactory,
|
|
mode: str,
|
|
active: bool,
|
|
expected_action: str,
|
|
) -> None:
|
|
"""Test that we can read the current HVAC action."""
|
|
# Initial state should be no action.
|
|
assert (
|
|
hass.states.get("climate.system_1_zone_1").attributes[ATTR_HVAC_ACTION]
|
|
== HVACAction.OFF
|
|
)
|
|
# Perturb the system and verify we see an action.
|
|
mock_client = await mock_evolution_client_factory(1, 1, "/dev/unused")
|
|
mock_client.read_heating_setpoint.return_value = 75 # Needed if mode == heat
|
|
mock_client.read_hvac_mode.return_value = (mode, active)
|
|
await trigger_polling(hass, freezer)
|
|
assert (
|
|
hass.states.get("climate.system_1_zone_1").attributes[ATTR_HVAC_ACTION]
|
|
== expected_action
|
|
)
|