149 lines
5.6 KiB
Python
149 lines
5.6 KiB
Python
"""Test the Dyson air quality component."""
|
|
import json
|
|
from unittest import mock
|
|
|
|
import asynctest
|
|
from libpurecool.dyson_pure_cool import DysonPureCool
|
|
from libpurecool.dyson_pure_state_v2 import DysonEnvironmentalSensorV2State
|
|
|
|
import homeassistant.components.dyson.air_quality as dyson
|
|
from homeassistant.components import dyson as dyson_parent
|
|
from homeassistant.components.air_quality import DOMAIN as AIQ_DOMAIN, \
|
|
ATTR_PM_2_5, ATTR_PM_10, ATTR_NO2
|
|
from homeassistant.helpers import discovery
|
|
from homeassistant.setup import async_setup_component
|
|
|
|
|
|
def _get_dyson_purecool_device():
|
|
"""Return a valid device as provided by the Dyson web services."""
|
|
device = mock.Mock(spec=DysonPureCool)
|
|
device.serial = 'XX-XXXXX-XX'
|
|
device.name = 'Living room'
|
|
device.connect = mock.Mock(return_value=True)
|
|
device.auto_connect = mock.Mock(return_value=True)
|
|
device.environmental_state.particulate_matter_25 = '0014'
|
|
device.environmental_state.particulate_matter_10 = '0025'
|
|
device.environmental_state.nitrogen_dioxide = '0042'
|
|
device.environmental_state.volatile_organic_compounds = '0035'
|
|
return device
|
|
|
|
|
|
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'
|
|
}
|
|
]
|
|
}}
|
|
|
|
|
|
@asynctest.patch('libpurecool.dyson.DysonAccount.login', return_value=True)
|
|
@asynctest.patch('libpurecool.dyson.DysonAccount.devices',
|
|
return_value=[_get_dyson_purecool_device()])
|
|
async def test_purecool_aiq_attributes(devices, login, hass):
|
|
"""Test state attributes."""
|
|
await async_setup_component(hass, dyson_parent.DOMAIN, _get_config())
|
|
await hass.async_block_till_done()
|
|
fan_state = hass.states.get("air_quality.living_room")
|
|
attributes = fan_state.attributes
|
|
|
|
assert fan_state.state == '14'
|
|
assert attributes[ATTR_PM_2_5] == 14
|
|
assert attributes[ATTR_PM_10] == 25
|
|
assert attributes[ATTR_NO2] == 42
|
|
assert attributes[dyson.ATTR_VOC] == 35
|
|
|
|
|
|
@asynctest.patch('libpurecool.dyson.DysonAccount.login', return_value=True)
|
|
@asynctest.patch('libpurecool.dyson.DysonAccount.devices',
|
|
return_value=[_get_dyson_purecool_device()])
|
|
async def test_purecool_aiq_update_state(devices, login, hass):
|
|
"""Test state update."""
|
|
device = devices.return_value[0]
|
|
await async_setup_component(hass, dyson_parent.DOMAIN, _get_config())
|
|
await hass.async_block_till_done()
|
|
event = {
|
|
"msg": "ENVIRONMENTAL-CURRENT-SENSOR-DATA",
|
|
"time": "2019-03-29T10:00:01.000Z",
|
|
"data": {
|
|
"pm10": "0080",
|
|
"p10r": "0151",
|
|
"hact": "0040",
|
|
"va10": "0055",
|
|
"p25r": "0161",
|
|
"noxl": "0069",
|
|
"pm25": "0035",
|
|
"sltm": "OFF",
|
|
"tact": "2960"
|
|
}
|
|
}
|
|
device.environmental_state = \
|
|
DysonEnvironmentalSensorV2State(json.dumps(event))
|
|
|
|
for call in device.add_message_listener.call_args_list:
|
|
callback = call[0][0]
|
|
if type(callback.__self__) == dyson.DysonAirSensor:
|
|
callback(device.environmental_state)
|
|
|
|
await hass.async_block_till_done()
|
|
fan_state = hass.states.get("air_quality.living_room")
|
|
attributes = fan_state.attributes
|
|
|
|
assert fan_state.state == '35'
|
|
assert attributes[ATTR_PM_2_5] == 35
|
|
assert attributes[ATTR_PM_10] == 80
|
|
assert attributes[ATTR_NO2] == 69
|
|
assert attributes[dyson.ATTR_VOC] == 55
|
|
|
|
|
|
@asynctest.patch('libpurecool.dyson.DysonAccount.login', return_value=True)
|
|
@asynctest.patch('libpurecool.dyson.DysonAccount.devices',
|
|
return_value=[_get_dyson_purecool_device()])
|
|
async def test_purecool_component_setup_only_once(devices, login, hass):
|
|
"""Test if entities are created only once."""
|
|
config = _get_config()
|
|
await async_setup_component(hass, dyson_parent.DOMAIN, config)
|
|
await hass.async_block_till_done()
|
|
discovery.load_platform(hass, AIQ_DOMAIN,
|
|
dyson_parent.DOMAIN, {}, config)
|
|
await hass.async_block_till_done()
|
|
|
|
assert len(hass.data[dyson.DYSON_AIQ_DEVICES]) == 1
|
|
|
|
|
|
@asynctest.patch('libpurecool.dyson.DysonAccount.login', return_value=True)
|
|
@asynctest.patch('libpurecool.dyson.DysonAccount.devices',
|
|
return_value=[_get_dyson_purecool_device()])
|
|
async def test_purecool_aiq_without_discovery(devices, login, hass):
|
|
"""Test if component correctly returns if discovery not set."""
|
|
await async_setup_component(hass, dyson_parent.DOMAIN, _get_config())
|
|
await hass.async_block_till_done()
|
|
add_entities_mock = mock.MagicMock()
|
|
|
|
dyson.setup_platform(hass, None, add_entities_mock, None)
|
|
|
|
assert add_entities_mock.call_count == 0
|
|
|
|
|
|
@asynctest.patch('libpurecool.dyson.DysonAccount.login', return_value=True)
|
|
@asynctest.patch('libpurecool.dyson.DysonAccount.devices',
|
|
return_value=[_get_dyson_purecool_device()])
|
|
async def test_purecool_aiq_empty_environment_state(devices, login, hass):
|
|
"""Test device with empty environmental state."""
|
|
await async_setup_component(hass, dyson_parent.DOMAIN, _get_config())
|
|
await hass.async_block_till_done()
|
|
device = hass.data[dyson.DYSON_AIQ_DEVICES][0]
|
|
device._device.environmental_state = None
|
|
|
|
assert device.state is None
|
|
assert device.particulate_matter_2_5 is None
|
|
assert device.particulate_matter_10 is None
|
|
assert device.nitrogen_dioxide is None
|
|
assert device.volatile_organic_compounds is None
|