Rework Melissa tests (#113241)

This commit is contained in:
Joost Lekkerkerker 2024-03-13 19:54:52 +01:00 committed by GitHub
parent 3e85b2ed12
commit a136638719
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 128 additions and 371 deletions

View File

@ -1,6 +1,6 @@
"""Support for Melissa climate.""" """Support for Melissa climate."""
import melissa from melissa import AsyncMelissa
import voluptuous as vol import voluptuous as vol
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME, Platform from homeassistant.const import CONF_PASSWORD, CONF_USERNAME, Platform
@ -31,7 +31,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
conf = config[DOMAIN] conf = config[DOMAIN]
username = conf.get(CONF_USERNAME) username = conf.get(CONF_USERNAME)
password = conf.get(CONF_PASSWORD) password = conf.get(CONF_PASSWORD)
api = melissa.AsyncMelissa(username=username, password=password) api = AsyncMelissa(username=username, password=password)
await api.async_connect() await api.async_connect()
hass.data[DATA_MELISSA] = api hass.data[DATA_MELISSA] = api

View File

@ -50,7 +50,7 @@ async def async_setup_platform(
if device["type"] == "melissa": if device["type"] == "melissa":
all_devices.append(MelissaClimate(api, device["serial_number"], device)) all_devices.append(MelissaClimate(api, device["serial_number"], device))
async_add_entities(all_devices) async_add_entities(all_devices, True)
class MelissaClimate(ClimateEntity): class MelissaClimate(ClimateEntity):

View File

@ -1 +1,11 @@
"""Tests for the melissa component.""" """Tests for the melissa component."""
from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
VALID_CONFIG = {"melissa": {"username": "********", "password": "********"}}
async def setup_integration(hass: HomeAssistant) -> None:
"""Set up the melissa integration in Home Assistant."""
assert await async_setup_component(hass, "melissa", VALID_CONFIG)
await hass.async_block_till_done()

View File

@ -0,0 +1,47 @@
"""Melissa conftest."""
from unittest.mock import AsyncMock, patch
import pytest
from tests.common import load_json_object_fixture
@pytest.fixture
async def mock_melissa():
"""Mock the Melissa API."""
with patch(
"homeassistant.components.melissa.AsyncMelissa", autospec=True
) as mock_client:
mock_client.return_value.async_connect = AsyncMock()
mock_client.return_value.async_fetch_devices.return_value = (
load_json_object_fixture("fetch_devices.json", "melissa")
)
mock_client.return_value.async_status.return_value = load_json_object_fixture(
"status.json", "melissa"
)
mock_client.return_value.async_cur_settings.return_value = (
load_json_object_fixture("cur_settings.json", "melissa")
)
mock_client.return_value.STATE_OFF = 0
mock_client.return_value.STATE_ON = 1
mock_client.return_value.STATE_IDLE = 2
mock_client.return_value.MODE_AUTO = 0
mock_client.return_value.MODE_FAN = 1
mock_client.return_value.MODE_HEAT = 2
mock_client.return_value.MODE_COOL = 3
mock_client.return_value.MODE_DRY = 4
mock_client.return_value.FAN_AUTO = 0
mock_client.return_value.FAN_LOW = 1
mock_client.return_value.FAN_MEDIUM = 2
mock_client.return_value.FAN_HIGH = 3
mock_client.return_value.STATE = "state"
mock_client.return_value.MODE = "mode"
mock_client.return_value.FAN = "fan"
mock_client.return_value.TEMP = "temp"
mock_client.return_value.HUMIDITY = "humidity"
yield mock_client

View File

@ -0,0 +1,34 @@
# serializer version: 1
# name: test_setup_platform
StateSnapshot({
'attributes': ReadOnlyDict({
'current_humidity': 18.7,
'current_temperature': 27.4,
'fan_mode': 'low',
'fan_modes': list([
'auto',
'high',
'medium',
'low',
]),
'friendly_name': 'Melissa 12345678',
'hvac_modes': list([
<HVACMode.HEAT: 'heat'>,
<HVACMode.COOL: 'cool'>,
<HVACMode.DRY: 'dry'>,
<HVACMode.FAN_ONLY: 'fan_only'>,
<HVACMode.OFF: 'off'>,
]),
'max_temp': 30,
'min_temp': 16,
'supported_features': <ClimateEntityFeature: 393>,
'target_temp_step': 1,
'temperature': 16,
}),
'context': <ANY>,
'entity_id': 'climate.melissa_12345678',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': 'heat',
})
# ---

View File

@ -1,368 +1,46 @@
"""Test for Melissa climate component.""" """Test for Melissa climate component."""
import json from unittest.mock import AsyncMock
from unittest.mock import AsyncMock, Mock, patch
from syrupy import SnapshotAssertion
from homeassistant.components.climate import ( from homeassistant.components.climate import (
FAN_HIGH, DOMAIN as CLIMATE_DOMAIN,
FAN_LOW, SERVICE_SET_TEMPERATURE,
FAN_MEDIUM,
ClimateEntityFeature,
HVACMode,
) )
from homeassistant.components.melissa import DATA_MELISSA, climate as melissa from homeassistant.const import ATTR_ENTITY_ID, ATTR_TEMPERATURE
from homeassistant.components.melissa.climate import MelissaClimate
from homeassistant.const import ATTR_TEMPERATURE, UnitOfTemperature
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
import homeassistant.helpers.entity_registry as er
from tests.common import load_fixture from tests.components.melissa import setup_integration
_SERIAL = "12345678"
def melissa_mock(): async def test_setup_platform(
"""Use this to mock the melissa api.""" hass: HomeAssistant, mock_melissa, snapshot: SnapshotAssertion
api = Mock() ) -> None:
api.async_fetch_devices = AsyncMock(
return_value=json.loads(load_fixture("fetch_devices.json", "melissa"))
)
api.async_status = AsyncMock(
return_value=json.loads(load_fixture("status.json", "melissa"))
)
api.async_cur_settings = AsyncMock(
return_value=json.loads(load_fixture("cur_settings.json", "melissa"))
)
api.async_send = AsyncMock(return_value=True)
api.STATE_OFF = 0
api.STATE_ON = 1
api.STATE_IDLE = 2
api.MODE_AUTO = 0
api.MODE_FAN = 1
api.MODE_HEAT = 2
api.MODE_COOL = 3
api.MODE_DRY = 4
api.FAN_AUTO = 0
api.FAN_LOW = 1
api.FAN_MEDIUM = 2
api.FAN_HIGH = 3
api.STATE = "state"
api.MODE = "mode"
api.FAN = "fan"
api.TEMP = "temp"
return api
async def test_setup_platform(hass: HomeAssistant) -> None:
"""Test setup_platform.""" """Test setup_platform."""
with patch( await setup_integration(hass)
"homeassistant.components.melissa.climate.MelissaClimate"
) as mocked_thermostat:
api = melissa_mock()
device = (await api.async_fetch_devices())[_SERIAL]
thermostat = mocked_thermostat(api, device["serial_number"], device)
thermostats = [thermostat]
hass.data[DATA_MELISSA] = api assert hass.states.get("climate.melissa_12345678") == snapshot
config = {}
add_entities = Mock()
discovery_info = {}
await melissa.async_setup_platform(hass, config, add_entities, discovery_info)
add_entities.assert_called_once_with(thermostats)
async def test_get_name(hass: HomeAssistant) -> None: async def test_actions(
"""Test name property.""" hass: HomeAssistant,
with patch("homeassistant.components.melissa"): snapshot: SnapshotAssertion,
api = melissa_mock() entity_registry: er.EntityRegistry,
device = (await api.async_fetch_devices())[_SERIAL] mock_melissa: AsyncMock,
thermostat = MelissaClimate(api, _SERIAL, device) ) -> None:
assert thermostat.name == "Melissa 12345678" """Test that the switch can be turned on and off."""
await setup_integration(hass)
entity_id = "climate.melissa_12345678"
async def test_current_fan_mode(hass: HomeAssistant) -> None: await hass.services.async_call(
"""Test current_fan_mode property.""" CLIMATE_DOMAIN,
with patch("homeassistant.components.melissa"): SERVICE_SET_TEMPERATURE,
api = melissa_mock() {ATTR_ENTITY_ID: entity_id, ATTR_TEMPERATURE: 25},
device = (await api.async_fetch_devices())[_SERIAL] blocking=True,
thermostat = MelissaClimate(api, _SERIAL, device) )
await thermostat.async_update() await hass.async_block_till_done()
assert thermostat.fan_mode == FAN_LOW
thermostat._cur_settings = None assert len(mock_melissa.return_value.async_send.mock_calls) == 2
assert thermostat.fan_mode is None
async def test_current_temperature(hass: HomeAssistant) -> None:
"""Test current temperature."""
with patch("homeassistant.components.melissa"):
api = melissa_mock()
device = (await api.async_fetch_devices())[_SERIAL]
thermostat = MelissaClimate(api, _SERIAL, device)
assert thermostat.current_temperature == 27.4
async def test_current_temperature_no_data(hass: HomeAssistant) -> None:
"""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: HomeAssistant) -> None:
"""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 thermostat.target_temperature_step == 1
async def test_current_operation(hass: HomeAssistant) -> None:
"""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.state == HVACMode.HEAT
thermostat._cur_settings = None
assert thermostat.hvac_action is None
async def test_operation_list(hass: HomeAssistant) -> None:
"""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 [
HVACMode.HEAT,
HVACMode.COOL,
HVACMode.DRY,
HVACMode.FAN_ONLY,
HVACMode.OFF,
] == thermostat.hvac_modes
async def test_fan_modes(hass: HomeAssistant) -> None:
"""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 ["auto", FAN_HIGH, FAN_MEDIUM, FAN_LOW] == thermostat.fan_modes
async def test_target_temperature(hass: HomeAssistant) -> None:
"""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 thermostat.target_temperature == 16
thermostat._cur_settings = None
assert thermostat.target_temperature is None
async def test_state(hass: HomeAssistant) -> None:
"""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 thermostat.state == HVACMode.HEAT
thermostat._cur_settings = None
assert thermostat.state is None
async def test_temperature_unit(hass: HomeAssistant) -> None:
"""Test temperature unit."""
with patch("homeassistant.components.melissa"):
api = melissa_mock()
device = (await api.async_fetch_devices())[_SERIAL]
thermostat = MelissaClimate(api, _SERIAL, device)
assert thermostat.temperature_unit == UnitOfTemperature.CELSIUS
async def test_min_temp(hass: HomeAssistant) -> None:
"""Test min temp."""
with patch("homeassistant.components.melissa"):
api = melissa_mock()
device = (await api.async_fetch_devices())[_SERIAL]
thermostat = MelissaClimate(api, _SERIAL, device)
assert thermostat.min_temp == 16
async def test_max_temp(hass: HomeAssistant) -> None:
"""Test max temp."""
with patch("homeassistant.components.melissa"):
api = melissa_mock()
device = (await api.async_fetch_devices())[_SERIAL]
thermostat = MelissaClimate(api, _SERIAL, device)
assert thermostat.max_temp == 30
async def test_supported_features(hass: HomeAssistant) -> None:
"""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 = (
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.FAN_MODE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
assert thermostat.supported_features == features
async def test_set_temperature(hass: HomeAssistant) -> None:
"""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 thermostat.target_temperature == 25
async def test_fan_mode(hass: HomeAssistant) -> None:
"""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(FAN_HIGH)
await hass.async_block_till_done()
assert thermostat.fan_mode == FAN_HIGH
async def test_set_operation_mode(hass: HomeAssistant) -> None:
"""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_hvac_mode(HVACMode.COOL)
await hass.async_block_till_done()
assert thermostat.hvac_mode == HVACMode.COOL
async def test_send(hass: HomeAssistant) -> None:
"""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 thermostat.fan_mode == FAN_MEDIUM
api.async_send.return_value = AsyncMock(return_value=False)
thermostat._cur_settings = None
await thermostat.async_send({"fan": api.FAN_LOW})
await hass.async_block_till_done()
assert thermostat.fan_mode != FAN_LOW
assert thermostat._cur_settings is None
async def test_update(hass: HomeAssistant) -> None:
"""Test update."""
with patch(
"homeassistant.components.melissa.climate._LOGGER.warning"
) as mocked_warning, 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.fan_mode == FAN_LOW
assert thermostat.state == HVACMode.HEAT
api.async_status = AsyncMock(side_effect=KeyError("boom"))
await thermostat.async_update()
mocked_warning.assert_called_once_with(
"Unable to update entity %s", thermostat.entity_id
)
async def test_melissa_op_to_hass(hass: HomeAssistant) -> None:
"""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 thermostat.melissa_op_to_hass(1) == HVACMode.FAN_ONLY
assert thermostat.melissa_op_to_hass(2) == HVACMode.HEAT
assert thermostat.melissa_op_to_hass(3) == HVACMode.COOL
assert thermostat.melissa_op_to_hass(4) == HVACMode.DRY
assert thermostat.melissa_op_to_hass(5) is None
async def test_melissa_fan_to_hass(hass: HomeAssistant) -> None:
"""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 thermostat.melissa_fan_to_hass(0) == "auto"
assert thermostat.melissa_fan_to_hass(1) == FAN_LOW
assert thermostat.melissa_fan_to_hass(2) == FAN_MEDIUM
assert thermostat.melissa_fan_to_hass(3) == FAN_HIGH
assert thermostat.melissa_fan_to_hass(4) is None
async def test_hass_mode_to_melissa(hass: HomeAssistant) -> None:
"""Test for hass operations to melssa."""
with patch(
"homeassistant.components.melissa.climate._LOGGER.warning"
) as mocked_warning, patch("homeassistant.components.melissa"):
api = melissa_mock()
device = (await api.async_fetch_devices())[_SERIAL]
thermostat = MelissaClimate(api, _SERIAL, device)
assert thermostat.hass_mode_to_melissa(HVACMode.FAN_ONLY) == 1
assert thermostat.hass_mode_to_melissa(HVACMode.HEAT) == 2
assert thermostat.hass_mode_to_melissa(HVACMode.COOL) == 3
assert thermostat.hass_mode_to_melissa(HVACMode.DRY) == 4
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: HomeAssistant) -> None:
"""Test for translate melissa states to hass."""
with patch(
"homeassistant.components.melissa.climate._LOGGER.warning"
) as mocked_warning, patch("homeassistant.components.melissa"):
api = melissa_mock()
device = (await api.async_fetch_devices())[_SERIAL]
thermostat = MelissaClimate(api, _SERIAL, device)
assert thermostat.hass_fan_to_melissa("auto") == 0
assert thermostat.hass_fan_to_melissa(FAN_LOW) == 1
assert thermostat.hass_fan_to_melissa(FAN_MEDIUM) == 2
assert thermostat.hass_fan_to_melissa(FAN_HIGH) == 3
thermostat.hass_fan_to_melissa("test")
mocked_warning.assert_called_once_with(
"Melissa have no setting for %s fan mode", "test"
)

View File

@ -1,25 +1,13 @@
"""The test for the Melissa Climate component.""" """The test for the Melissa Climate component."""
from unittest.mock import AsyncMock, patch
from homeassistant.components import melissa
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
VALID_CONFIG = {"melissa": {"username": "********", "password": "********"}} from tests.components.melissa import setup_integration
async def test_setup(hass: HomeAssistant) -> None: async def test_setup(hass: HomeAssistant, mock_melissa) -> None:
"""Test setting up the Melissa component.""" """Test setting up the Melissa component."""
with patch("melissa.AsyncMelissa") as mocked_melissa, patch.object( await setup_integration(hass)
melissa, "async_load_platform"
):
mocked_melissa.return_value.async_connect = AsyncMock()
await melissa.async_setup(hass, VALID_CONFIG)
mocked_melissa.assert_called_with(username="********", password="********") mock_melissa.assert_called_with(username="********", password="********")
assert melissa.DATA_MELISSA in hass.data
assert isinstance(
hass.data[melissa.DATA_MELISSA],
type(mocked_melissa.return_value),
)