fix check for already created entities remove hepa and carbon filter add AQI attribute initial commit fix check for already created entities remove hepa and carbon filter add AQI attribute add air quality component tests fix method call tests fix line lengths fix pylint issues fix docstrings revert fan related changes remove whitespace change fix fan update state test add for loop for platform initialization add requested changes to aiq platform change string concatenation to new style string formatting update air quality tests update air quality tests refactor sensor component changes fix pylint issues fix debug string in the air quality component replace failing tests for older devices fix line length fan tests remove dependencies const and move imports move back imports to methods remove whitespace from blank line
375 lines
14 KiB
Python
375 lines
14 KiB
Python
"""Test the Dyson fan component."""
|
|
import unittest
|
|
from unittest import mock
|
|
|
|
import asynctest
|
|
from libpurecool.const import (FocusMode, HeatMode,
|
|
HeatState, HeatTarget, TiltState)
|
|
from libpurecool.dyson_pure_hotcool_link import DysonPureHotCoolLink
|
|
from libpurecool.dyson_pure_state import DysonPureHotCoolState
|
|
|
|
from homeassistant.components import dyson as dyson_parent
|
|
from homeassistant.components.dyson import climate as dyson
|
|
from homeassistant.const import TEMP_CELSIUS, ATTR_TEMPERATURE
|
|
from homeassistant.setup import async_setup_component
|
|
from tests.common import get_test_home_assistant
|
|
|
|
|
|
class MockDysonState(DysonPureHotCoolState):
|
|
"""Mock Dyson state."""
|
|
|
|
def __init__(self):
|
|
"""Create new Mock Dyson State."""
|
|
pass
|
|
|
|
|
|
def _get_config():
|
|
"""Return a config dictionary."""
|
|
return {dyson_parent.DOMAIN: {
|
|
dyson_parent.CONF_USERNAME: "email",
|
|
dyson_parent.CONF_PASSWORD: "password",
|
|
dyson_parent.CONF_LANGUAGE: "GB",
|
|
dyson_parent.CONF_DEVICES: [
|
|
{
|
|
"device_id": "XX-XXXXX-XX",
|
|
"device_ip": "192.168.0.1"
|
|
},
|
|
{
|
|
"device_id": "YY-YYYYY-YY",
|
|
"device_ip": "192.168.0.2"
|
|
}
|
|
]
|
|
}}
|
|
|
|
|
|
def _get_device_with_no_state():
|
|
"""Return a device with no state."""
|
|
device = mock.Mock(spec=DysonPureHotCoolLink)
|
|
device.name = "Device_name"
|
|
device.state = None
|
|
device.environmental_state = None
|
|
return device
|
|
|
|
|
|
def _get_device_off():
|
|
"""Return a device with state off."""
|
|
device = mock.Mock(spec=DysonPureHotCoolLink)
|
|
device.name = "Device_name"
|
|
device.state = mock.Mock()
|
|
device.environmental_state = mock.Mock()
|
|
return device
|
|
|
|
|
|
def _get_device_focus():
|
|
"""Return a device with fan state of focus mode."""
|
|
device = mock.Mock(spec=DysonPureHotCoolLink)
|
|
device.name = "Device_name"
|
|
device.state.focus_mode = FocusMode.FOCUS_ON.value
|
|
return device
|
|
|
|
|
|
def _get_device_diffuse():
|
|
"""Return a device with fan state of diffuse mode."""
|
|
device = mock.Mock(spec=DysonPureHotCoolLink)
|
|
device.name = "Device_name"
|
|
device.state.focus_mode = FocusMode.FOCUS_OFF.value
|
|
return device
|
|
|
|
|
|
def _get_device_cool():
|
|
"""Return a device with state of cooling."""
|
|
device = mock.Mock(spec=DysonPureHotCoolLink)
|
|
device.name = "Device_name"
|
|
device.serial = "XX-XXXXX-XX"
|
|
device.state.tilt = TiltState.TILT_FALSE.value
|
|
device.state.focus_mode = FocusMode.FOCUS_OFF.value
|
|
device.state.heat_target = HeatTarget.celsius(12)
|
|
device.state.heat_mode = HeatMode.HEAT_OFF.value
|
|
device.state.heat_state = HeatState.HEAT_STATE_OFF.value
|
|
device.environmental_state.temperature = 288
|
|
device.environmental_state.humidity = 53
|
|
return device
|
|
|
|
|
|
def _get_device_heat_off():
|
|
"""Return a device with state of heat reached target."""
|
|
device = mock.Mock(spec=DysonPureHotCoolLink)
|
|
device.name = "Device_name"
|
|
device.state = mock.Mock()
|
|
device.state.tilt = TiltState.TILT_FALSE.value
|
|
device.state.focus_mode = FocusMode.FOCUS_ON.value
|
|
device.state.heat_target = HeatTarget.celsius(20)
|
|
device.state.heat_mode = HeatMode.HEAT_ON.value
|
|
device.state.heat_state = HeatState.HEAT_STATE_OFF.value
|
|
device.environmental_state.temperature = 293
|
|
device.environmental_state.humidity = 53
|
|
return device
|
|
|
|
|
|
def _get_device_heat_on():
|
|
"""Return a device with state of heating."""
|
|
device = mock.Mock(spec=DysonPureHotCoolLink)
|
|
device.name = "Device_name"
|
|
device.serial = "YY-YYYYY-YY"
|
|
device.state = mock.Mock()
|
|
device.state.tilt = TiltState.TILT_FALSE.value
|
|
device.state.focus_mode = FocusMode.FOCUS_ON.value
|
|
device.state.heat_target = HeatTarget.celsius(23)
|
|
device.state.heat_mode = HeatMode.HEAT_ON.value
|
|
device.state.heat_state = HeatState.HEAT_STATE_ON.value
|
|
device.environmental_state.temperature = 289
|
|
device.environmental_state.humidity = 53
|
|
return device
|
|
|
|
|
|
class DysonTest(unittest.TestCase):
|
|
"""Dyson Climate component test class."""
|
|
|
|
def setUp(self): # pylint: disable=invalid-name
|
|
"""Set up things to be run when tests are started."""
|
|
self.hass = get_test_home_assistant()
|
|
|
|
def tearDown(self): # pylint: disable=invalid-name
|
|
"""Stop everything that was started."""
|
|
self.hass.stop()
|
|
|
|
def test_setup_component_without_devices(self):
|
|
"""Test setup component with no devices."""
|
|
self.hass.data[dyson.DYSON_DEVICES] = []
|
|
add_devices = mock.MagicMock()
|
|
dyson.setup_platform(self.hass, None, add_devices)
|
|
add_devices.assert_not_called()
|
|
|
|
def test_setup_component_with_devices(self):
|
|
"""Test setup component with valid devices."""
|
|
devices = [
|
|
_get_device_with_no_state(),
|
|
_get_device_off(),
|
|
_get_device_heat_on()
|
|
]
|
|
self.hass.data[dyson.DYSON_DEVICES] = devices
|
|
add_devices = mock.MagicMock()
|
|
dyson.setup_platform(self.hass, None, add_devices, discovery_info={})
|
|
assert add_devices.called
|
|
|
|
def test_setup_component_with_invalid_devices(self):
|
|
"""Test setup component with invalid devices."""
|
|
devices = [
|
|
None,
|
|
"foo_bar"
|
|
]
|
|
self.hass.data[dyson.DYSON_DEVICES] = devices
|
|
add_devices = mock.MagicMock()
|
|
dyson.setup_platform(self.hass, None, add_devices, discovery_info={})
|
|
add_devices.assert_called_with([])
|
|
|
|
def test_setup_component(self):
|
|
"""Test setup component with devices."""
|
|
device_fan = _get_device_heat_on()
|
|
device_non_fan = _get_device_off()
|
|
|
|
def _add_device(devices):
|
|
assert len(devices) == 1
|
|
assert devices[0].name == "Device_name"
|
|
|
|
self.hass.data[dyson.DYSON_DEVICES] = [device_fan, device_non_fan]
|
|
dyson.setup_platform(self.hass, None, _add_device)
|
|
|
|
def test_dyson_set_temperature(self):
|
|
"""Test set climate temperature."""
|
|
device = _get_device_heat_on()
|
|
device.temp_unit = TEMP_CELSIUS
|
|
entity = dyson.DysonPureHotCoolLinkDevice(device)
|
|
assert not entity.should_poll
|
|
|
|
# Without target temp.
|
|
kwargs = {}
|
|
entity.set_temperature(**kwargs)
|
|
set_config = device.set_configuration
|
|
set_config.assert_not_called()
|
|
|
|
kwargs = {ATTR_TEMPERATURE: 23}
|
|
entity.set_temperature(**kwargs)
|
|
set_config = device.set_configuration
|
|
set_config.assert_called_with(
|
|
heat_mode=HeatMode.HEAT_ON,
|
|
heat_target=HeatTarget.celsius(23))
|
|
|
|
# Should clip the target temperature between 1 and 37 inclusive.
|
|
kwargs = {ATTR_TEMPERATURE: 50}
|
|
entity.set_temperature(**kwargs)
|
|
set_config = device.set_configuration
|
|
set_config.assert_called_with(
|
|
heat_mode=HeatMode.HEAT_ON,
|
|
heat_target=HeatTarget.celsius(37))
|
|
|
|
kwargs = {ATTR_TEMPERATURE: -5}
|
|
entity.set_temperature(**kwargs)
|
|
set_config = device.set_configuration
|
|
set_config.assert_called_with(
|
|
heat_mode=HeatMode.HEAT_ON,
|
|
heat_target=HeatTarget.celsius(1))
|
|
|
|
def test_dyson_set_temperature_when_cooling_mode(self):
|
|
"""Test set climate temperature when heating is off."""
|
|
device = _get_device_cool()
|
|
device.temp_unit = TEMP_CELSIUS
|
|
entity = dyson.DysonPureHotCoolLinkDevice(device)
|
|
entity.schedule_update_ha_state = mock.Mock()
|
|
|
|
kwargs = {ATTR_TEMPERATURE: 23}
|
|
entity.set_temperature(**kwargs)
|
|
set_config = device.set_configuration
|
|
set_config.assert_called_with(
|
|
heat_mode=HeatMode.HEAT_ON,
|
|
heat_target=HeatTarget.celsius(23))
|
|
|
|
def test_dyson_set_fan_mode(self):
|
|
"""Test set fan mode."""
|
|
device = _get_device_heat_on()
|
|
entity = dyson.DysonPureHotCoolLinkDevice(device)
|
|
assert not entity.should_poll
|
|
|
|
entity.set_fan_mode(dyson.STATE_FOCUS)
|
|
set_config = device.set_configuration
|
|
set_config.assert_called_with(focus_mode=FocusMode.FOCUS_ON)
|
|
|
|
entity.set_fan_mode(dyson.STATE_DIFFUSE)
|
|
set_config = device.set_configuration
|
|
set_config.assert_called_with(focus_mode=FocusMode.FOCUS_OFF)
|
|
|
|
def test_dyson_fan_list(self):
|
|
"""Test get fan list."""
|
|
device = _get_device_heat_on()
|
|
entity = dyson.DysonPureHotCoolLinkDevice(device)
|
|
assert len(entity.fan_list) == 2
|
|
assert dyson.STATE_FOCUS in entity.fan_list
|
|
assert dyson.STATE_DIFFUSE in entity.fan_list
|
|
|
|
def test_dyson_fan_mode_focus(self):
|
|
"""Test fan focus mode."""
|
|
device = _get_device_focus()
|
|
entity = dyson.DysonPureHotCoolLinkDevice(device)
|
|
assert entity.current_fan_mode == dyson.STATE_FOCUS
|
|
|
|
def test_dyson_fan_mode_diffuse(self):
|
|
"""Test fan diffuse mode."""
|
|
device = _get_device_diffuse()
|
|
entity = dyson.DysonPureHotCoolLinkDevice(device)
|
|
assert entity.current_fan_mode == dyson.STATE_DIFFUSE
|
|
|
|
def test_dyson_set_operation_mode(self):
|
|
"""Test set operation mode."""
|
|
device = _get_device_heat_on()
|
|
entity = dyson.DysonPureHotCoolLinkDevice(device)
|
|
assert not entity.should_poll
|
|
|
|
entity.set_operation_mode(dyson.STATE_HEAT)
|
|
set_config = device.set_configuration
|
|
set_config.assert_called_with(heat_mode=HeatMode.HEAT_ON)
|
|
|
|
entity.set_operation_mode(dyson.STATE_COOL)
|
|
set_config = device.set_configuration
|
|
set_config.assert_called_with(heat_mode=HeatMode.HEAT_OFF)
|
|
|
|
def test_dyson_operation_list(self):
|
|
"""Test get operation list."""
|
|
device = _get_device_heat_on()
|
|
entity = dyson.DysonPureHotCoolLinkDevice(device)
|
|
assert len(entity.operation_list) == 2
|
|
assert dyson.STATE_HEAT in entity.operation_list
|
|
assert dyson.STATE_COOL in entity.operation_list
|
|
|
|
def test_dyson_heat_off(self):
|
|
"""Test turn off heat."""
|
|
device = _get_device_heat_off()
|
|
entity = dyson.DysonPureHotCoolLinkDevice(device)
|
|
entity.set_operation_mode(dyson.STATE_COOL)
|
|
set_config = device.set_configuration
|
|
set_config.assert_called_with(heat_mode=HeatMode.HEAT_OFF)
|
|
|
|
def test_dyson_heat_on(self):
|
|
"""Test turn on heat."""
|
|
device = _get_device_heat_on()
|
|
entity = dyson.DysonPureHotCoolLinkDevice(device)
|
|
entity.set_operation_mode(dyson.STATE_HEAT)
|
|
set_config = device.set_configuration
|
|
set_config.assert_called_with(heat_mode=HeatMode.HEAT_ON)
|
|
|
|
def test_dyson_heat_value_on(self):
|
|
"""Test get heat value on."""
|
|
device = _get_device_heat_on()
|
|
entity = dyson.DysonPureHotCoolLinkDevice(device)
|
|
assert entity.current_operation == dyson.STATE_HEAT
|
|
|
|
def test_dyson_heat_value_off(self):
|
|
"""Test get heat value off."""
|
|
device = _get_device_cool()
|
|
entity = dyson.DysonPureHotCoolLinkDevice(device)
|
|
assert entity.current_operation == dyson.STATE_COOL
|
|
|
|
def test_dyson_heat_value_idle(self):
|
|
"""Test get heat value idle."""
|
|
device = _get_device_heat_off()
|
|
entity = dyson.DysonPureHotCoolLinkDevice(device)
|
|
assert entity.current_operation == dyson.STATE_IDLE
|
|
|
|
def test_on_message(self):
|
|
"""Test when message is received."""
|
|
device = _get_device_heat_on()
|
|
entity = dyson.DysonPureHotCoolLinkDevice(device)
|
|
entity.schedule_update_ha_state = mock.Mock()
|
|
entity.on_message(MockDysonState())
|
|
entity.schedule_update_ha_state.assert_called_with()
|
|
|
|
def test_general_properties(self):
|
|
"""Test properties of entity."""
|
|
device = _get_device_with_no_state()
|
|
entity = dyson.DysonPureHotCoolLinkDevice(device)
|
|
assert entity.should_poll is False
|
|
assert entity.supported_features == dyson.SUPPORT_FLAGS
|
|
assert entity.temperature_unit == TEMP_CELSIUS
|
|
|
|
def test_property_current_humidity(self):
|
|
"""Test properties of current humidity."""
|
|
device = _get_device_heat_on()
|
|
entity = dyson.DysonPureHotCoolLinkDevice(device)
|
|
assert entity.current_humidity == 53
|
|
|
|
def test_property_current_humidity_with_invalid_env_state(self):
|
|
"""Test properties of current humidity with invalid env state."""
|
|
device = _get_device_off()
|
|
device.environmental_state.humidity = 0
|
|
entity = dyson.DysonPureHotCoolLinkDevice(device)
|
|
assert entity.current_humidity is None
|
|
|
|
def test_property_current_humidity_without_env_state(self):
|
|
"""Test properties of current humidity without env state."""
|
|
device = _get_device_with_no_state()
|
|
entity = dyson.DysonPureHotCoolLinkDevice(device)
|
|
assert entity.current_humidity is None
|
|
|
|
def test_property_current_temperature(self):
|
|
"""Test properties of current temperature."""
|
|
device = _get_device_heat_on()
|
|
entity = dyson.DysonPureHotCoolLinkDevice(device)
|
|
# Result should be in celsius, hence then subtraction of 273.
|
|
assert entity.current_temperature == 289 - 273
|
|
|
|
def test_property_target_temperature(self):
|
|
"""Test properties of target temperature."""
|
|
device = _get_device_heat_on()
|
|
entity = dyson.DysonPureHotCoolLinkDevice(device)
|
|
assert entity.target_temperature == 23
|
|
|
|
|
|
@asynctest.patch('libpurecool.dyson.DysonAccount.devices',
|
|
return_value=[_get_device_heat_on(), _get_device_cool()])
|
|
@asynctest.patch('libpurecool.dyson.DysonAccount.login', return_value=True)
|
|
async def test_setup_component_with_parent_discovery(mocked_login,
|
|
mocked_devices, hass):
|
|
"""Test setup_component using discovery."""
|
|
await async_setup_component(hass, dyson_parent.DOMAIN, _get_config())
|
|
await hass.async_block_till_done()
|
|
|
|
assert len(hass.data[dyson.DYSON_DEVICES]) == 2
|