from __future__ import annotations from itertools import chain import pytest from pytest_mock import MockerFixture from kasa import Device, Feature, Module from kasa.smart.modules import LightEffect, LightStripEffect from ...device_fixtures import parametrize light_strip_effect = parametrize( "has light strip effect", component_filter="light_strip_lighting_effect", protocol_filter={"SMART"}, ) @light_strip_effect async def test_light_strip_effect(dev: Device, mocker: MockerFixture): """Test light strip effect.""" light_effect = dev.modules.get(Module.LightEffect) assert isinstance(light_effect, LightStripEffect) brightness = dev.modules[Module.Brightness] feature = dev.features["light_effect"] assert feature.type == Feature.Type.Choice call = mocker.spy(light_effect, "call") assert feature.choices == light_effect.effect_list assert feature.choices for effect in chain(reversed(feature.choices), feature.choices): if effect == LightEffect.LIGHT_EFFECTS_OFF: off_effect = ( light_effect.effect if light_effect.effect in light_effect._effect_mapping else "Aurora" ) await light_effect.set_effect(effect) if effect != LightEffect.LIGHT_EFFECTS_OFF: params = {**light_effect._effect_mapping[effect]} else: params = {**light_effect._effect_mapping[off_effect]} params["enable"] = 0 params["brightness"] = brightness.brightness # use the existing brightness call.assert_called_with("set_lighting_effect", params) await dev.update() assert light_effect.effect == effect assert feature.value == effect with pytest.raises(ValueError, match="The effect foobar is not a built in effect"): await light_effect.set_effect("foobar") @light_strip_effect @pytest.mark.parametrize("effect_active", [True, False]) async def test_light_effect_brightness( dev: Device, effect_active: bool, mocker: MockerFixture ): """Test that light module uses light_effect for brightness when active.""" light_module = dev.modules[Module.Light] light_effect = dev.modules[Module.SmartLightEffect] light_effect_set_brightness = mocker.spy(light_effect, "set_brightness") mock_light_effect_call = mocker.patch.object(light_effect, "call") brightness = dev.modules[Module.Brightness] brightness_set_brightness = mocker.spy(brightness, "set_brightness") mock_brightness_call = mocker.patch.object(brightness, "call") mocker.patch.object( type(light_effect), "is_active", new_callable=mocker.PropertyMock, return_value=effect_active, ) await light_module.set_brightness(10) if effect_active: assert light_effect.is_active assert light_effect.brightness == light_module.brightness light_effect_set_brightness.assert_called_with(10) mock_light_effect_call.assert_called_with( "set_lighting_effect", {"brightness": 10, "bAdjusted": True} ) else: assert not light_effect.is_active brightness_set_brightness.assert_called_with(10) mock_brightness_call.assert_called_with("set_device_info", {"brightness": 10})