mirror of
https://github.com/home-assistant/core.git
synced 2026-09-27 18:08:37 -04:00
Refactor fan in vesync (#135744)
* Refactor Fan * Add tower fan tests and mode * Schedule update after turn off * Adjust updates to refresh library * correct off command * Revert changes * Merge corrections * Remove unused code to increase test coverage * Ruff * Tests * Test for preset mode * Adjust to increase coverage * Test Corrections * tests to match other PR --------- Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
co-authored by
Joost Lekkerkerker
parent
4c40ec4948
commit
2dc63eb8c5
@@ -15,6 +15,8 @@ ENTITY_HUMIDIFIER_MIST_LEVEL = "number.humidifier_200s_mist_level"
|
||||
ENTITY_HUMIDIFIER_HUMIDITY = "sensor.humidifier_200s_humidity"
|
||||
ENTITY_HUMIDIFIER_300S_NIGHT_LIGHT_SELECT = "select.humidifier_300s_night_light_level"
|
||||
|
||||
ENTITY_FAN = "fan.SmartTowerFan"
|
||||
|
||||
ENTITY_SWITCH_DISPLAY = "switch.humidifier_200s_display"
|
||||
|
||||
ALL_DEVICES = load_json_object_fixture("vesync-devices.json", DOMAIN)
|
||||
|
||||
@@ -198,6 +198,26 @@ async def install_humidifier_device(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
||||
@pytest.fixture(name="fan_config_entry")
|
||||
async def fan_config_entry(
|
||||
hass: HomeAssistant, requests_mock: requests_mock.Mocker, config
|
||||
) -> MockConfigEntry:
|
||||
"""Create a mock VeSync config entry for `SmartTowerFan`."""
|
||||
entry = MockConfigEntry(
|
||||
title="VeSync",
|
||||
domain=DOMAIN,
|
||||
data=config[DOMAIN],
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
device_name = "SmartTowerFan"
|
||||
mock_multiple_device_responses(requests_mock, [device_name])
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
return entry
|
||||
|
||||
|
||||
@pytest.fixture(name="switch_old_id_config_entry")
|
||||
async def switch_old_id_config_entry(
|
||||
hass: HomeAssistant, requests_mock: requests_mock.Mocker, config
|
||||
|
||||
@@ -640,8 +640,8 @@
|
||||
'preset_modes': list([
|
||||
'advancedSleep',
|
||||
'auto',
|
||||
'turbo',
|
||||
'normal',
|
||||
'turbo',
|
||||
]),
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
@@ -682,12 +682,12 @@
|
||||
'night_light': 'off',
|
||||
'percentage': None,
|
||||
'percentage_step': 7.6923076923076925,
|
||||
'preset_mode': None,
|
||||
'preset_mode': 'normal',
|
||||
'preset_modes': list([
|
||||
'advancedSleep',
|
||||
'auto',
|
||||
'turbo',
|
||||
'normal',
|
||||
'turbo',
|
||||
]),
|
||||
'screen_status': False,
|
||||
'supported_features': <FanEntityFeature: 57>,
|
||||
|
||||
@@ -1,17 +1,24 @@
|
||||
"""Tests for the fan module."""
|
||||
|
||||
from contextlib import nullcontext
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
import requests_mock
|
||||
from syrupy import SnapshotAssertion
|
||||
|
||||
from homeassistant.components.fan import DOMAIN as FAN_DOMAIN
|
||||
from homeassistant.components.fan import ATTR_PRESET_MODE, DOMAIN as FAN_DOMAIN
|
||||
from homeassistant.const import ATTR_ENTITY_ID, SERVICE_TURN_OFF, SERVICE_TURN_ON
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||
|
||||
from .common import ALL_DEVICE_NAMES, mock_devices_response
|
||||
from .common import ALL_DEVICE_NAMES, ENTITY_FAN, mock_devices_response
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
NoException = nullcontext()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("device_name", ALL_DEVICE_NAMES)
|
||||
async def test_fan_state(
|
||||
@@ -49,3 +56,105 @@ async def test_fan_state(
|
||||
# Check states
|
||||
for entity in entities:
|
||||
assert hass.states.get(entity.entity_id) == snapshot(name=entity.entity_id)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("action", "command"),
|
||||
[
|
||||
(SERVICE_TURN_ON, "pyvesync.vesyncfan.VeSyncTowerFan.turn_on"),
|
||||
(SERVICE_TURN_OFF, "pyvesync.vesyncfan.VeSyncTowerFan.turn_off"),
|
||||
],
|
||||
)
|
||||
async def test_turn_on_off_success(
|
||||
hass: HomeAssistant,
|
||||
fan_config_entry: MockConfigEntry,
|
||||
action: str,
|
||||
command: str,
|
||||
) -> None:
|
||||
"""Test turn_on and turn_off method."""
|
||||
|
||||
with (
|
||||
patch(command, return_value=True) as method_mock,
|
||||
):
|
||||
with patch(
|
||||
"homeassistant.components.vesync.fan.VeSyncFanHA.schedule_update_ha_state"
|
||||
) as update_mock:
|
||||
await hass.services.async_call(
|
||||
FAN_DOMAIN,
|
||||
action,
|
||||
{ATTR_ENTITY_ID: ENTITY_FAN},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
await hass.async_block_till_done()
|
||||
method_mock.assert_called_once()
|
||||
update_mock.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("action", "command"),
|
||||
[
|
||||
(SERVICE_TURN_ON, "pyvesync.vesyncfan.VeSyncTowerFan.turn_on"),
|
||||
(SERVICE_TURN_OFF, "pyvesync.vesyncfan.VeSyncTowerFan.turn_off"),
|
||||
],
|
||||
)
|
||||
async def test_turn_on_off_raises_error(
|
||||
hass: HomeAssistant,
|
||||
fan_config_entry: MockConfigEntry,
|
||||
action: str,
|
||||
command: str,
|
||||
) -> None:
|
||||
"""Test turn_on and turn_off raises errors when fails."""
|
||||
|
||||
# returns False indicating failure in which case raises HomeAssistantError.
|
||||
with (
|
||||
patch(
|
||||
command,
|
||||
return_value=False,
|
||||
) as method_mock,
|
||||
pytest.raises(HomeAssistantError),
|
||||
):
|
||||
await hass.services.async_call(
|
||||
FAN_DOMAIN,
|
||||
action,
|
||||
{ATTR_ENTITY_ID: ENTITY_FAN},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
await hass.async_block_till_done()
|
||||
method_mock.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("api_response", "expectation"),
|
||||
[(True, NoException), (False, pytest.raises(HomeAssistantError))],
|
||||
)
|
||||
async def test_set_preset_mode(
|
||||
hass: HomeAssistant,
|
||||
fan_config_entry: MockConfigEntry,
|
||||
api_response: bool,
|
||||
expectation,
|
||||
) -> None:
|
||||
"""Test handling of value in set_preset_mode method. Does this via turn on as it increases test coverage."""
|
||||
|
||||
# If VeSyncTowerFan.normal_mode fails (returns False), then HomeAssistantError is raised
|
||||
with (
|
||||
expectation,
|
||||
patch(
|
||||
"pyvesync.vesyncfan.VeSyncTowerFan.normal_mode",
|
||||
return_value=api_response,
|
||||
) as method_mock,
|
||||
):
|
||||
with patch(
|
||||
"homeassistant.components.vesync.fan.VeSyncFanHA.schedule_update_ha_state"
|
||||
) as update_mock:
|
||||
await hass.services.async_call(
|
||||
FAN_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: ENTITY_FAN, ATTR_PRESET_MODE: "normal"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
await hass.async_block_till_done()
|
||||
method_mock.assert_called_once()
|
||||
update_mock.assert_called_once()
|
||||
|
||||
Reference in New Issue
Block a user