From 59b0a4d0605f81d3ca191d2699b1a659808d3fd7 Mon Sep 17 00:00:00 2001 From: Xiaonan Shen Date: Sun, 24 Jan 2021 03:54:58 +0800 Subject: [PATCH] Rewrite dyson air quality tests (#45466) --- homeassistant/components/dyson/air_quality.py | 23 +-- tests/components/dyson/test_air_quality.py | 192 +++++------------- 2 files changed, 55 insertions(+), 160 deletions(-) diff --git a/homeassistant/components/dyson/air_quality.py b/homeassistant/components/dyson/air_quality.py index 3a5731587f6f..d23b2b1ef883 100644 --- a/homeassistant/components/dyson/air_quality.py +++ b/homeassistant/components/dyson/air_quality.py @@ -74,37 +74,24 @@ class DysonAirSensor(DysonEntity, AirQualityEntity): @property def particulate_matter_2_5(self): """Return the particulate matter 2.5 level.""" - if self._device.environmental_state: - return int(self._device.environmental_state.particulate_matter_25) - return None + return int(self._device.environmental_state.particulate_matter_25) @property def particulate_matter_10(self): """Return the particulate matter 10 level.""" - if self._device.environmental_state: - return int(self._device.environmental_state.particulate_matter_10) - return None + return int(self._device.environmental_state.particulate_matter_10) @property def nitrogen_dioxide(self): """Return the NO2 (nitrogen dioxide) level.""" - if self._device.environmental_state: - return int(self._device.environmental_state.nitrogen_dioxide) - return None + return int(self._device.environmental_state.nitrogen_dioxide) @property def volatile_organic_compounds(self): """Return the VOC (Volatile Organic Compounds) level.""" - if self._device.environmental_state: - return int(self._device.environmental_state.volatile_organic_compounds) - return None + return int(self._device.environmental_state.volatile_organic_compounds) @property def device_state_attributes(self): """Return the device state attributes.""" - data = {} - - voc = self.volatile_organic_compounds - if voc is not None: - data[ATTR_VOC] = voc - return data + return {ATTR_VOC: self.volatile_organic_compounds} diff --git a/tests/components/dyson/test_air_quality.py b/tests/components/dyson/test_air_quality.py index 06050fb8014f..51b38303a58f 100644 --- a/tests/components/dyson/test_air_quality.py +++ b/tests/components/dyson/test_air_quality.py @@ -1,159 +1,67 @@ """Test the Dyson air quality component.""" -import json -from unittest import mock -from unittest.mock import patch from libpurecool.dyson_pure_cool import DysonPureCool from libpurecool.dyson_pure_state_v2 import DysonEnvironmentalSensorV2State -from homeassistant.components import dyson as dyson_parent from homeassistant.components.air_quality import ( + ATTR_AQI, ATTR_NO2, ATTR_PM_2_5, ATTR_PM_10, - DOMAIN as AIQ_DOMAIN, + DOMAIN as PLATFORM_DOMAIN, ) -import homeassistant.components.dyson.air_quality as dyson -from homeassistant.helpers import discovery -from homeassistant.setup import async_setup_component +from homeassistant.components.dyson.air_quality import ATTR_VOC +from homeassistant.core import HomeAssistant, callback -from .common import load_mock_device +from .common import ENTITY_NAME, async_get_purecool_device, async_update_device + +ENTITY_ID = f"{PLATFORM_DOMAIN}.{ENTITY_NAME}" + +MOCKED_VALUES = { + ATTR_PM_2_5: 10, + ATTR_PM_10: 20, + ATTR_NO2: 30, + ATTR_VOC: 40, +} + +MOCKED_UPDATED_VALUES = { + ATTR_PM_2_5: 60, + ATTR_PM_10: 50, + ATTR_NO2: 40, + ATTR_VOC: 30, +} -def _get_dyson_purecool_device(): - """Return a valid device as provided by the Dyson web services.""" - device = mock.Mock(spec=DysonPureCool) - load_mock_device(device) - device.name = "Living room" - 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" +def _async_assign_values(device: DysonPureCool, values=MOCKED_VALUES) -> None: + """Assign mocked environmental states to the device.""" + device.environmental_state.particulate_matter_25 = values[ATTR_PM_2_5] + device.environmental_state.particulate_matter_10 = values[ATTR_PM_10] + device.environmental_state.nitrogen_dioxide = values[ATTR_NO2] + device.environmental_state.volatile_organic_compounds = values[ATTR_VOC] + + +@callback +def async_get_device() -> DysonPureCool: + """Return a device of the given type.""" + device = async_get_purecool_device() + _async_assign_values(device) 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"} - ], - } - } +async def test_air_quality(hass: HomeAssistant, device: DysonPureCool) -> None: + """Test the state and attributes of the air quality entity.""" + state = hass.states.get(ENTITY_ID) + assert state.state == str(MOCKED_VALUES[ATTR_PM_2_5]) + attributes = state.attributes + for attr, value in MOCKED_VALUES.items(): + assert attributes[attr] == value + assert attributes[ATTR_AQI] == 40 - -@patch("libpurecool.dyson.DysonAccount.login", return_value=True) -@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 - - -@patch("libpurecool.dyson.DysonAccount.login", return_value=True) -@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 - - -@patch("libpurecool.dyson.DysonAccount.login", return_value=True) -@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 - - -@patch("libpurecool.dyson.DysonAccount.login", return_value=True) -@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 - - -@patch("libpurecool.dyson.DysonAccount.login", return_value=True) -@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 + _async_assign_values(device, MOCKED_UPDATED_VALUES) + await async_update_device(hass, device, DysonEnvironmentalSensorV2State) + state = hass.states.get(ENTITY_ID) + assert state.state == str(MOCKED_UPDATED_VALUES[ATTR_PM_2_5]) + attributes = state.attributes + for attr, value in MOCKED_UPDATED_VALUES.items(): + assert attributes[attr] == value + assert attributes[ATTR_AQI] == 60