From 72806bfaf2442d4f15e19fe6f13e5010c2425bf6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 28 Jun 2023 01:40:21 -0500 Subject: [PATCH] Add more test coverage for ESPHome lights (#95415) --- .coveragerc | 1 - homeassistant/components/esphome/light.py | 6 - tests/components/esphome/test_light.py | 821 +++++++++++++++++++++- 3 files changed, 817 insertions(+), 11 deletions(-) diff --git a/.coveragerc b/.coveragerc index cd787606432..33a84516165 100644 --- a/.coveragerc +++ b/.coveragerc @@ -310,7 +310,6 @@ omit = homeassistant/components/esphome/camera.py homeassistant/components/esphome/domain_data.py homeassistant/components/esphome/entry_data.py - homeassistant/components/esphome/light.py homeassistant/components/etherscan/sensor.py homeassistant/components/eufy/* homeassistant/components/eufylife_ble/__init__.py diff --git a/homeassistant/components/esphome/light.py b/homeassistant/components/esphome/light.py index aa67a8124fc..1ecc99730bf 100644 --- a/homeassistant/components/esphome/light.py +++ b/homeassistant/components/esphome/light.py @@ -362,12 +362,6 @@ class EsphomeLight(EsphomeEntity[LightInfo, LightState], LightEntity): round(state.warm_white * 255), ) - @property - @esphome_state_property - def color_temp(self) -> int: - """Return the CT color value in mireds.""" - return round(self._state.color_temperature) - @property @esphome_state_property def color_temp_kelvin(self) -> int: diff --git a/tests/components/esphome/test_light.py b/tests/components/esphome/test_light.py index cf43f6c754d..a0998898e75 100644 --- a/tests/components/esphome/test_light.py +++ b/tests/components/esphome/test_light.py @@ -14,7 +14,11 @@ import pytest from homeassistant.components.light import ( ATTR_BRIGHTNESS, + ATTR_COLOR_MODE, ATTR_COLOR_TEMP_KELVIN, + ATTR_EFFECT, + ATTR_EFFECT_LIST, + ATTR_FLASH, ATTR_HS_COLOR, ATTR_MAX_COLOR_TEMP_KELVIN, ATTR_MAX_MIREDS, @@ -23,10 +27,15 @@ from homeassistant.components.light import ( ATTR_RGB_COLOR, ATTR_RGBW_COLOR, ATTR_RGBWW_COLOR, + ATTR_SUPPORTED_COLOR_MODES, + ATTR_TRANSITION, DOMAIN as LIGHT_DOMAIN, + FLASH_LONG, + FLASH_SHORT, SERVICE_TURN_OFF, SERVICE_TURN_ON, STATE_ON, + ColorMode, ) from homeassistant.const import ATTR_ENTITY_ID from homeassistant.core import HomeAssistant @@ -129,6 +138,393 @@ async def test_light_brightness( ) mock_client.light_command.reset_mock() + await hass.services.async_call( + LIGHT_DOMAIN, + SERVICE_TURN_OFF, + {ATTR_ENTITY_ID: "light.test_my_light", ATTR_TRANSITION: 2}, + blocking=True, + ) + mock_client.light_command.assert_has_calls( + [call(key=1, state=False, transition_length=2.0)] + ) + mock_client.light_command.reset_mock() + + await hass.services.async_call( + LIGHT_DOMAIN, + SERVICE_TURN_OFF, + {ATTR_ENTITY_ID: "light.test_my_light", ATTR_FLASH: FLASH_LONG}, + blocking=True, + ) + mock_client.light_command.assert_has_calls( + [call(key=1, state=False, flash_length=10.0)] + ) + mock_client.light_command.reset_mock() + + await hass.services.async_call( + LIGHT_DOMAIN, + SERVICE_TURN_ON, + {ATTR_ENTITY_ID: "light.test_my_light", ATTR_TRANSITION: 2}, + blocking=True, + ) + mock_client.light_command.assert_has_calls( + [ + call( + key=1, + state=True, + transition_length=2.0, + color_mode=LightColorCapability.BRIGHTNESS, + ) + ] + ) + mock_client.light_command.reset_mock() + + await hass.services.async_call( + LIGHT_DOMAIN, + SERVICE_TURN_ON, + {ATTR_ENTITY_ID: "light.test_my_light", ATTR_FLASH: FLASH_SHORT}, + blocking=True, + ) + mock_client.light_command.assert_has_calls( + [ + call( + key=1, + state=True, + flash_length=2.0, + color_mode=LightColorCapability.BRIGHTNESS, + ) + ] + ) + mock_client.light_command.reset_mock() + + +async def test_light_brightness_on_off( + hass: HomeAssistant, mock_client: APIClient, mock_generic_device_entry +) -> None: + """Test a generic light entity that only supports brightness.""" + mock_client.api_version = APIVersion(1, 7) + entity_info = [ + LightInfo( + object_id="mylight", + key=1, + name="my light", + unique_id="my_light", + min_mireds=153, + max_mireds=400, + supported_color_modes=[ + LightColorCapability.ON_OFF | LightColorCapability.BRIGHTNESS + ], + ) + ] + states = [LightState(key=1, state=True, brightness=100)] + user_service = [] + await mock_generic_device_entry( + mock_client=mock_client, + entity_info=entity_info, + user_service=user_service, + states=states, + ) + state = hass.states.get("light.test_my_light") + assert state is not None + assert state.state == STATE_ON + + await hass.services.async_call( + LIGHT_DOMAIN, + SERVICE_TURN_ON, + {ATTR_ENTITY_ID: "light.test_my_light"}, + blocking=True, + ) + mock_client.light_command.assert_has_calls( + [ + call( + key=1, + state=True, + color_mode=LightColorCapability.ON_OFF + | LightColorCapability.BRIGHTNESS, + ) + ] + ) + mock_client.light_command.reset_mock() + + await hass.services.async_call( + LIGHT_DOMAIN, + SERVICE_TURN_ON, + {ATTR_ENTITY_ID: "light.test_my_light", ATTR_BRIGHTNESS: 127}, + blocking=True, + ) + mock_client.light_command.assert_has_calls( + [ + call( + key=1, + state=True, + color_mode=LightColorCapability.ON_OFF + | LightColorCapability.BRIGHTNESS, + brightness=pytest.approx(0.4980392156862745), + ) + ] + ) + mock_client.light_command.reset_mock() + + +async def test_light_legacy_white_converted_to_brightness( + hass: HomeAssistant, mock_client: APIClient, mock_generic_device_entry +) -> None: + """Test a generic light entity that only supports legacy white.""" + mock_client.api_version = APIVersion(1, 7) + entity_info = [ + LightInfo( + object_id="mylight", + key=1, + name="my light", + unique_id="my_light", + min_mireds=153, + max_mireds=400, + supported_color_modes=[ + LightColorCapability.ON_OFF + | LightColorCapability.BRIGHTNESS + | LightColorCapability.WHITE + ], + ) + ] + states = [LightState(key=1, state=True, brightness=100)] + user_service = [] + await mock_generic_device_entry( + mock_client=mock_client, + entity_info=entity_info, + user_service=user_service, + states=states, + ) + state = hass.states.get("light.test_my_light") + assert state is not None + assert state.state == STATE_ON + + await hass.services.async_call( + LIGHT_DOMAIN, + SERVICE_TURN_ON, + {ATTR_ENTITY_ID: "light.test_my_light"}, + blocking=True, + ) + mock_client.light_command.assert_has_calls( + [ + call( + key=1, + state=True, + color_mode=LightColorCapability.ON_OFF + | LightColorCapability.BRIGHTNESS + | LightColorCapability.WHITE, + ) + ] + ) + mock_client.light_command.reset_mock() + + +async def test_light_brightness_on_off_with_unknown_color_mode( + hass: HomeAssistant, mock_client: APIClient, mock_generic_device_entry +) -> None: + """Test a generic light entity that only supports brightness along with an unknown color mode.""" + mock_client.api_version = APIVersion(1, 7) + entity_info = [ + LightInfo( + object_id="mylight", + key=1, + name="my light", + unique_id="my_light", + min_mireds=153, + max_mireds=400, + supported_color_modes=[ + LightColorCapability.ON_OFF | LightColorCapability.BRIGHTNESS | 1 << 8 + ], + ) + ] + states = [LightState(key=1, state=True, brightness=100)] + user_service = [] + await mock_generic_device_entry( + mock_client=mock_client, + entity_info=entity_info, + user_service=user_service, + states=states, + ) + state = hass.states.get("light.test_my_light") + assert state is not None + assert state.state == STATE_ON + + await hass.services.async_call( + LIGHT_DOMAIN, + SERVICE_TURN_ON, + {ATTR_ENTITY_ID: "light.test_my_light"}, + blocking=True, + ) + mock_client.light_command.assert_has_calls( + [ + call( + key=1, + state=True, + color_mode=LightColorCapability.ON_OFF + | LightColorCapability.BRIGHTNESS + | 1 << 8, + ) + ] + ) + mock_client.light_command.reset_mock() + + await hass.services.async_call( + LIGHT_DOMAIN, + SERVICE_TURN_ON, + {ATTR_ENTITY_ID: "light.test_my_light", ATTR_BRIGHTNESS: 127}, + blocking=True, + ) + mock_client.light_command.assert_has_calls( + [ + call( + key=1, + state=True, + color_mode=LightColorCapability.ON_OFF + | LightColorCapability.BRIGHTNESS + | 1 << 8, + brightness=pytest.approx(0.4980392156862745), + ) + ] + ) + mock_client.light_command.reset_mock() + + +async def test_light_on_and_brightness( + hass: HomeAssistant, mock_client: APIClient, mock_generic_device_entry +) -> None: + """Test a generic light entity that supports on and on and brightness.""" + mock_client.api_version = APIVersion(1, 7) + entity_info = [ + LightInfo( + object_id="mylight", + key=1, + name="my light", + unique_id="my_light", + min_mireds=153, + max_mireds=400, + supported_color_modes=[ + LightColorCapability.ON_OFF | LightColorCapability.BRIGHTNESS, + LightColorCapability.ON_OFF, + ], + ) + ] + states = [LightState(key=1, state=True, brightness=100)] + user_service = [] + await mock_generic_device_entry( + mock_client=mock_client, + entity_info=entity_info, + user_service=user_service, + states=states, + ) + state = hass.states.get("light.test_my_light") + assert state is not None + assert state.state == STATE_ON + + await hass.services.async_call( + LIGHT_DOMAIN, + SERVICE_TURN_ON, + {ATTR_ENTITY_ID: "light.test_my_light"}, + blocking=True, + ) + mock_client.light_command.assert_has_calls( + [call(key=1, state=True, color_mode=LightColorCapability.ON_OFF)] + ) + mock_client.light_command.reset_mock() + + +async def test_rgb_color_temp_light( + hass: HomeAssistant, mock_client: APIClient, mock_generic_device_entry +) -> None: + """Test a generic light that supports color temp and RGB.""" + color_modes = [ + LightColorCapability.ON_OFF | LightColorCapability.BRIGHTNESS, + LightColorCapability.ON_OFF + | LightColorCapability.BRIGHTNESS + | LightColorCapability.COLOR_TEMPERATURE, + LightColorCapability.ON_OFF + | LightColorCapability.BRIGHTNESS + | LightColorCapability.RGB, + ] + + mock_client.api_version = APIVersion(1, 7) + entity_info = [ + LightInfo( + object_id="mylight", + key=1, + name="my light", + unique_id="my_light", + min_mireds=153, + max_mireds=400, + supported_color_modes=color_modes, + ) + ] + states = [LightState(key=1, state=True, brightness=100)] + user_service = [] + await mock_generic_device_entry( + mock_client=mock_client, + entity_info=entity_info, + user_service=user_service, + states=states, + ) + state = hass.states.get("light.test_my_light") + assert state is not None + assert state.state == STATE_ON + + await hass.services.async_call( + LIGHT_DOMAIN, + SERVICE_TURN_ON, + {ATTR_ENTITY_ID: "light.test_my_light"}, + blocking=True, + ) + mock_client.light_command.assert_has_calls( + [ + call( + key=1, + state=True, + color_mode=LightColorCapability.ON_OFF + | LightColorCapability.BRIGHTNESS, + ) + ] + ) + mock_client.light_command.reset_mock() + + await hass.services.async_call( + LIGHT_DOMAIN, + SERVICE_TURN_ON, + {ATTR_ENTITY_ID: "light.test_my_light", ATTR_BRIGHTNESS: 127}, + blocking=True, + ) + mock_client.light_command.assert_has_calls( + [ + call( + key=1, + state=True, + color_mode=LightColorCapability.ON_OFF + | LightColorCapability.BRIGHTNESS, + brightness=pytest.approx(0.4980392156862745), + ) + ] + ) + mock_client.light_command.reset_mock() + + await hass.services.async_call( + LIGHT_DOMAIN, + SERVICE_TURN_ON, + {ATTR_ENTITY_ID: "light.test_my_light", ATTR_COLOR_TEMP_KELVIN: 2500}, + blocking=True, + ) + mock_client.light_command.assert_has_calls( + [ + call( + key=1, + state=True, + color_mode=LightColorCapability.ON_OFF + | LightColorCapability.BRIGHTNESS + | LightColorCapability.COLOR_TEMPERATURE, + color_temperature=400, + ) + ] + ) + mock_client.light_command.reset_mock() + async def test_light_rgb( hass: HomeAssistant, mock_client: APIClient, mock_generic_device_entry @@ -266,7 +662,21 @@ async def test_light_rgbw( ], ) ] - states = [LightState(key=1, state=True, brightness=100, red=1, green=1, blue=1)] + states = [ + LightState( + key=1, + state=True, + brightness=100, + red=1, + green=1, + blue=1, + white=1, + color_mode=LightColorCapability.RGB + | LightColorCapability.WHITE + | LightColorCapability.ON_OFF + | LightColorCapability.BRIGHTNESS, + ) + ] user_service = [] await mock_generic_device_entry( mock_client=mock_client, @@ -277,6 +687,8 @@ async def test_light_rgbw( state = hass.states.get("light.test_my_light") assert state is not None assert state.state == STATE_ON + assert state.attributes[ATTR_SUPPORTED_COLOR_MODES] == [ColorMode.RGBW] + assert state.attributes[ATTR_COLOR_MODE] == ColorMode.RGBW await hass.services.async_call( LIGHT_DOMAIN, @@ -394,10 +806,10 @@ async def test_light_rgbw( mock_client.light_command.reset_mock() -async def test_light_rgbww( +async def test_light_rgbww_with_cold_warm_white_support( hass: HomeAssistant, mock_client: APIClient, mock_generic_device_entry ) -> None: - """Test a generic RGBWW light entity.""" + """Test a generic RGBWW light entity with cold warm white support.""" mock_client.api_version = APIVersion(1, 7) entity_info = [ LightInfo( @@ -417,7 +829,25 @@ async def test_light_rgbww( ], ) ] - states = [LightState(key=1, state=True, brightness=100, red=1, green=1, blue=1)] + states = [ + LightState( + key=1, + state=True, + color_brightness=1, + brightness=100, + red=1, + green=1, + blue=1, + warm_white=1, + cold_white=1, + color_mode=LightColorCapability.RGB + | LightColorCapability.WHITE + | LightColorCapability.COLOR_TEMPERATURE + | LightColorCapability.COLD_WARM_WHITE + | LightColorCapability.ON_OFF + | LightColorCapability.BRIGHTNESS, + ) + ] user_service = [] await mock_generic_device_entry( mock_client=mock_client, @@ -428,6 +858,9 @@ async def test_light_rgbww( state = hass.states.get("light.test_my_light") assert state is not None assert state.state == STATE_ON + assert state.attributes[ATTR_SUPPORTED_COLOR_MODES] == [ColorMode.RGBWW] + assert state.attributes[ATTR_COLOR_MODE] == ColorMode.RGBWW + assert state.attributes[ATTR_RGBWW_COLOR] == (255, 255, 255, 255, 255) await hass.services.async_call( LIGHT_DOMAIN, @@ -613,6 +1046,236 @@ async def test_light_rgbww( mock_client.light_command.reset_mock() +async def test_light_rgbww_without_cold_warm_white_support( + hass: HomeAssistant, mock_client: APIClient, mock_generic_device_entry +) -> None: + """Test a generic RGBWW light entity without cold warm white support.""" + mock_client.api_version = APIVersion(1, 7) + entity_info = [ + LightInfo( + object_id="mylight", + key=1, + name="my light", + unique_id="my_light", + min_mireds=153, + max_mireds=400, + supported_color_modes=[ + LightColorCapability.RGB + | LightColorCapability.WHITE + | LightColorCapability.COLOR_TEMPERATURE + | LightColorCapability.ON_OFF + | LightColorCapability.BRIGHTNESS + ], + ) + ] + states = [ + LightState( + key=1, + state=True, + color_brightness=1, + brightness=100, + red=1, + green=1, + blue=1, + white=1, + color_mode=LightColorCapability.RGB + | LightColorCapability.WHITE + | LightColorCapability.COLOR_TEMPERATURE + | LightColorCapability.ON_OFF + | LightColorCapability.BRIGHTNESS, + ) + ] + user_service = [] + await mock_generic_device_entry( + mock_client=mock_client, + entity_info=entity_info, + user_service=user_service, + states=states, + ) + state = hass.states.get("light.test_my_light") + assert state is not None + assert state.state == STATE_ON + assert state.attributes[ATTR_SUPPORTED_COLOR_MODES] == [ColorMode.RGBWW] + assert state.attributes[ATTR_COLOR_MODE] == ColorMode.RGBWW + assert state.attributes[ATTR_RGBWW_COLOR] == (255, 255, 255, 255, 0) + + await hass.services.async_call( + LIGHT_DOMAIN, + SERVICE_TURN_ON, + {ATTR_ENTITY_ID: "light.test_my_light"}, + blocking=True, + ) + mock_client.light_command.assert_has_calls( + [ + call( + key=1, + state=True, + color_mode=LightColorCapability.RGB + | LightColorCapability.WHITE + | LightColorCapability.COLOR_TEMPERATURE + | LightColorCapability.ON_OFF + | LightColorCapability.BRIGHTNESS, + ) + ] + ) + mock_client.light_command.reset_mock() + + await hass.services.async_call( + LIGHT_DOMAIN, + SERVICE_TURN_ON, + {ATTR_ENTITY_ID: "light.test_my_light", ATTR_BRIGHTNESS: 127}, + blocking=True, + ) + mock_client.light_command.assert_has_calls( + [ + call( + key=1, + state=True, + color_mode=LightColorCapability.RGB + | LightColorCapability.WHITE + | LightColorCapability.COLOR_TEMPERATURE + | LightColorCapability.ON_OFF + | LightColorCapability.BRIGHTNESS, + brightness=pytest.approx(0.4980392156862745), + ) + ] + ) + mock_client.light_command.reset_mock() + + await hass.services.async_call( + LIGHT_DOMAIN, + SERVICE_TURN_ON, + { + ATTR_ENTITY_ID: "light.test_my_light", + ATTR_BRIGHTNESS: 127, + ATTR_HS_COLOR: (100, 100), + }, + blocking=True, + ) + mock_client.light_command.assert_has_calls( + [ + call( + key=1, + state=True, + color_brightness=1.0, + color_mode=LightColorCapability.RGB + | LightColorCapability.WHITE + | LightColorCapability.COLOR_TEMPERATURE + | LightColorCapability.ON_OFF + | LightColorCapability.BRIGHTNESS, + white=0, + rgb=(pytest.approx(0.32941176470588235), 1.0, 0.0), + brightness=pytest.approx(0.4980392156862745), + ) + ] + ) + + mock_client.light_command.reset_mock() + + await hass.services.async_call( + LIGHT_DOMAIN, + SERVICE_TURN_ON, + {ATTR_ENTITY_ID: "light.test_my_light", ATTR_RGB_COLOR: (255, 255, 255)}, + blocking=True, + ) + mock_client.light_command.assert_has_calls( + [ + call( + key=1, + state=True, + color_brightness=pytest.approx(0.4235294117647059), + color_temperature=276.5, + white=1, + color_mode=LightColorCapability.RGB + | LightColorCapability.WHITE + | LightColorCapability.COLOR_TEMPERATURE + | LightColorCapability.ON_OFF + | LightColorCapability.BRIGHTNESS, + rgb=(0, pytest.approx(0.5462962962962963), 1.0), + ) + ] + ) + mock_client.light_command.reset_mock() + + await hass.services.async_call( + LIGHT_DOMAIN, + SERVICE_TURN_ON, + {ATTR_ENTITY_ID: "light.test_my_light", ATTR_RGBW_COLOR: (255, 255, 255, 255)}, + blocking=True, + ) + mock_client.light_command.assert_has_calls( + [ + call( + key=1, + state=True, + color_brightness=pytest.approx(0.4235294117647059), + white=1, + color_temperature=276.5, + color_mode=LightColorCapability.RGB + | LightColorCapability.WHITE + | LightColorCapability.COLOR_TEMPERATURE + | LightColorCapability.ON_OFF + | LightColorCapability.BRIGHTNESS, + rgb=(0, pytest.approx(0.5462962962962963), 1.0), + ) + ] + ) + mock_client.light_command.reset_mock() + + await hass.services.async_call( + LIGHT_DOMAIN, + SERVICE_TURN_ON, + { + ATTR_ENTITY_ID: "light.test_my_light", + ATTR_RGBWW_COLOR: (255, 255, 255, 255, 255), + }, + blocking=True, + ) + mock_client.light_command.assert_has_calls( + [ + call( + key=1, + state=True, + color_brightness=1, + white=1, + color_temperature=276.5, + color_mode=LightColorCapability.RGB + | LightColorCapability.WHITE + | LightColorCapability.COLOR_TEMPERATURE + | LightColorCapability.ON_OFF + | LightColorCapability.BRIGHTNESS, + rgb=(1, 1, 1), + ) + ] + ) + mock_client.light_command.reset_mock() + + await hass.services.async_call( + LIGHT_DOMAIN, + SERVICE_TURN_ON, + {ATTR_ENTITY_ID: "light.test_my_light", ATTR_COLOR_TEMP_KELVIN: 2500}, + blocking=True, + ) + mock_client.light_command.assert_has_calls( + [ + call( + key=1, + state=True, + color_brightness=0, + white=100, + color_temperature=400.0, + color_mode=LightColorCapability.RGB + | LightColorCapability.WHITE + | LightColorCapability.COLOR_TEMPERATURE + | LightColorCapability.ON_OFF + | LightColorCapability.BRIGHTNESS, + rgb=(0, 0, 0), + ) + ] + ) + mock_client.light_command.reset_mock() + + async def test_light_color_temp( hass: HomeAssistant, mock_client: APIClient, mock_generic_device_entry ) -> None: @@ -831,6 +1494,8 @@ async def test_light_color_temp_legacy( assert state.state == STATE_ON attributes = state.attributes + assert attributes[ATTR_COLOR_MODE] == ColorMode.COLOR_TEMP + assert attributes[ATTR_SUPPORTED_COLOR_MODES] == [ColorMode.COLOR_TEMP] assert attributes[ATTR_MIN_MIREDS] == 153 assert attributes[ATTR_MAX_MIREDS] == 370 @@ -863,3 +1528,151 @@ async def test_light_color_temp_legacy( ) mock_client.light_command.assert_has_calls([call(key=1, state=False)]) mock_client.light_command.reset_mock() + + +async def test_light_rgb_legacy( + hass: HomeAssistant, mock_client: APIClient, mock_generic_device_entry +) -> None: + """Test a legacy light entity that supports rgb.""" + mock_client.api_version = APIVersion(1, 5) + entity_info = [ + LightInfo( + object_id="mylight", + key=1, + name="my light", + unique_id="my_light", + min_mireds=153.846161, + max_mireds=370.370361, + supported_color_modes=[ + LightColorCapability.COLOR_TEMPERATURE + | LightColorCapability.ON_OFF + | LightColorCapability.BRIGHTNESS + | LightColorCapability.RGB + ], + legacy_supports_brightness=True, + legacy_supports_color_temperature=True, + legacy_supports_rgb=True, + ) + ] + states = [ + LightState( + key=1, + state=True, + brightness=100, + red=1, + green=1, + blue=1, + color_mode=LightColorCapability.COLOR_TEMPERATURE + | LightColorCapability.ON_OFF + | LightColorCapability.BRIGHTNESS + | LightColorCapability.RGB, + ) + ] + user_service = [] + await mock_generic_device_entry( + mock_client=mock_client, + entity_info=entity_info, + user_service=user_service, + states=states, + ) + state = hass.states.get("light.test_my_light") + assert state is not None + assert state.state == STATE_ON + attributes = state.attributes + assert attributes[ATTR_SUPPORTED_COLOR_MODES] == [ColorMode.RGB] + assert attributes[ATTR_COLOR_MODE] == ColorMode.RGB + + await hass.services.async_call( + LIGHT_DOMAIN, + SERVICE_TURN_ON, + {ATTR_ENTITY_ID: "light.test_my_light"}, + blocking=True, + ) + mock_client.light_command.assert_has_calls( + [ + call( + key=1, + state=True, + ) + ] + ) + mock_client.light_command.reset_mock() + + await hass.services.async_call( + LIGHT_DOMAIN, + SERVICE_TURN_OFF, + {ATTR_ENTITY_ID: "light.test_my_light"}, + blocking=True, + ) + mock_client.light_command.assert_has_calls([call(key=1, state=False)]) + mock_client.light_command.reset_mock() + + await hass.services.async_call( + LIGHT_DOMAIN, + SERVICE_TURN_ON, + {ATTR_ENTITY_ID: "light.test_my_light", ATTR_RGB_COLOR: (255, 255, 255)}, + blocking=True, + ) + mock_client.light_command.assert_has_calls( + [ + call( + key=1, + state=True, + rgb=(1.0, 1.0, 1.0), + color_brightness=1.0, + ) + ] + ) + mock_client.light_command.reset_mock() + + +async def test_light_effects( + hass: HomeAssistant, mock_client: APIClient, mock_generic_device_entry +) -> None: + """Test a generic light entity that supports on and on and brightness.""" + mock_client.api_version = APIVersion(1, 7) + entity_info = [ + LightInfo( + object_id="mylight", + key=1, + name="my light", + unique_id="my_light", + min_mireds=153, + max_mireds=400, + effects=["effect1", "effect2"], + supported_color_modes=[ + LightColorCapability.ON_OFF | LightColorCapability.BRIGHTNESS, + ], + ) + ] + states = [LightState(key=1, state=True, brightness=100)] + user_service = [] + await mock_generic_device_entry( + mock_client=mock_client, + entity_info=entity_info, + user_service=user_service, + states=states, + ) + state = hass.states.get("light.test_my_light") + assert state is not None + assert state.state == STATE_ON + assert state.attributes[ATTR_EFFECT_LIST] == ["effect1", "effect2"] + + await hass.services.async_call( + LIGHT_DOMAIN, + SERVICE_TURN_ON, + {ATTR_ENTITY_ID: "light.test_my_light", ATTR_EFFECT: "effect1"}, + blocking=True, + ) + mock_client.light_command.assert_has_calls( + [ + call( + key=1, + state=True, + color_mode=LightColorCapability.ON_OFF + | LightColorCapability.BRIGHTNESS, + effect="effect1", + ) + ] + ) + mock_client.light_command.reset_mock()