hass-core/tests/components/ecobee/test_climate.py
Mark Coombes f6995b8d17 Add config flow to ecobee (#26634)
* Add basic config flow

* Fix json files

* Update __init__.py

* Fix json errors

* Move constants to const.py

* Add ecobee to generated config flows

* Update config_flow for updated API

* Update manifest to include new dependencies

Bump pyecobee, add aiofiles.

* Update constants for ecobee

* Modify ecobee setup to use config flow

* Bump dependency

* Update binary_sensor to use config_entry

* Update sensor to use config_entry

* Update __init__.py

* Update weather to use config_entry

* Update notify.py

* Update ecobee constants

* Update climate to use config_entry

* Avoid a breaking change on ecobee services

* Store api key from old config entry

* Allow unloading of config entry

* Show user a form before import

* Refine import flow

* Update strings.json to remove import step

Not needed.

* Move third party imports to top of module

* Remove periods from end of log messages

* Make configuration.yaml config optional

* Remove unused strings

* Reorganize config flow

* Remove unneeded requirement

* No need to store API key

* Update async_unload_entry

* Clean up if/else statements

* Update requirements_all.txt

* Fix config schema

* Update __init__.py

* Remove check for DATA_ECOBEE_CONFIG

* Remove redundant check

* Add check for DATA_ECOBEE_CONFIG

* Change setup_platform to async

* Fix state unknown and imports

* Change init step to user

* Have import step raise specific exceptions

* Rearrange try/except block in import flow

* Convert update() and refresh() to coroutines

...and update platforms to use async_update coroutine.

* Finish converting init to async

* Preliminary tests

* Test full implementation

* Update test_config_flow.py

* Update test_config_flow.py

* Add self to codeowners

* Update test_config_flow.py

* Use MockConfigEntry

* Update test_config_flow.py

* Update CODEOWNERS

* pylint fixes

* Register services under ecobee domain

Breaking change!

* Pylint fixes

* Pylint fixes

* Pylint fixes

* Move service strings to ecobee domain

* Fix log message capitalization

* Fix import formatting

* Update .coveragerc

* Add __init__ to coveragerc

* Add option flow test

* Update .coveragerc

* Act on updated options

* Revert "Act on updated options"

This reverts commit 56b0a859f2e3e80b6f4c77a8f784a2b29ee2cce9.

* Remove hold_temp from climate

* Remove hold_temp and options from init

* Remove options handler from config flow

* Remove options strings

* Remove options flow test

* Remove hold_temp constants

* Fix climate tests

* Pass api key to user step in import flow

* Update test_config_flow.py

Ensure that the import step calls the user step with the user's api key as user input if importing from ecobee.conf/validating imported keys fails.
2019-09-25 22:38:21 +02:00

287 lines
11 KiB
Python

"""The test for the Ecobee thermostat module."""
import unittest
from unittest import mock
import homeassistant.const as const
from homeassistant.components.ecobee import climate as ecobee
from homeassistant.const import STATE_OFF
class TestEcobee(unittest.TestCase):
"""Tests for Ecobee climate."""
def setUp(self):
"""Set up test variables."""
vals = {
"name": "Ecobee",
"program": {
"climates": [
{"name": "Climate1", "climateRef": "c1"},
{"name": "Climate2", "climateRef": "c2"},
],
"currentClimateRef": "c1",
},
"runtime": {
"actualTemperature": 300,
"actualHumidity": 15,
"desiredHeat": 400,
"desiredCool": 200,
"desiredFanMode": "on",
},
"settings": {
"hvacMode": "auto",
"heatStages": 1,
"coolStages": 1,
"fanMinOnTime": 10,
"heatCoolMinDelta": 50,
"holdAction": "nextTransition",
},
"equipmentStatus": "fan",
"events": [
{
"name": "Event1",
"running": True,
"type": "hold",
"holdClimateRef": "away",
"endDate": "2017-01-01 10:00:00",
"startDate": "2017-02-02 11:00:00",
}
],
}
self.ecobee = mock.Mock()
self.ecobee.__getitem__ = mock.Mock(side_effect=vals.__getitem__)
self.ecobee.__setitem__ = mock.Mock(side_effect=vals.__setitem__)
self.data = mock.Mock()
self.data.ecobee.get_thermostat.return_value = self.ecobee
self.thermostat = ecobee.Thermostat(self.data, 1)
def test_name(self):
"""Test name property."""
assert "Ecobee" == self.thermostat.name
def test_current_temperature(self):
"""Test current temperature."""
assert 30 == self.thermostat.current_temperature
self.ecobee["runtime"]["actualTemperature"] = 404
assert 40.4 == self.thermostat.current_temperature
def test_target_temperature_low(self):
"""Test target low temperature."""
assert 40 == self.thermostat.target_temperature_low
self.ecobee["runtime"]["desiredHeat"] = 502
assert 50.2 == self.thermostat.target_temperature_low
def test_target_temperature_high(self):
"""Test target high temperature."""
assert 20 == self.thermostat.target_temperature_high
self.ecobee["runtime"]["desiredCool"] = 103
assert 10.3 == self.thermostat.target_temperature_high
def test_target_temperature(self):
"""Test target temperature."""
assert self.thermostat.target_temperature is None
self.ecobee["settings"]["hvacMode"] = "heat"
assert 40 == self.thermostat.target_temperature
self.ecobee["settings"]["hvacMode"] = "cool"
assert 20 == self.thermostat.target_temperature
self.ecobee["settings"]["hvacMode"] = "auxHeatOnly"
assert 40 == self.thermostat.target_temperature
self.ecobee["settings"]["hvacMode"] = "off"
assert self.thermostat.target_temperature is None
def test_desired_fan_mode(self):
"""Test desired fan mode property."""
assert "on" == self.thermostat.fan_mode
self.ecobee["runtime"]["desiredFanMode"] = "auto"
assert "auto" == self.thermostat.fan_mode
def test_fan(self):
"""Test fan property."""
assert const.STATE_ON == self.thermostat.fan
self.ecobee["equipmentStatus"] = ""
assert STATE_OFF == self.thermostat.fan
self.ecobee["equipmentStatus"] = "heatPump, heatPump2"
assert STATE_OFF == self.thermostat.fan
def test_hvac_mode(self):
"""Test current operation property."""
assert "auto" == self.thermostat.hvac_mode
self.ecobee["settings"]["hvacMode"] = "heat"
assert "heat" == self.thermostat.hvac_mode
self.ecobee["settings"]["hvacMode"] = "cool"
assert "cool" == self.thermostat.hvac_mode
self.ecobee["settings"]["hvacMode"] = "auxHeatOnly"
assert "heat" == self.thermostat.hvac_mode
self.ecobee["settings"]["hvacMode"] = "off"
assert "off" == self.thermostat.hvac_mode
def test_hvac_modes(self):
"""Test operation list property."""
assert ["auto", "heat", "cool", "off"] == self.thermostat.hvac_modes
def test_hvac_mode2(self):
"""Test operation mode property."""
assert "auto" == self.thermostat.hvac_mode
self.ecobee["settings"]["hvacMode"] = "heat"
assert "heat" == self.thermostat.hvac_mode
def test_device_state_attributes(self):
"""Test device state attributes property."""
self.ecobee["equipmentStatus"] = "heatPump2"
assert {
"fan": "off",
"climate_mode": "Climate1",
"fan_min_on_time": 10,
"equipment_running": "heatPump2",
} == self.thermostat.device_state_attributes
self.ecobee["equipmentStatus"] = "auxHeat2"
assert {
"fan": "off",
"climate_mode": "Climate1",
"fan_min_on_time": 10,
"equipment_running": "auxHeat2",
} == self.thermostat.device_state_attributes
self.ecobee["equipmentStatus"] = "compCool1"
assert {
"fan": "off",
"climate_mode": "Climate1",
"fan_min_on_time": 10,
"equipment_running": "compCool1",
} == self.thermostat.device_state_attributes
self.ecobee["equipmentStatus"] = ""
assert {
"fan": "off",
"climate_mode": "Climate1",
"fan_min_on_time": 10,
"equipment_running": "",
} == self.thermostat.device_state_attributes
self.ecobee["equipmentStatus"] = "Unknown"
assert {
"fan": "off",
"climate_mode": "Climate1",
"fan_min_on_time": 10,
"equipment_running": "Unknown",
} == self.thermostat.device_state_attributes
self.ecobee["program"]["currentClimateRef"] = "c2"
assert {
"fan": "off",
"climate_mode": "Climate2",
"fan_min_on_time": 10,
"equipment_running": "Unknown",
} == self.thermostat.device_state_attributes
def test_is_aux_heat_on(self):
"""Test aux heat property."""
assert not self.thermostat.is_aux_heat
self.ecobee["equipmentStatus"] = "fan, auxHeat"
assert self.thermostat.is_aux_heat
def test_set_temperature(self):
"""Test set temperature."""
# Auto -> Auto
self.data.reset_mock()
self.thermostat.set_temperature(target_temp_low=20, target_temp_high=30)
self.data.ecobee.set_hold_temp.assert_has_calls(
[mock.call(1, 30, 20, "nextTransition")]
)
# Auto -> Hold
self.data.reset_mock()
self.thermostat.set_temperature(temperature=20)
self.data.ecobee.set_hold_temp.assert_has_calls(
[mock.call(1, 25, 15, "nextTransition")]
)
# Cool -> Hold
self.data.reset_mock()
self.ecobee["settings"]["hvacMode"] = "cool"
self.thermostat.set_temperature(temperature=20.5)
self.data.ecobee.set_hold_temp.assert_has_calls(
[mock.call(1, 20.5, 20.5, "nextTransition")]
)
# Heat -> Hold
self.data.reset_mock()
self.ecobee["settings"]["hvacMode"] = "heat"
self.thermostat.set_temperature(temperature=20)
self.data.ecobee.set_hold_temp.assert_has_calls(
[mock.call(1, 20, 20, "nextTransition")]
)
# Heat -> Auto
self.data.reset_mock()
self.ecobee["settings"]["hvacMode"] = "heat"
self.thermostat.set_temperature(target_temp_low=20, target_temp_high=30)
assert not self.data.ecobee.set_hold_temp.called
def test_set_hvac_mode(self):
"""Test operation mode setter."""
self.data.reset_mock()
self.thermostat.set_hvac_mode("auto")
self.data.ecobee.set_hvac_mode.assert_has_calls([mock.call(1, "auto")])
self.data.reset_mock()
self.thermostat.set_hvac_mode("heat")
self.data.ecobee.set_hvac_mode.assert_has_calls([mock.call(1, "heat")])
def test_set_fan_min_on_time(self):
"""Test fan min on time setter."""
self.data.reset_mock()
self.thermostat.set_fan_min_on_time(15)
self.data.ecobee.set_fan_min_on_time.assert_has_calls([mock.call(1, 15)])
self.data.reset_mock()
self.thermostat.set_fan_min_on_time(20)
self.data.ecobee.set_fan_min_on_time.assert_has_calls([mock.call(1, 20)])
def test_resume_program(self):
"""Test resume program."""
# False
self.data.reset_mock()
self.thermostat.resume_program(False)
self.data.ecobee.resume_program.assert_has_calls([mock.call(1, "false")])
self.data.reset_mock()
self.thermostat.resume_program(None)
self.data.ecobee.resume_program.assert_has_calls([mock.call(1, "false")])
self.data.reset_mock()
self.thermostat.resume_program(0)
self.data.ecobee.resume_program.assert_has_calls([mock.call(1, "false")])
# True
self.data.reset_mock()
self.thermostat.resume_program(True)
self.data.ecobee.resume_program.assert_has_calls([mock.call(1, "true")])
self.data.reset_mock()
self.thermostat.resume_program(1)
self.data.ecobee.resume_program.assert_has_calls([mock.call(1, "true")])
def test_hold_preference(self):
"""Test hold preference."""
assert "nextTransition" == self.thermostat.hold_preference()
for action in [
"useEndTime4hour",
"useEndTime2hour",
"nextPeriod",
"indefinite",
"askMe",
]:
self.ecobee["settings"]["holdAction"] = action
assert "nextTransition" == self.thermostat.hold_preference()
def test_set_fan_mode_on(self):
"""Test set fan mode to on."""
self.data.reset_mock()
self.thermostat.set_fan_mode("on")
self.data.ecobee.set_fan_mode.assert_has_calls(
[mock.call(1, "on", 20, 40, "nextTransition")]
)
def test_set_fan_mode_auto(self):
"""Test set fan mode to auto."""
self.data.reset_mock()
self.thermostat.set_fan_mode("auto")
self.data.ecobee.set_fan_mode.assert_has_calls(
[mock.call(1, "auto", 20, 40, "nextTransition")]
)