Increase nest climate test coverage (#44146)

This commit is contained in:
Allen Porter 2020-12-12 11:57:02 -08:00 committed by GitHub
parent 05f9fb80c8
commit 1a8123aba6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 290 additions and 18 deletions

View File

@ -580,7 +580,6 @@ omit =
homeassistant/components/nest/camera_legacy.py
homeassistant/components/nest/climate.py
homeassistant/components/nest/climate_legacy.py
homeassistant/components/nest/climate_sdm.py
homeassistant/components/nest/local_auth.py
homeassistant/components/nest/sensor.py
homeassistant/components/nest/sensor_legacy.py

View File

@ -186,8 +186,6 @@ class ThermostatEntity(ClimateEntity):
@property
def _target_temperature_trait(self):
"""Return the correct trait with a target temp depending on mode."""
if not self.hvac_mode:
return None
if self.preset_mode == PRESET_ECO:
if ThermostatEcoTrait.NAME in self._device.traits:
return self._device.traits[ThermostatEcoTrait.NAME]
@ -225,8 +223,6 @@ class ThermostatEntity(ClimateEntity):
@property
def hvac_action(self):
"""Return the current HVAC action (heating, cooling)."""
if ThermostatHvacTrait.NAME not in self._device.traits:
return None
trait = self._device.traits[ThermostatHvacTrait.NAME]
if trait.status in THERMOSTAT_HVAC_STATUS_MAP:
return THERMOSTAT_HVAC_STATUS_MAP[trait.status]
@ -262,9 +258,10 @@ class ThermostatEntity(ClimateEntity):
@property
def fan_modes(self):
"""Return the list of available fan modes."""
modes = []
if FanTrait.NAME in self._device.traits:
return list(FAN_INV_MODE_MAP)
return []
modes = list(FAN_INV_MODE_MAP)
return modes
@property
def supported_features(self):
@ -290,12 +287,8 @@ class ThermostatEntity(ClimateEntity):
async def async_set_hvac_mode(self, hvac_mode):
"""Set new target hvac mode."""
if hvac_mode not in self.hvac_modes:
return
if hvac_mode not in THERMOSTAT_INV_MODE_MAP:
return
raise ValueError(f"Unsupported hvac_mode '{hvac_mode}'")
api_mode = THERMOSTAT_INV_MODE_MAP[hvac_mode]
if ThermostatModeTrait.NAME not in self._device.traits:
return
trait = self._device.traits[ThermostatModeTrait.NAME]
await trait.set_mode(api_mode)
@ -318,17 +311,13 @@ class ThermostatEntity(ClimateEntity):
async def async_set_preset_mode(self, preset_mode):
"""Set new target preset mode."""
if preset_mode not in self.preset_modes:
return
if ThermostatEcoTrait.NAME not in self._device.traits:
return
raise ValueError(f"Unsupported preset_mode '{preset_mode}'")
trait = self._device.traits[ThermostatEcoTrait.NAME]
await trait.set_mode(PRESET_INV_MODE_MAP[preset_mode])
async def async_set_fan_mode(self, fan_mode):
"""Set new target fan mode."""
if fan_mode not in self.fan_modes:
return
if FanTrait.NAME not in self._device.traits:
return
raise ValueError(f"Unsupported fan__mode '{fan_mode}'")
trait = self._device.traits[FanTrait.NAME]
await trait.set_timer(FAN_INV_MODE_MAP[fan_mode])

View File

@ -7,6 +7,7 @@ pubsub subscriber.
from google_nest_sdm.device import Device
from google_nest_sdm.event import EventMessage
import pytest
from homeassistant.components.climate.const import (
ATTR_CURRENT_TEMPERATURE,
@ -21,14 +22,17 @@ from homeassistant.components.climate.const import (
CURRENT_HVAC_COOL,
CURRENT_HVAC_HEAT,
CURRENT_HVAC_OFF,
FAN_LOW,
FAN_OFF,
FAN_ON,
HVAC_MODE_COOL,
HVAC_MODE_DRY,
HVAC_MODE_HEAT,
HVAC_MODE_HEAT_COOL,
HVAC_MODE_OFF,
PRESET_ECO,
PRESET_NONE,
PRESET_SLEEP,
)
from homeassistant.const import ATTR_TEMPERATURE
@ -450,6 +454,34 @@ async def test_thermostat_set_hvac_mode(hass, auth):
assert thermostat.attributes[ATTR_HVAC_ACTION] == CURRENT_HVAC_HEAT
async def test_thermostat_invalid_hvac_mode(hass, auth):
"""Test setting an hvac_mode that is not supported."""
await setup_climate(
hass,
{
"sdm.devices.traits.ThermostatHvac": {"status": "OFF"},
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
"mode": "OFF",
},
},
auth=auth,
)
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVAC_MODE_OFF
assert thermostat.attributes[ATTR_HVAC_ACTION] == CURRENT_HVAC_OFF
with pytest.raises(ValueError):
await common.async_set_hvac_mode(hass, HVAC_MODE_DRY)
await hass.async_block_till_done()
assert thermostat.state == HVAC_MODE_OFF
assert auth.method is None # No communication with API
async def test_thermostat_set_eco_preset(hass, auth):
"""Test a thermostat put into eco mode."""
subscriber = await setup_climate(
@ -782,6 +814,53 @@ async def test_thermostat_fan_empty(hass):
assert ATTR_FAN_MODE not in thermostat.attributes
assert ATTR_FAN_MODES not in thermostat.attributes
# Ignores set_fan_mode since it is lacking SUPPORT_FAN_MODE
await common.async_set_fan_mode(hass, FAN_ON)
await hass.async_block_till_done()
assert ATTR_FAN_MODE not in thermostat.attributes
assert ATTR_FAN_MODES not in thermostat.attributes
async def test_thermostat_invalid_fan_mode(hass):
"""Test setting a fan mode that is not supported."""
await setup_climate(
hass,
{
"sdm.devices.traits.Fan": {
"timerMode": "ON",
"timerTimeout": "2019-05-10T03:22:54Z",
},
"sdm.devices.traits.ThermostatHvac": {"status": "OFF"},
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
"mode": "OFF",
},
"sdm.devices.traits.Temperature": {
"ambientTemperatureCelsius": 16.2,
},
},
)
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVAC_MODE_OFF
assert thermostat.attributes[ATTR_HVAC_ACTION] == CURRENT_HVAC_OFF
assert thermostat.attributes[ATTR_CURRENT_TEMPERATURE] == 16.2
assert set(thermostat.attributes[ATTR_HVAC_MODES]) == {
HVAC_MODE_HEAT,
HVAC_MODE_COOL,
HVAC_MODE_HEAT_COOL,
HVAC_MODE_OFF,
}
assert thermostat.attributes[ATTR_FAN_MODE] == FAN_ON
assert thermostat.attributes[ATTR_FAN_MODES] == [FAN_ON, FAN_OFF]
with pytest.raises(ValueError):
await common.async_set_fan_mode(hass, FAN_LOW)
await hass.async_block_till_done()
async def test_thermostat_target_temp(hass, auth):
"""Test a thermostat changing hvac modes and affected on target temps."""
@ -843,3 +922,208 @@ async def test_thermostat_target_temp(hass, auth):
assert thermostat.attributes[ATTR_TARGET_TEMP_LOW] == 22.0
assert thermostat.attributes[ATTR_TARGET_TEMP_HIGH] == 28.0
assert thermostat.attributes[ATTR_TEMPERATURE] is None
async def test_thermostat_missing_mode_traits(hass):
"""Test a thermostat missing many thermostat traits in api response."""
await setup_climate(
hass,
{
"sdm.devices.traits.ThermostatHvac": {"status": "OFF"},
},
)
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVAC_MODE_OFF
assert thermostat.attributes[ATTR_HVAC_ACTION] == CURRENT_HVAC_OFF
assert thermostat.attributes[ATTR_CURRENT_TEMPERATURE] is None
assert set(thermostat.attributes[ATTR_HVAC_MODES]) == set()
assert ATTR_TEMPERATURE not in thermostat.attributes
assert ATTR_TARGET_TEMP_LOW not in thermostat.attributes
assert ATTR_TARGET_TEMP_HIGH not in thermostat.attributes
assert ATTR_PRESET_MODE not in thermostat.attributes
assert ATTR_PRESET_MODES not in thermostat.attributes
assert ATTR_FAN_MODE not in thermostat.attributes
assert ATTR_FAN_MODES not in thermostat.attributes
await common.async_set_temperature(hass, temperature=24.0)
await hass.async_block_till_done()
assert ATTR_TEMPERATURE not in thermostat.attributes
await common.async_set_preset_mode(hass, PRESET_ECO)
await hass.async_block_till_done()
assert ATTR_PRESET_MODE not in thermostat.attributes
async def test_thermostat_missing_temperature_trait(hass):
"""Test a thermostat missing many thermostat traits in api response."""
await setup_climate(
hass,
{
"sdm.devices.traits.ThermostatHvac": {"status": "OFF"},
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
"mode": "HEAT",
},
},
)
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVAC_MODE_HEAT
assert thermostat.attributes[ATTR_HVAC_ACTION] == CURRENT_HVAC_OFF
assert thermostat.attributes[ATTR_CURRENT_TEMPERATURE] is None
assert set(thermostat.attributes[ATTR_HVAC_MODES]) == {
HVAC_MODE_HEAT,
HVAC_MODE_COOL,
HVAC_MODE_HEAT_COOL,
HVAC_MODE_OFF,
}
assert thermostat.attributes[ATTR_TEMPERATURE] is None
assert thermostat.attributes[ATTR_TARGET_TEMP_LOW] is None
assert thermostat.attributes[ATTR_TARGET_TEMP_HIGH] is None
assert ATTR_PRESET_MODE not in thermostat.attributes
assert ATTR_PRESET_MODES not in thermostat.attributes
assert ATTR_FAN_MODE not in thermostat.attributes
assert ATTR_FAN_MODES not in thermostat.attributes
await common.async_set_temperature(hass, temperature=24.0)
await hass.async_block_till_done()
assert thermostat.attributes[ATTR_TEMPERATURE] is None
async def test_thermostat_unexpected_hvac_status(hass):
"""Test a thermostat missing many thermostat traits in api response."""
await setup_climate(
hass,
{
"sdm.devices.traits.ThermostatHvac": {"status": "UNEXPECTED"},
},
)
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVAC_MODE_OFF
assert ATTR_HVAC_ACTION not in thermostat.attributes
assert thermostat.attributes[ATTR_CURRENT_TEMPERATURE] is None
assert set(thermostat.attributes[ATTR_HVAC_MODES]) == set()
assert ATTR_TEMPERATURE not in thermostat.attributes
assert ATTR_TARGET_TEMP_LOW not in thermostat.attributes
assert ATTR_TARGET_TEMP_HIGH not in thermostat.attributes
assert ATTR_PRESET_MODE not in thermostat.attributes
assert ATTR_PRESET_MODES not in thermostat.attributes
assert ATTR_FAN_MODE not in thermostat.attributes
assert ATTR_FAN_MODES not in thermostat.attributes
with pytest.raises(ValueError):
await common.async_set_hvac_mode(hass, HVAC_MODE_DRY)
await hass.async_block_till_done()
assert thermostat.state == HVAC_MODE_OFF
async def test_thermostat_missing_set_point(hass):
"""Test a thermostat missing many thermostat traits in api response."""
await setup_climate(
hass,
{
"sdm.devices.traits.ThermostatHvac": {"status": "OFF"},
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
"mode": "HEATCOOL",
},
},
)
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVAC_MODE_HEAT_COOL
assert thermostat.attributes[ATTR_HVAC_ACTION] == CURRENT_HVAC_OFF
assert thermostat.attributes[ATTR_CURRENT_TEMPERATURE] is None
assert set(thermostat.attributes[ATTR_HVAC_MODES]) == {
HVAC_MODE_HEAT,
HVAC_MODE_COOL,
HVAC_MODE_HEAT_COOL,
HVAC_MODE_OFF,
}
assert thermostat.attributes[ATTR_TEMPERATURE] is None
assert thermostat.attributes[ATTR_TARGET_TEMP_LOW] is None
assert thermostat.attributes[ATTR_TARGET_TEMP_HIGH] is None
assert ATTR_PRESET_MODE not in thermostat.attributes
assert ATTR_PRESET_MODES not in thermostat.attributes
assert ATTR_FAN_MODE not in thermostat.attributes
assert ATTR_FAN_MODES not in thermostat.attributes
async def test_thermostat_unexepected_hvac_mode(hass):
"""Test a thermostat missing many thermostat traits in api response."""
await setup_climate(
hass,
{
"sdm.devices.traits.ThermostatHvac": {"status": "OFF"},
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF", "UNEXPECTED"],
"mode": "UNEXPECTED",
},
},
)
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVAC_MODE_OFF
assert thermostat.attributes[ATTR_HVAC_ACTION] == CURRENT_HVAC_OFF
assert thermostat.attributes[ATTR_CURRENT_TEMPERATURE] is None
assert set(thermostat.attributes[ATTR_HVAC_MODES]) == {
HVAC_MODE_HEAT,
HVAC_MODE_COOL,
HVAC_MODE_HEAT_COOL,
HVAC_MODE_OFF,
}
assert thermostat.attributes[ATTR_TEMPERATURE] is None
assert thermostat.attributes[ATTR_TARGET_TEMP_LOW] is None
assert thermostat.attributes[ATTR_TARGET_TEMP_HIGH] is None
assert ATTR_PRESET_MODE not in thermostat.attributes
assert ATTR_PRESET_MODES not in thermostat.attributes
assert ATTR_FAN_MODE not in thermostat.attributes
assert ATTR_FAN_MODES not in thermostat.attributes
async def test_thermostat_invalid_set_preset_mode(hass, auth):
"""Test a thermostat set with an invalid preset mode."""
await setup_climate(
hass,
{
"sdm.devices.traits.ThermostatHvac": {"status": "OFF"},
"sdm.devices.traits.ThermostatEco": {
"availableModes": ["MANUAL_ECO", "OFF"],
"mode": "OFF",
"heatCelsius": 15.0,
"coolCelsius": 28.0,
},
},
auth=auth,
)
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVAC_MODE_OFF
assert thermostat.attributes[ATTR_PRESET_MODE] == PRESET_NONE
assert thermostat.attributes[ATTR_PRESET_MODES] == [PRESET_ECO, PRESET_NONE]
# Set preset mode that is invalid
with pytest.raises(ValueError):
await common.async_set_preset_mode(hass, PRESET_SLEEP)
await hass.async_block_till_done()
# No RPC sent
assert auth.method is None
# Preset is unchanged
assert thermostat.attributes[ATTR_PRESET_MODE] == PRESET_NONE
assert thermostat.attributes[ATTR_PRESET_MODES] == [PRESET_ECO, PRESET_NONE]