From 4073f63256a3c67e05fd8fa142c83a6a5649a787 Mon Sep 17 00:00:00 2001 From: kennedyshead Date: Tue, 30 Oct 2018 21:29:11 +0100 Subject: [PATCH] Async version of melissa (#17721) * rebase upstream * Fixed tests * Fixing lint --- homeassistant/components/climate/melissa.py | 43 +- homeassistant/components/melissa.py | 16 +- homeassistant/components/sensor/melissa.py | 20 +- requirements_all.txt | 2 +- tests/components/climate/test_melissa.py | 535 +++++++++++++------- tests/components/sensor/test_melissa.py | 149 +++--- tests/components/test_melissa.py | 33 +- 7 files changed, 481 insertions(+), 317 deletions(-) diff --git a/homeassistant/components/climate/melissa.py b/homeassistant/components/climate/melissa.py index c8e67c14835..bfb18fa0a4c 100644 --- a/homeassistant/components/climate/melissa.py +++ b/homeassistant/components/climate/melissa.py @@ -34,10 +34,11 @@ FAN_MODES = [ ] -def setup_platform(hass, config, add_entities, discovery_info=None): +async def async_setup_platform( + hass, config, async_add_entities, discovery_info=None): """Iterate through and add all Melissa devices.""" api = hass.data[DATA_MELISSA] - devices = api.fetch_devices().values() + devices = (await api.async_fetch_devices()).values() all_devices = [] @@ -46,7 +47,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None): all_devices.append(MelissaClimate( api, device['serial_number'], device)) - add_entities(all_devices) + async_add_entities(all_devices) class MelissaClimate(ClimateDevice): @@ -142,48 +143,48 @@ class MelissaClimate(ClimateDevice): """Return the list of supported features.""" return SUPPORT_FLAGS - def set_temperature(self, **kwargs): + async def async_set_temperature(self, **kwargs): """Set new target temperature.""" temp = kwargs.get(ATTR_TEMPERATURE) - self.send({self._api.TEMP: temp}) + await self.async_send({self._api.TEMP: temp}) - def set_fan_mode(self, fan_mode): + async def async_set_fan_mode(self, fan_mode): """Set fan mode.""" melissa_fan_mode = self.hass_fan_to_melissa(fan_mode) - self.send({self._api.FAN: melissa_fan_mode}) + await self.async_send({self._api.FAN: melissa_fan_mode}) - def set_operation_mode(self, operation_mode): + async def async_set_operation_mode(self, operation_mode): """Set operation mode.""" mode = self.hass_mode_to_melissa(operation_mode) - self.send({self._api.MODE: mode}) + await self.async_send({self._api.MODE: mode}) - def turn_on(self): + async def async_turn_on(self): """Turn on device.""" - self.send({self._api.STATE: self._api.STATE_ON}) + await self.async_send({self._api.STATE: self._api.STATE_ON}) - def turn_off(self): + async def async_turn_off(self): """Turn off device.""" - self.send({self._api.STATE: self._api.STATE_OFF}) + await self.async_send({self._api.STATE: self._api.STATE_OFF}) - def send(self, value): + async def async_send(self, value): """Send action to service.""" try: old_value = self._cur_settings.copy() self._cur_settings.update(value) except AttributeError: old_value = None - if not self._api.send(self._serial_number, self._cur_settings): + if not await self._api.async_send( + self._serial_number, self._cur_settings): self._cur_settings = old_value - return False - return True - def update(self): + async def async_update(self): """Get latest data from Melissa.""" try: - self._data = self._api.status(cached=True)[self._serial_number] - self._cur_settings = self._api.cur_settings( + self._data = (await self._api.async_status(cached=True))[ + self._serial_number] + self._cur_settings = (await self._api.async_cur_settings( self._serial_number - )['controller']['_relation']['command_log'] + ))['controller']['_relation']['command_log'] except KeyError: _LOGGER.warning( 'Unable to update entity %s', self.entity_id) diff --git a/homeassistant/components/melissa.py b/homeassistant/components/melissa.py index 49e7d62f5cb..da2ec49d11f 100644 --- a/homeassistant/components/melissa.py +++ b/homeassistant/components/melissa.py @@ -10,9 +10,9 @@ import voluptuous as vol from homeassistant.const import CONF_USERNAME, CONF_PASSWORD from homeassistant.helpers import config_validation as cv -from homeassistant.helpers.discovery import load_platform +from homeassistant.helpers.discovery import async_load_platform -REQUIREMENTS = ["py-melissa-climate==1.0.6"] +REQUIREMENTS = ["py-melissa-climate==2.0.0"] _LOGGER = logging.getLogger(__name__) @@ -28,17 +28,19 @@ CONFIG_SCHEMA = vol.Schema({ }, extra=vol.ALLOW_EXTRA) -def setup(hass, config): +async def async_setup(hass, config): """Set up the Melissa Climate component.""" import melissa conf = config[DOMAIN] username = conf.get(CONF_USERNAME) password = conf.get(CONF_PASSWORD) - - api = melissa.Melissa(username=username, password=password) + api = melissa.AsyncMelissa(username=username, password=password) + await api.async_connect() hass.data[DATA_MELISSA] = api - load_platform(hass, 'sensor', DOMAIN, {}, config) - load_platform(hass, 'climate', DOMAIN, {}, config) + hass.async_create_task( + async_load_platform(hass, 'sensor', DOMAIN, {}, config)) + hass.async_create_task( + async_load_platform(hass, 'climate', DOMAIN, {}, config)) return True diff --git a/homeassistant/components/sensor/melissa.py b/homeassistant/components/sensor/melissa.py index df4800cbbd0..c11c5c76740 100644 --- a/homeassistant/components/sensor/melissa.py +++ b/homeassistant/components/sensor/melissa.py @@ -15,17 +15,19 @@ DEPENDENCIES = ['melissa'] _LOGGER = logging.getLogger(__name__) -def setup_platform(hass, config, add_entities, discovery_info=None): +async def async_setup_platform( + hass, config, async_add_entities, discovery_info=None): """Set up the melissa sensor platform.""" sensors = [] api = hass.data[DATA_MELISSA] - devices = api.fetch_devices().values() + + devices = (await api.async_fetch_devices()).values() for device in devices: if device['type'] == 'melissa': sensors.append(MelissaTemperatureSensor(device, api)) sensors.append(MelissaHumiditySensor(device, api)) - add_entities(sensors) + async_add_entities(sensors) class MelissaSensor(Entity): @@ -54,9 +56,9 @@ class MelissaSensor(Entity): """Return the state of the sensor.""" return self._state - def update(self): + async def async_update(self): """Fetch status from melissa.""" - self._data = self._api.status(cached=True) + self._data = await self._api.async_status(cached=True) class MelissaTemperatureSensor(MelissaSensor): @@ -70,9 +72,9 @@ class MelissaTemperatureSensor(MelissaSensor): """Return the unit of measurement.""" return self._unit - def update(self): + async def async_update(self): """Fetch new state data for the sensor.""" - super().update() + await super().async_update() try: self._state = self._data[self._serial]['temp'] except KeyError: @@ -90,9 +92,9 @@ class MelissaHumiditySensor(MelissaSensor): """Return the unit of measurement.""" return self._unit - def update(self): + async def async_update(self): """Fetch new state data for the sensor.""" - super().update() + await super().async_update() try: self._state = self._data[self._serial]['humidity'] except KeyError: diff --git a/requirements_all.txt b/requirements_all.txt index 77d58cac617..e99e1a34665 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -768,7 +768,7 @@ py-canary==0.5.0 py-cpuinfo==4.0.0 # homeassistant.components.melissa -py-melissa-climate==1.0.6 +py-melissa-climate==2.0.0 # homeassistant.components.camera.synology py-synology==0.2.0 diff --git a/tests/components/climate/test_melissa.py b/tests/components/climate/test_melissa.py index 538e642cd82..2c135bfc09d 100644 --- a/tests/components/climate/test_melissa.py +++ b/tests/components/climate/test_melissa.py @@ -1,9 +1,8 @@ """Test for Melissa climate component.""" -import unittest from unittest.mock import Mock, patch import json -from asynctest import mock +from homeassistant.components.climate.melissa import MelissaClimate from homeassistant.components.climate import ( melissa, SUPPORT_TARGET_TEMPERATURE, SUPPORT_OPERATION_MODE, @@ -15,244 +14,392 @@ from homeassistant.components.melissa import DATA_MELISSA from homeassistant.const import ( TEMP_CELSIUS, STATE_ON, ATTR_TEMPERATURE, STATE_OFF, STATE_IDLE ) -from tests.common import get_test_home_assistant, load_fixture +from tests.common import load_fixture, mock_coro_func + +_SERIAL = "12345678" -class TestMelissa(unittest.TestCase): - """Tests for Melissa climate.""" +def melissa_mock(): + """Use this to mock the melissa api.""" + api = Mock() + api.async_fetch_devices = mock_coro_func( + return_value=json.loads(load_fixture('melissa_fetch_devices.json'))) + api.async_status = mock_coro_func(return_value=json.loads(load_fixture( + 'melissa_status.json'))) + api.async_cur_settings = mock_coro_func( + return_value=json.loads(load_fixture('melissa_cur_settings.json'))) - def setUp(self): # pylint: disable=invalid-name - """Set up test variables.""" - self.hass = get_test_home_assistant() - self._serial = '12345678' + api.async_send = mock_coro_func(return_value=True) - self.api = Mock() - self.api.fetch_devices.return_value = json.loads(load_fixture( - 'melissa_fetch_devices.json' - )) - self.api.cur_settings.return_value = json.loads(load_fixture( - 'melissa_cur_settings.json' - )) - self.api.status.return_value = json.loads(load_fixture( - 'melissa_status.json' - )) - self.api.STATE_OFF = 0 - self.api.STATE_ON = 1 - self.api.STATE_IDLE = 2 + api.STATE_OFF = 0 + api.STATE_ON = 1 + api.STATE_IDLE = 2 - self.api.MODE_AUTO = 0 - self.api.MODE_FAN = 1 - self.api.MODE_HEAT = 2 - self.api.MODE_COOL = 3 - self.api.MODE_DRY = 4 + api.MODE_AUTO = 0 + api.MODE_FAN = 1 + api.MODE_HEAT = 2 + api.MODE_COOL = 3 + api.MODE_DRY = 4 - self.api.FAN_AUTO = 0 - self.api.FAN_LOW = 1 - self.api.FAN_MEDIUM = 2 - self.api.FAN_HIGH = 3 + api.FAN_AUTO = 0 + api.FAN_LOW = 1 + api.FAN_MEDIUM = 2 + api.FAN_HIGH = 3 - self.api.STATE = 'state' - self.api.MODE = 'mode' - self.api.FAN = 'fan' - self.api.TEMP = 'temp' + api.STATE = 'state' + api.MODE = 'mode' + api.FAN = 'fan' + api.TEMP = 'temp' + return api - device = self.api.fetch_devices()[self._serial] - self.thermostat = melissa.MelissaClimate( - self.api, device['serial_number'], device) - self.thermostat.update() - def tearDown(self): # pylint: disable=invalid-name - """Teardown this test class. Stop hass.""" - self.hass.stop() - - @patch("homeassistant.components.climate.melissa.MelissaClimate") - def test_setup_platform(self, mocked_thermostat): - """Test setup_platform.""" - device = self.api.fetch_devices()[self._serial] - thermostat = mocked_thermostat(self.api, device['serial_number'], +async def test_setup_platform(hass): + """Test setup_platform.""" + with patch("homeassistant.components.climate.melissa.MelissaClimate" + ) as mocked_thermostat: + api = melissa_mock() + device = (await api.async_fetch_devices())[_SERIAL] + thermostat = mocked_thermostat(api, device['serial_number'], device) thermostats = [thermostat] - self.hass.data[DATA_MELISSA] = self.api + hass.data[DATA_MELISSA] = api config = {} add_entities = Mock() discovery_info = {} - melissa.setup_platform(self.hass, config, add_entities, discovery_info) + await melissa.async_setup_platform( + hass, config, add_entities, discovery_info) add_entities.assert_called_once_with(thermostats) - def test_get_name(self): - """Test name property.""" - assert "Melissa 12345678" == self.thermostat.name - def test_is_on(self): - """Test name property.""" - assert self.thermostat.is_on - self.thermostat._cur_settings = None - assert not self.thermostat.is_on +async def test_get_name(hass): + """Test name property.""" + with patch('homeassistant.components.melissa'): + api = melissa_mock() + device = (await api.async_fetch_devices())[_SERIAL] + thermostat = MelissaClimate(api, _SERIAL, device) + assert "Melissa 12345678" == thermostat.name - def test_current_fan_mode(self): - """Test current_fan_mode property.""" - self.thermostat.update() - assert SPEED_LOW == self.thermostat.current_fan_mode - self.thermostat._cur_settings = None - assert self.thermostat.current_fan_mode is None - def test_current_temperature(self): - """Test current temperature.""" - assert 27.4 == self.thermostat.current_temperature +async def test_is_on(hass): + """Test name property.""" + with patch('homeassistant.components.melissa'): + api = melissa_mock() + device = (await api.async_fetch_devices())[_SERIAL] + thermostat = MelissaClimate(api, _SERIAL, device) + await thermostat.async_update() + assert thermostat.is_on - def test_current_temperature_no_data(self): - """Test current temperature without data.""" - self.thermostat._data = None - assert self.thermostat.current_temperature is None + thermostat._cur_settings = None + assert not thermostat.is_on - def test_target_temperature_step(self): - """Test current target_temperature_step.""" - assert 1 == self.thermostat.target_temperature_step - def test_current_operation(self): - """Test current operation.""" - self.thermostat.update() - assert self.thermostat.current_operation == STATE_HEAT - self.thermostat._cur_settings = None - assert self.thermostat.current_operation is None +async def test_current_fan_mode(hass): + """Test current_fan_mode property.""" + with patch('homeassistant.components.melissa'): + api = melissa_mock() + device = (await api.async_fetch_devices())[_SERIAL] + thermostat = MelissaClimate(api, _SERIAL, device) + await thermostat.async_update() + assert SPEED_LOW == thermostat.current_fan_mode - def test_operation_list(self): - """Test the operation list.""" + thermostat._cur_settings = None + assert thermostat.current_fan_mode is None + + +async def test_current_temperature(hass): + """Test current temperature.""" + with patch('homeassistant.components.melissa'): + api = melissa_mock() + device = (await api.async_fetch_devices())[_SERIAL] + thermostat = MelissaClimate(api, _SERIAL, device) + assert 27.4 == thermostat.current_temperature + + +async def test_current_temperature_no_data(hass): + """Test current temperature without data.""" + with patch('homeassistant.components.melissa'): + api = melissa_mock() + device = (await api.async_fetch_devices())[_SERIAL] + thermostat = MelissaClimate(api, _SERIAL, device) + thermostat._data = None + assert thermostat.current_temperature is None + + +async def test_target_temperature_step(hass): + """Test current target_temperature_step.""" + with patch('homeassistant.components.melissa'): + api = melissa_mock() + device = (await api.async_fetch_devices())[_SERIAL] + thermostat = MelissaClimate(api, _SERIAL, device) + assert 1 == thermostat.target_temperature_step + + +async def test_current_operation(hass): + """Test current operation.""" + with patch('homeassistant.components.melissa'): + api = melissa_mock() + device = (await api.async_fetch_devices())[_SERIAL] + thermostat = MelissaClimate(api, _SERIAL, device) + await thermostat.async_update() + assert thermostat.current_operation == STATE_HEAT + + thermostat._cur_settings = None + assert thermostat.current_operation is None + + +async def test_operation_list(hass): + """Test the operation list.""" + with patch('homeassistant.components.melissa'): + api = melissa_mock() + device = (await api.async_fetch_devices())[_SERIAL] + thermostat = MelissaClimate(api, _SERIAL, device) assert [STATE_COOL, STATE_DRY, STATE_FAN_ONLY, STATE_HEAT] == \ - self.thermostat.operation_list + thermostat.operation_list - def test_fan_list(self): - """Test the fan list.""" + +async def test_fan_list(hass): + """Test the fan list.""" + with patch('homeassistant.components.melissa'): + api = melissa_mock() + device = (await api.async_fetch_devices())[_SERIAL] + thermostat = MelissaClimate(api, _SERIAL, device) assert [STATE_AUTO, SPEED_HIGH, SPEED_LOW, SPEED_MEDIUM] == \ - self.thermostat.fan_list + thermostat.fan_list - def test_target_temperature(self): - """Test target temperature.""" - assert 16 == self.thermostat.target_temperature - self.thermostat._cur_settings = None - assert self.thermostat.target_temperature is None - def test_state(self): - """Test state.""" - assert STATE_ON == self.thermostat.state - self.thermostat._cur_settings = None - assert self.thermostat.state is None +async def test_target_temperature(hass): + """Test target temperature.""" + with patch('homeassistant.components.melissa'): + api = melissa_mock() + device = (await api.async_fetch_devices())[_SERIAL] + thermostat = MelissaClimate(api, _SERIAL, device) + await thermostat.async_update() + assert 16 == thermostat.target_temperature - def test_temperature_unit(self): - """Test temperature unit.""" - assert TEMP_CELSIUS == self.thermostat.temperature_unit + thermostat._cur_settings = None + assert thermostat.target_temperature is None - def test_min_temp(self): - """Test min temp.""" - assert 16 == self.thermostat.min_temp - def test_max_temp(self): - """Test max temp.""" - assert 30 == self.thermostat.max_temp +async def test_state(hass): + """Test state.""" + with patch('homeassistant.components.melissa'): + api = melissa_mock() + device = (await api.async_fetch_devices())[_SERIAL] + thermostat = MelissaClimate(api, _SERIAL, device) + await thermostat.async_update() + assert STATE_ON == thermostat.state - def test_supported_features(self): - """Test supported_features property.""" + thermostat._cur_settings = None + assert thermostat.state is None + + +async def test_temperature_unit(hass): + """Test temperature unit.""" + with patch('homeassistant.components.melissa'): + api = melissa_mock() + device = (await api.async_fetch_devices())[_SERIAL] + thermostat = MelissaClimate(api, _SERIAL, device) + assert TEMP_CELSIUS == thermostat.temperature_unit + + +async def test_min_temp(hass): + """Test min temp.""" + with patch('homeassistant.components.melissa'): + api = melissa_mock() + device = (await api.async_fetch_devices())[_SERIAL] + thermostat = MelissaClimate(api, _SERIAL, device) + assert 16 == thermostat.min_temp + + +async def test_max_temp(hass): + """Test max temp.""" + with patch('homeassistant.components.melissa'): + api = melissa_mock() + device = (await api.async_fetch_devices())[_SERIAL] + thermostat = MelissaClimate(api, _SERIAL, device) + assert 30 == thermostat.max_temp + + +async def test_supported_features(hass): + """Test supported_features property.""" + with patch('homeassistant.components.melissa'): + api = melissa_mock() + device = (await api.async_fetch_devices())[_SERIAL] + thermostat = MelissaClimate(api, _SERIAL, device) features = (SUPPORT_TARGET_TEMPERATURE | SUPPORT_OPERATION_MODE | SUPPORT_ON_OFF | SUPPORT_FAN_MODE) - assert features == self.thermostat.supported_features + assert features == thermostat.supported_features - def test_set_temperature(self): - """Test set_temperature.""" - self.api.send.return_value = True - self.thermostat.update() - self.thermostat.set_temperature(**{ATTR_TEMPERATURE: 25}) - assert 25 == self.thermostat.target_temperature - def test_fan_mode(self): - """Test set_fan_mode.""" - self.api.send.return_value = True - self.thermostat.set_fan_mode(SPEED_HIGH) - assert SPEED_HIGH == self.thermostat.current_fan_mode +async def test_set_temperature(hass): + """Test set_temperature.""" + with patch('homeassistant.components.melissa'): + api = melissa_mock() + device = (await api.async_fetch_devices())[_SERIAL] + thermostat = MelissaClimate(api, _SERIAL, device) + await thermostat.async_update() + await thermostat.async_set_temperature(**{ATTR_TEMPERATURE: 25}) + assert 25 == thermostat.target_temperature - def test_set_operation_mode(self): - """Test set_operation_mode.""" - self.api.send.return_value = True - self.thermostat.set_operation_mode(STATE_COOL) - assert STATE_COOL == self.thermostat.current_operation - def test_turn_on(self): - """Test turn_on.""" - self.thermostat.turn_on() - assert self.thermostat.state +async def test_fan_mode(hass): + """Test set_fan_mode.""" + with patch('homeassistant.components.melissa'): + api = melissa_mock() + device = (await api.async_fetch_devices())[_SERIAL] + thermostat = MelissaClimate(api, _SERIAL, device) + await thermostat.async_update() + await hass.async_block_till_done() + await thermostat.async_set_fan_mode(SPEED_HIGH) + await hass.async_block_till_done() + assert SPEED_HIGH == thermostat.current_fan_mode - def test_turn_off(self): - """Test turn_off.""" - self.thermostat.turn_off() - assert STATE_OFF == self.thermostat.state - def test_send(self): - """Test send.""" - self.thermostat.update() - assert self.thermostat.send( - {'fan': self.api.FAN_MEDIUM}) - assert SPEED_MEDIUM == self.thermostat.current_fan_mode - self.api.send.return_value = False - self.thermostat._cur_settings = None - assert not self.thermostat.send({ - 'fan': self.api.FAN_LOW}) - assert SPEED_LOW != self.thermostat.current_fan_mode - assert self.thermostat._cur_settings is None +async def test_set_operation_mode(hass): + """Test set_operation_mode.""" + with patch('homeassistant.components.melissa'): + api = melissa_mock() + device = (await api.async_fetch_devices())[_SERIAL] + thermostat = MelissaClimate(api, _SERIAL, device) + await thermostat.async_update() + await hass.async_block_till_done() + await thermostat.async_set_operation_mode(STATE_COOL) + await hass.async_block_till_done() + assert STATE_COOL == thermostat.current_operation - @mock.patch('homeassistant.components.climate.melissa._LOGGER.warning') - def test_update(self, mocked_warning): - """Test update.""" - self.thermostat.update() - assert SPEED_LOW == self.thermostat.current_fan_mode - assert STATE_HEAT == self.thermostat.current_operation - self.thermostat._api.status.side_effect = KeyError('boom') - self.thermostat.update() - mocked_warning.assert_called_once_with( - 'Unable to update entity %s', self.thermostat.entity_id) - def test_melissa_state_to_hass(self): - """Test for translate melissa states to hass.""" - assert STATE_OFF == self.thermostat.melissa_state_to_hass(0) - assert STATE_ON == self.thermostat.melissa_state_to_hass(1) - assert STATE_IDLE == self.thermostat.melissa_state_to_hass(2) - assert self.thermostat.melissa_state_to_hass(3) is None +async def test_turn_on(hass): + """Test turn_on.""" + with patch('homeassistant.components.melissa'): + api = melissa_mock() + device = (await api.async_fetch_devices())[_SERIAL] + thermostat = MelissaClimate(api, _SERIAL, device) + await thermostat.async_update() + await hass.async_block_till_done() + await thermostat.async_turn_on() + await hass.async_block_till_done() + assert thermostat.state - def test_melissa_op_to_hass(self): - """Test for translate melissa operations to hass.""" - assert STATE_FAN_ONLY == self.thermostat.melissa_op_to_hass(1) - assert STATE_HEAT == self.thermostat.melissa_op_to_hass(2) - assert STATE_COOL == self.thermostat.melissa_op_to_hass(3) - assert STATE_DRY == self.thermostat.melissa_op_to_hass(4) - assert self.thermostat.melissa_op_to_hass(5) is None - def test_melissa_fan_to_hass(self): - """Test for translate melissa fan state to hass.""" - assert STATE_AUTO == self.thermostat.melissa_fan_to_hass(0) - assert SPEED_LOW == self.thermostat.melissa_fan_to_hass(1) - assert SPEED_MEDIUM == self.thermostat.melissa_fan_to_hass(2) - assert SPEED_HIGH == self.thermostat.melissa_fan_to_hass(3) - assert self.thermostat.melissa_fan_to_hass(4) is None +async def test_turn_off(hass): + """Test turn_off.""" + with patch('homeassistant.components.melissa'): + api = melissa_mock() + device = (await api.async_fetch_devices())[_SERIAL] + thermostat = MelissaClimate(api, _SERIAL, device) + await thermostat.async_update() + await hass.async_block_till_done() + await thermostat.async_turn_off() + await hass.async_block_till_done() + assert STATE_OFF == thermostat.state - @mock.patch('homeassistant.components.climate.melissa._LOGGER.warning') - def test_hass_mode_to_melissa(self, mocked_warning): - """Test for hass operations to melssa.""" - assert 1 == self.thermostat.hass_mode_to_melissa(STATE_FAN_ONLY) - assert 2 == self.thermostat.hass_mode_to_melissa(STATE_HEAT) - assert 3 == self.thermostat.hass_mode_to_melissa(STATE_COOL) - assert 4 == self.thermostat.hass_mode_to_melissa(STATE_DRY) - self.thermostat.hass_mode_to_melissa("test") - mocked_warning.assert_called_once_with( - "Melissa have no setting for %s mode", "test") - @mock.patch('homeassistant.components.climate.melissa._LOGGER.warning') - def test_hass_fan_to_melissa(self, mocked_warning): - """Test for translate melissa states to hass.""" - assert 0 == self.thermostat.hass_fan_to_melissa(STATE_AUTO) - assert 1 == self.thermostat.hass_fan_to_melissa(SPEED_LOW) - assert 2 == self.thermostat.hass_fan_to_melissa(SPEED_MEDIUM) - assert 3 == self.thermostat.hass_fan_to_melissa(SPEED_HIGH) - self.thermostat.hass_fan_to_melissa("test") - mocked_warning.assert_called_once_with( - "Melissa have no setting for %s fan mode", "test") +async def test_send(hass): + """Test send.""" + with patch('homeassistant.components.melissa'): + api = melissa_mock() + device = (await api.async_fetch_devices())[_SERIAL] + thermostat = MelissaClimate(api, _SERIAL, device) + await thermostat.async_update() + await hass.async_block_till_done() + await thermostat.async_send({'fan': api.FAN_MEDIUM}) + await hass.async_block_till_done() + assert SPEED_MEDIUM == thermostat.current_fan_mode + api.async_send.return_value = mock_coro_func(return_value=False) + thermostat._cur_settings = None + await thermostat.async_send({'fan': api.FAN_LOW}) + await hass.async_block_till_done() + assert SPEED_LOW != thermostat.current_fan_mode + assert thermostat._cur_settings is None + + +async def test_update(hass): + """Test update.""" + with patch('homeassistant.components.melissa'): + with patch('homeassistant.components.climate.melissa._LOGGER.warning' + ) as mocked_warning: + api = melissa_mock() + device = (await api.async_fetch_devices())[_SERIAL] + thermostat = MelissaClimate(api, _SERIAL, device) + await thermostat.async_update() + assert SPEED_LOW == thermostat.current_fan_mode + assert STATE_HEAT == thermostat.current_operation + api.async_status = mock_coro_func(exception=KeyError('boom')) + await thermostat.async_update() + mocked_warning.assert_called_once_with( + 'Unable to update entity %s', thermostat.entity_id) + + +async def test_melissa_state_to_hass(hass): + """Test for translate melissa states to hass.""" + with patch('homeassistant.components.melissa'): + api = melissa_mock() + device = (await api.async_fetch_devices())[_SERIAL] + thermostat = MelissaClimate(api, _SERIAL, device) + assert STATE_OFF == thermostat.melissa_state_to_hass(0) + assert STATE_ON == thermostat.melissa_state_to_hass(1) + assert STATE_IDLE == thermostat.melissa_state_to_hass(2) + assert thermostat.melissa_state_to_hass(3) is None + + +async def test_melissa_op_to_hass(hass): + """Test for translate melissa operations to hass.""" + with patch('homeassistant.components.melissa'): + api = melissa_mock() + device = (await api.async_fetch_devices())[_SERIAL] + thermostat = MelissaClimate(api, _SERIAL, device) + assert STATE_FAN_ONLY == thermostat.melissa_op_to_hass(1) + assert STATE_HEAT == thermostat.melissa_op_to_hass(2) + assert STATE_COOL == thermostat.melissa_op_to_hass(3) + assert STATE_DRY == thermostat.melissa_op_to_hass(4) + assert thermostat.melissa_op_to_hass(5) is None + + +async def test_melissa_fan_to_hass(hass): + """Test for translate melissa fan state to hass.""" + with patch('homeassistant.components.melissa'): + api = melissa_mock() + device = (await api.async_fetch_devices())[_SERIAL] + thermostat = MelissaClimate(api, _SERIAL, device) + assert STATE_AUTO == thermostat.melissa_fan_to_hass(0) + assert SPEED_LOW == thermostat.melissa_fan_to_hass(1) + assert SPEED_MEDIUM == thermostat.melissa_fan_to_hass(2) + assert SPEED_HIGH == thermostat.melissa_fan_to_hass(3) + assert thermostat.melissa_fan_to_hass(4) is None + + +async def test_hass_mode_to_melissa(hass): + """Test for hass operations to melssa.""" + with patch('homeassistant.components.melissa'): + with patch('homeassistant.components.climate.melissa._LOGGER.warning' + ) as mocked_warning: + api = melissa_mock() + device = (await api.async_fetch_devices())[_SERIAL] + thermostat = MelissaClimate(api, _SERIAL, device) + assert 1 == thermostat.hass_mode_to_melissa(STATE_FAN_ONLY) + assert 2 == thermostat.hass_mode_to_melissa(STATE_HEAT) + assert 3 == thermostat.hass_mode_to_melissa(STATE_COOL) + assert 4 == thermostat.hass_mode_to_melissa(STATE_DRY) + thermostat.hass_mode_to_melissa("test") + mocked_warning.assert_called_once_with( + "Melissa have no setting for %s mode", "test") + + +async def test_hass_fan_to_melissa(hass): + """Test for translate melissa states to hass.""" + with patch('homeassistant.components.melissa'): + with patch('homeassistant.components.climate.melissa._LOGGER.warning' + ) as mocked_warning: + api = melissa_mock() + device = (await api.async_fetch_devices())[_SERIAL] + thermostat = MelissaClimate(api, _SERIAL, device) + assert 0 == thermostat.hass_fan_to_melissa(STATE_AUTO) + assert 1 == thermostat.hass_fan_to_melissa(SPEED_LOW) + assert 2 == thermostat.hass_fan_to_melissa(SPEED_MEDIUM) + assert 3 == thermostat.hass_fan_to_melissa(SPEED_HIGH) + thermostat.hass_fan_to_melissa("test") + mocked_warning.assert_called_once_with( + "Melissa have no setting for %s fan mode", "test") diff --git a/tests/components/sensor/test_melissa.py b/tests/components/sensor/test_melissa.py index aff3df83c3d..024e2e564eb 100644 --- a/tests/components/sensor/test_melissa.py +++ b/tests/components/sensor/test_melissa.py @@ -1,89 +1,112 @@ """Test for Melissa climate component.""" -import unittest import json -from unittest.mock import Mock +from unittest.mock import Mock, patch + +from homeassistant.components.sensor.melissa import MelissaTemperatureSensor, \ + MelissaHumiditySensor + +from tests.common import load_fixture, mock_coro_func from homeassistant.components.melissa import DATA_MELISSA from homeassistant.components.sensor import melissa -from homeassistant.components.sensor.melissa import MelissaTemperatureSensor, \ - MelissaHumiditySensor from homeassistant.const import TEMP_CELSIUS -from tests.common import get_test_home_assistant, load_fixture -class TestMelissa(unittest.TestCase): - """Tests for Melissa climate.""" +_SERIAL = "12345678" - def setUp(self): # pylint: disable=invalid-name - """Set up test variables.""" - self.hass = get_test_home_assistant() - self._serial = '12345678' - self.api = Mock() - self.api.fetch_devices.return_value = json.loads(load_fixture( - 'melissa_fetch_devices.json' - )) - self.api.status.return_value = json.loads(load_fixture( - 'melissa_status.json' - )) +def melissa_mock(): + """Use this to mock the melissa api.""" + api = Mock() + api.async_fetch_devices = mock_coro_func( + return_value=json.loads(load_fixture('melissa_fetch_devices.json'))) + api.async_status = mock_coro_func(return_value=json.loads(load_fixture( + 'melissa_status.json' + ))) - self.api.TEMP = 'temp' - self.api.HUMIDITY = 'humidity' - device = self.api.fetch_devices()[self._serial] - self.temp = MelissaTemperatureSensor(device, self.api) - self.hum = MelissaHumiditySensor(device, self.api) + api.TEMP = 'temp' + api.HUMIDITY = 'humidity' + return api - def tearDown(self): # pylint: disable=invalid-name - """Teardown this test class. Stop hass.""" - self.hass.stop() - def test_setup_platform(self): - """Test setup_platform.""" - self.hass.data[DATA_MELISSA] = self.api +async def test_setup_platform(hass): + """Test setup_platform.""" + with patch('homeassistant.components.melissa'): + hass.data[DATA_MELISSA] = melissa_mock() config = {} - add_entities = Mock() + async_add_entities = mock_coro_func() discovery_info = {} - melissa.setup_platform(self.hass, config, add_entities, discovery_info) + await melissa.async_setup_platform( + hass, config, async_add_entities, discovery_info) - def test_name(self): - """Test name property.""" - device = self.api.fetch_devices()[self._serial] - assert self.temp.name == '{0} {1}'.format( + +async def test_name(hass): + """Test name property.""" + with patch('homeassistant.components.melissa'): + mocked_melissa = melissa_mock() + device = (await mocked_melissa.async_fetch_devices())[_SERIAL] + temp = MelissaTemperatureSensor(device, mocked_melissa) + hum = MelissaHumiditySensor(device, mocked_melissa) + + assert temp.name == '{0} {1}'.format( device['name'], - self.temp._type + temp._type ) - assert self.hum.name == '{0} {1}'.format( + assert hum.name == '{0} {1}'.format( device['name'], - self.hum._type + hum._type ) - def test_state(self): - """Test state property.""" - device = self.api.status()[self._serial] - self.temp.update() - assert self.temp.state == device[self.api.TEMP] - self.hum.update() - assert self.hum.state == device[self.api.HUMIDITY] - def test_unit_of_measurement(self): - """Test unit of measurement property.""" - assert self.temp.unit_of_measurement == TEMP_CELSIUS - assert self.hum.unit_of_measurement == '%' +async def test_state(hass): + """Test state property.""" + with patch('homeassistant.components.melissa'): + mocked_melissa = melissa_mock() + device = (await mocked_melissa.async_fetch_devices())[_SERIAL] + status = (await mocked_melissa.async_status())[_SERIAL] + temp = MelissaTemperatureSensor(device, mocked_melissa) + hum = MelissaHumiditySensor(device, mocked_melissa) + await temp.async_update() + assert temp.state == status[mocked_melissa.TEMP] + await hum.async_update() + assert hum.state == status[mocked_melissa.HUMIDITY] - def test_update(self): - """Test for update.""" - self.temp.update() - assert self.temp.state == 27.4 - self.hum.update() - assert self.hum.state == 18.7 - def test_update_keyerror(self): - """Test for faulty update.""" - self.temp._api.status.return_value = {} - self.temp.update() - assert self.temp.state is None - self.hum._api.status.return_value = {} - self.hum.update() - assert self.hum.state is None +async def test_unit_of_measurement(hass): + """Test unit of measurement property.""" + with patch('homeassistant.components.melissa'): + mocked_melissa = melissa_mock() + device = (await mocked_melissa.async_fetch_devices())[_SERIAL] + temp = MelissaTemperatureSensor(device, mocked_melissa) + hum = MelissaHumiditySensor(device, mocked_melissa) + assert temp.unit_of_measurement == TEMP_CELSIUS + assert hum.unit_of_measurement == '%' + + +async def test_update(hass): + """Test for update.""" + with patch('homeassistant.components.melissa'): + mocked_melissa = melissa_mock() + device = (await mocked_melissa.async_fetch_devices())[_SERIAL] + temp = MelissaTemperatureSensor(device, mocked_melissa) + hum = MelissaHumiditySensor(device, mocked_melissa) + await temp.async_update() + assert temp.state == 27.4 + await hum.async_update() + assert hum.state == 18.7 + + +async def test_update_keyerror(hass): + """Test for faulty update.""" + with patch('homeassistant.components.melissa'): + mocked_melissa = melissa_mock() + device = (await mocked_melissa.async_fetch_devices())[_SERIAL] + temp = MelissaTemperatureSensor(device, mocked_melissa) + hum = MelissaHumiditySensor(device, mocked_melissa) + mocked_melissa.async_status = mock_coro_func(return_value={}) + await temp.async_update() + assert temp.state is None + await hum.async_update() + assert hum.state is None diff --git a/tests/components/test_melissa.py b/tests/components/test_melissa.py index 020d4f7db1e..d7bb9b3c1e4 100644 --- a/tests/components/test_melissa.py +++ b/tests/components/test_melissa.py @@ -1,6 +1,5 @@ """The test for the Melissa Climate component.""" -import unittest -from tests.common import get_test_home_assistant, MockDependency +from tests.common import MockDependency, mock_coro_func from homeassistant.components import melissa @@ -12,25 +11,15 @@ VALID_CONFIG = { } -class TestMelissa(unittest.TestCase): - """Test the Melissa component.""" +async def test_setup(hass): + """Test setting up the Melissa component.""" + with MockDependency('melissa') as mocked_melissa: + mocked_melissa.AsyncMelissa().async_connect = mock_coro_func() + await melissa.async_setup(hass, VALID_CONFIG) - def setUp(self): # pylint: disable=invalid-name - """Initialize the values for this test class.""" - self.hass = get_test_home_assistant() - self.config = VALID_CONFIG - - def tearDown(self): # pylint: disable=invalid-name - """Teardown this test class. Stop hass.""" - self.hass.stop() - - @MockDependency("melissa") - def test_setup(self, mocked_melissa): - """Test setting up the Melissa component.""" - melissa.setup(self.hass, self.config) - - mocked_melissa.Melissa.assert_called_with( + mocked_melissa.AsyncMelissa.assert_called_with( username="********", password="********") - assert melissa.DATA_MELISSA in self.hass.data - assert isinstance(self.hass.data[melissa.DATA_MELISSA], type( - mocked_melissa.Melissa())) + + assert melissa.DATA_MELISSA in hass.data + assert isinstance(hass.data[melissa.DATA_MELISSA], type( + mocked_melissa.AsyncMelissa()))