Yeelight local push updates (#51160)

Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
starkillerOG 2021-08-09 20:33:34 +02:00 committed by GitHub
parent acf55f2f3a
commit a23da30c29
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 328 additions and 259 deletions

View file

@ -1,6 +1,6 @@
"""Test the Yeelight light."""
import logging
from unittest.mock import MagicMock, patch
from unittest.mock import AsyncMock, MagicMock, patch
from yeelight import (
BulbException,
@ -131,7 +131,9 @@ async def test_services(hass: HomeAssistant, caplog):
config_entry.add_to_hass(hass)
mocked_bulb = _mocked_bulb()
with _patch_discovery(MODULE), patch(f"{MODULE}.Bulb", return_value=mocked_bulb):
with _patch_discovery(MODULE), patch(
f"{MODULE}.AsyncBulb", return_value=mocked_bulb
):
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
@ -146,8 +148,11 @@ async def test_services(hass: HomeAssistant, caplog):
err_count = len([x for x in caplog.records if x.levelno == logging.ERROR])
# success
mocked_method = MagicMock()
setattr(type(mocked_bulb), method, mocked_method)
if method.startswith("async_"):
mocked_method = AsyncMock()
else:
mocked_method = MagicMock()
setattr(mocked_bulb, method, mocked_method)
await hass.services.async_call(domain, service, data, blocking=True)
if payload is None:
mocked_method.assert_called_once()
@ -161,8 +166,11 @@ async def test_services(hass: HomeAssistant, caplog):
# failure
if failure_side_effect:
mocked_method = MagicMock(side_effect=failure_side_effect)
setattr(type(mocked_bulb), method, mocked_method)
if method.startswith("async_"):
mocked_method = AsyncMock(side_effect=failure_side_effect)
else:
mocked_method = MagicMock(side_effect=failure_side_effect)
setattr(mocked_bulb, method, mocked_method)
await hass.services.async_call(domain, service, data, blocking=True)
assert (
len([x for x in caplog.records if x.levelno == logging.ERROR])
@ -173,6 +181,7 @@ async def test_services(hass: HomeAssistant, caplog):
brightness = 100
rgb_color = (0, 128, 255)
transition = 2
mocked_bulb.last_properties["power"] = "off"
await hass.services.async_call(
"light",
SERVICE_TURN_ON,
@ -186,30 +195,30 @@ async def test_services(hass: HomeAssistant, caplog):
},
blocking=True,
)
mocked_bulb.turn_on.assert_called_once_with(
mocked_bulb.async_turn_on.assert_called_once_with(
duration=transition * 1000,
light_type=LightType.Main,
power_mode=PowerMode.NORMAL,
)
mocked_bulb.turn_on.reset_mock()
mocked_bulb.async_turn_on.reset_mock()
mocked_bulb.start_music.assert_called_once()
mocked_bulb.start_music.reset_mock()
mocked_bulb.set_brightness.assert_called_once_with(
mocked_bulb.async_set_brightness.assert_called_once_with(
brightness / 255 * 100, duration=transition * 1000, light_type=LightType.Main
)
mocked_bulb.set_brightness.reset_mock()
mocked_bulb.set_color_temp.assert_not_called()
mocked_bulb.set_color_temp.reset_mock()
mocked_bulb.set_hsv.assert_not_called()
mocked_bulb.set_hsv.reset_mock()
mocked_bulb.set_rgb.assert_called_once_with(
mocked_bulb.async_set_brightness.reset_mock()
mocked_bulb.async_set_color_temp.assert_not_called()
mocked_bulb.async_set_color_temp.reset_mock()
mocked_bulb.async_set_hsv.assert_not_called()
mocked_bulb.async_set_hsv.reset_mock()
mocked_bulb.async_set_rgb.assert_called_once_with(
*rgb_color, duration=transition * 1000, light_type=LightType.Main
)
mocked_bulb.set_rgb.reset_mock()
mocked_bulb.start_flow.assert_called_once() # flash
mocked_bulb.start_flow.reset_mock()
mocked_bulb.stop_flow.assert_called_once_with(light_type=LightType.Main)
mocked_bulb.stop_flow.reset_mock()
mocked_bulb.async_set_rgb.reset_mock()
mocked_bulb.async_start_flow.assert_called_once() # flash
mocked_bulb.async_start_flow.reset_mock()
mocked_bulb.async_stop_flow.assert_called_once_with(light_type=LightType.Main)
mocked_bulb.async_stop_flow.reset_mock()
# turn_on hs_color
brightness = 100
@ -228,35 +237,36 @@ async def test_services(hass: HomeAssistant, caplog):
},
blocking=True,
)
mocked_bulb.turn_on.assert_called_once_with(
mocked_bulb.async_turn_on.assert_called_once_with(
duration=transition * 1000,
light_type=LightType.Main,
power_mode=PowerMode.NORMAL,
)
mocked_bulb.turn_on.reset_mock()
mocked_bulb.async_turn_on.reset_mock()
mocked_bulb.start_music.assert_called_once()
mocked_bulb.start_music.reset_mock()
mocked_bulb.set_brightness.assert_called_once_with(
mocked_bulb.async_set_brightness.assert_called_once_with(
brightness / 255 * 100, duration=transition * 1000, light_type=LightType.Main
)
mocked_bulb.set_brightness.reset_mock()
mocked_bulb.set_color_temp.assert_not_called()
mocked_bulb.set_color_temp.reset_mock()
mocked_bulb.set_hsv.assert_called_once_with(
mocked_bulb.async_set_brightness.reset_mock()
mocked_bulb.async_set_color_temp.assert_not_called()
mocked_bulb.async_set_color_temp.reset_mock()
mocked_bulb.async_set_hsv.assert_called_once_with(
*hs_color, duration=transition * 1000, light_type=LightType.Main
)
mocked_bulb.set_hsv.reset_mock()
mocked_bulb.set_rgb.assert_not_called()
mocked_bulb.set_rgb.reset_mock()
mocked_bulb.start_flow.assert_called_once() # flash
mocked_bulb.start_flow.reset_mock()
mocked_bulb.stop_flow.assert_called_once_with(light_type=LightType.Main)
mocked_bulb.stop_flow.reset_mock()
mocked_bulb.async_set_hsv.reset_mock()
mocked_bulb.async_set_rgb.assert_not_called()
mocked_bulb.async_set_rgb.reset_mock()
mocked_bulb.async_start_flow.assert_called_once() # flash
mocked_bulb.async_start_flow.reset_mock()
mocked_bulb.async_stop_flow.assert_called_once_with(light_type=LightType.Main)
mocked_bulb.async_stop_flow.reset_mock()
# turn_on color_temp
brightness = 100
color_temp = 200
transition = 1
mocked_bulb.last_properties["power"] = "off"
await hass.services.async_call(
"light",
SERVICE_TURN_ON,
@ -270,31 +280,32 @@ async def test_services(hass: HomeAssistant, caplog):
},
blocking=True,
)
mocked_bulb.turn_on.assert_called_once_with(
mocked_bulb.async_turn_on.assert_called_once_with(
duration=transition * 1000,
light_type=LightType.Main,
power_mode=PowerMode.NORMAL,
)
mocked_bulb.turn_on.reset_mock()
mocked_bulb.async_turn_on.reset_mock()
mocked_bulb.start_music.assert_called_once()
mocked_bulb.set_brightness.assert_called_once_with(
mocked_bulb.async_set_brightness.assert_called_once_with(
brightness / 255 * 100, duration=transition * 1000, light_type=LightType.Main
)
mocked_bulb.set_color_temp.assert_called_once_with(
mocked_bulb.async_set_color_temp.assert_called_once_with(
color_temperature_mired_to_kelvin(color_temp),
duration=transition * 1000,
light_type=LightType.Main,
)
mocked_bulb.set_hsv.assert_not_called()
mocked_bulb.set_rgb.assert_not_called()
mocked_bulb.start_flow.assert_called_once() # flash
mocked_bulb.stop_flow.assert_called_once_with(light_type=LightType.Main)
mocked_bulb.async_set_hsv.assert_not_called()
mocked_bulb.async_set_rgb.assert_not_called()
mocked_bulb.async_start_flow.assert_called_once() # flash
mocked_bulb.async_stop_flow.assert_called_once_with(light_type=LightType.Main)
mocked_bulb.last_properties["power"] = "off"
# turn_on nightlight
await _async_test_service(
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: ENTITY_NIGHTLIGHT},
"turn_on",
"async_turn_on",
payload={
"duration": DEFAULT_TRANSITION,
"light_type": LightType.Main,
@ -303,11 +314,12 @@ async def test_services(hass: HomeAssistant, caplog):
domain="light",
)
mocked_bulb.last_properties["power"] = "on"
# turn_off
await _async_test_service(
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: ENTITY_LIGHT, ATTR_TRANSITION: transition},
"turn_off",
"async_turn_off",
domain="light",
payload={"duration": transition * 1000, "light_type": LightType.Main},
)
@ -317,7 +329,7 @@ async def test_services(hass: HomeAssistant, caplog):
await _async_test_service(
SERVICE_SET_MODE,
{ATTR_ENTITY_ID: ENTITY_LIGHT, ATTR_MODE: "rgb"},
"set_power_mode",
"async_set_power_mode",
[PowerMode[mode.upper()]],
)
@ -328,7 +340,7 @@ async def test_services(hass: HomeAssistant, caplog):
ATTR_ENTITY_ID: ENTITY_LIGHT,
ATTR_TRANSITIONS: [{YEELIGHT_TEMPERATURE_TRANSACTION: [1900, 2000, 60]}],
},
"start_flow",
"async_start_flow",
)
# set_color_scene
@ -339,7 +351,7 @@ async def test_services(hass: HomeAssistant, caplog):
ATTR_RGB_COLOR: [10, 20, 30],
ATTR_BRIGHTNESS: 50,
},
"set_scene",
"async_set_scene",
[SceneClass.COLOR, 10, 20, 30, 50],
)
@ -347,7 +359,7 @@ async def test_services(hass: HomeAssistant, caplog):
await _async_test_service(
SERVICE_SET_HSV_SCENE,
{ATTR_ENTITY_ID: ENTITY_LIGHT, ATTR_HS_COLOR: [180, 50], ATTR_BRIGHTNESS: 50},
"set_scene",
"async_set_scene",
[SceneClass.HSV, 180, 50, 50],
)
@ -355,7 +367,7 @@ async def test_services(hass: HomeAssistant, caplog):
await _async_test_service(
SERVICE_SET_COLOR_TEMP_SCENE,
{ATTR_ENTITY_ID: ENTITY_LIGHT, ATTR_KELVIN: 4000, ATTR_BRIGHTNESS: 50},
"set_scene",
"async_set_scene",
[SceneClass.CT, 4000, 50],
)
@ -366,14 +378,14 @@ async def test_services(hass: HomeAssistant, caplog):
ATTR_ENTITY_ID: ENTITY_LIGHT,
ATTR_TRANSITIONS: [{YEELIGHT_TEMPERATURE_TRANSACTION: [1900, 2000, 60]}],
},
"set_scene",
"async_set_scene",
)
# set_auto_delay_off_scene
await _async_test_service(
SERVICE_SET_AUTO_DELAY_OFF_SCENE,
{ATTR_ENTITY_ID: ENTITY_LIGHT, ATTR_MINUTES: 1, ATTR_BRIGHTNESS: 50},
"set_scene",
"async_set_scene",
[SceneClass.AUTO_DELAY_OFF, 50, 1],
)
@ -401,6 +413,7 @@ async def test_services(hass: HomeAssistant, caplog):
failure_side_effect=None,
)
# test _cmd wrapper error handler
mocked_bulb.last_properties["power"] = "off"
err_count = len([x for x in caplog.records if x.levelno == logging.ERROR])
type(mocked_bulb).turn_on = MagicMock()
type(mocked_bulb).set_brightness = MagicMock(side_effect=BulbException)
@ -424,8 +437,11 @@ async def test_device_types(hass: HomeAssistant, caplog):
mocked_bulb.last_properties = properties
async def _async_setup(config_entry):
with patch(f"{MODULE}.Bulb", return_value=mocked_bulb):
await hass.config_entries.async_setup(config_entry.entry_id)
with patch(f"{MODULE}.AsyncBulb", return_value=mocked_bulb):
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
# We use asyncio.create_task now to avoid
# blocking starting so we need to block again
await hass.async_block_till_done()
async def _async_test(
@ -447,6 +463,7 @@ async def test_device_types(hass: HomeAssistant, caplog):
await _async_setup(config_entry)
state = hass.states.get(entity_id)
assert state.state == "on"
target_properties["friendly_name"] = name
target_properties["flowing"] = False
@ -481,6 +498,7 @@ async def test_device_types(hass: HomeAssistant, caplog):
await hass.config_entries.async_unload(config_entry.entry_id)
await config_entry.async_remove(hass)
registry.async_clear_config_entry(config_entry.entry_id)
await hass.async_block_till_done()
bright = round(255 * int(PROPERTIES["bright"]) / 100)
current_brightness = round(255 * int(PROPERTIES["current_brightness"]) / 100)
@ -841,7 +859,9 @@ async def test_effects(hass: HomeAssistant):
config_entry.add_to_hass(hass)
mocked_bulb = _mocked_bulb()
with _patch_discovery(MODULE), patch(f"{MODULE}.Bulb", return_value=mocked_bulb):
with _patch_discovery(MODULE), patch(
f"{MODULE}.AsyncBulb", return_value=mocked_bulb
):
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
@ -850,8 +870,8 @@ async def test_effects(hass: HomeAssistant):
) == YEELIGHT_COLOR_EFFECT_LIST + ["mock_effect"]
async def _async_test_effect(name, target=None, called=True):
mocked_start_flow = MagicMock()
type(mocked_bulb).start_flow = mocked_start_flow
async_mocked_start_flow = AsyncMock()
mocked_bulb.async_start_flow = async_mocked_start_flow
await hass.services.async_call(
"light",
SERVICE_TURN_ON,
@ -860,10 +880,10 @@ async def test_effects(hass: HomeAssistant):
)
if not called:
return
mocked_start_flow.assert_called_once()
async_mocked_start_flow.assert_called_once()
if target is None:
return
args, _ = mocked_start_flow.call_args
args, _ = async_mocked_start_flow.call_args
flow = args[0]
assert flow.count == target.count
assert flow.action == target.action