core/tests/components/wled/test_light.py

399 lines
12 KiB
Python
Raw Normal View History

"""Tests for the WLED light platform."""
import json
from unittest.mock import MagicMock
import pytest
from wled import Device as WLEDDevice, WLEDConnectionError, WLEDError
from homeassistant.components.light import (
ATTR_BRIGHTNESS,
ATTR_EFFECT,
ATTR_HS_COLOR,
ATTR_RGB_COLOR,
ATTR_RGBW_COLOR,
ATTR_TRANSITION,
DOMAIN as LIGHT_DOMAIN,
)
2021-11-29 14:15:50 +00:00
from homeassistant.components.wled.const import CONF_KEEP_MASTER_LIGHT, SCAN_INTERVAL
from homeassistant.const import (
ATTR_ENTITY_ID,
ATTR_ICON,
SERVICE_TURN_OFF,
SERVICE_TURN_ON,
STATE_OFF,
STATE_ON,
STATE_UNAVAILABLE,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
import homeassistant.util.dt as dt_util
from tests.common import MockConfigEntry, async_fire_time_changed, load_fixture
async def test_rgb_light_state(
hass: HomeAssistant, init_integration: MockConfigEntry
) -> None:
"""Test the creation and values of the WLED lights."""
entity_registry = er.async_get(hass)
# First segment of the strip
state = hass.states.get("light.wled_rgb_light")
assert state
assert state.attributes.get(ATTR_BRIGHTNESS) == 127
assert state.attributes.get(ATTR_EFFECT) == "Solid"
assert state.attributes.get(ATTR_HS_COLOR) == (37.412, 100.0)
assert state.attributes.get(ATTR_ICON) == "mdi:led-strip-variant"
assert state.state == STATE_ON
entry = entity_registry.async_get("light.wled_rgb_light")
assert entry
assert entry.unique_id == "aabbccddeeff_0"
# Second segment of the strip
state = hass.states.get("light.wled_rgb_light_segment_1")
assert state
assert state.attributes.get(ATTR_BRIGHTNESS) == 127
assert state.attributes.get(ATTR_EFFECT) == "Blink"
assert state.attributes.get(ATTR_HS_COLOR) == (148.941, 100.0)
assert state.attributes.get(ATTR_ICON) == "mdi:led-strip-variant"
assert state.state == STATE_ON
entry = entity_registry.async_get("light.wled_rgb_light_segment_1")
assert entry
assert entry.unique_id == "aabbccddeeff_1"
# Test master control of the lightstrip
state = hass.states.get("light.wled_rgb_light_master")
assert state
assert state.attributes.get(ATTR_BRIGHTNESS) == 127
assert state.state == STATE_ON
entry = entity_registry.async_get("light.wled_rgb_light_master")
assert entry
assert entry.unique_id == "aabbccddeeff"
async def test_segment_change_state(
hass: HomeAssistant,
init_integration: MockConfigEntry,
mock_wled: MagicMock,
) -> None:
"""Test the change of state of the WLED segments."""
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: "light.wled_rgb_light", ATTR_TRANSITION: 5},
blocking=True,
)
await hass.async_block_till_done()
assert mock_wled.segment.call_count == 1
mock_wled.segment.assert_called_with(
on=False,
segment_id=0,
transition=50,
)
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_ON,
{
ATTR_BRIGHTNESS: 42,
ATTR_EFFECT: "Chase",
ATTR_ENTITY_ID: "light.wled_rgb_light",
ATTR_RGB_COLOR: [255, 0, 0],
ATTR_TRANSITION: 5,
},
blocking=True,
)
await hass.async_block_till_done()
assert mock_wled.segment.call_count == 2
mock_wled.segment.assert_called_with(
brightness=42,
color_primary=(255, 0, 0),
effect="Chase",
on=True,
segment_id=0,
transition=50,
)
async def test_master_change_state(
hass: HomeAssistant,
init_integration: MockConfigEntry,
mock_wled: MagicMock,
) -> None:
"""Test the change of state of the WLED master light control."""
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: "light.wled_rgb_light_master", ATTR_TRANSITION: 5},
blocking=True,
)
await hass.async_block_till_done()
assert mock_wled.master.call_count == 1
mock_wled.master.assert_called_with(
on=False,
transition=50,
)
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_ON,
{
ATTR_BRIGHTNESS: 42,
ATTR_ENTITY_ID: "light.wled_rgb_light_master",
ATTR_TRANSITION: 5,
},
blocking=True,
)
await hass.async_block_till_done()
assert mock_wled.master.call_count == 2
mock_wled.master.assert_called_with(
brightness=42,
on=True,
transition=50,
)
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: "light.wled_rgb_light_master", ATTR_TRANSITION: 5},
blocking=True,
)
await hass.async_block_till_done()
assert mock_wled.master.call_count == 3
mock_wled.master.assert_called_with(
on=False,
transition=50,
)
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_ON,
{
ATTR_BRIGHTNESS: 42,
ATTR_ENTITY_ID: "light.wled_rgb_light_master",
ATTR_TRANSITION: 5,
},
blocking=True,
)
await hass.async_block_till_done()
assert mock_wled.master.call_count == 4
mock_wled.master.assert_called_with(
brightness=42,
on=True,
transition=50,
)
@pytest.mark.parametrize("mock_wled", ["wled/rgb_single_segment.json"], indirect=True)
async def test_dynamically_handle_segments(
hass: HomeAssistant,
init_integration: MockConfigEntry,
mock_wled: MagicMock,
) -> None:
"""Test if a new/deleted segment is dynamically added/removed."""
master = hass.states.get("light.wled_rgb_light_master")
segment0 = hass.states.get("light.wled_rgb_light")
segment1 = hass.states.get("light.wled_rgb_light_segment_1")
assert segment0
assert segment0.state == STATE_ON
assert not master
assert not segment1
return_value = mock_wled.update.return_value
mock_wled.update.return_value = WLEDDevice(
json.loads(load_fixture("wled/rgb.json"))
)
async_fire_time_changed(hass, dt_util.utcnow() + SCAN_INTERVAL)
await hass.async_block_till_done()
master = hass.states.get("light.wled_rgb_light_master")
segment0 = hass.states.get("light.wled_rgb_light")
segment1 = hass.states.get("light.wled_rgb_light_segment_1")
assert master
assert master.state == STATE_ON
assert segment0
assert segment0.state == STATE_ON
assert segment1
assert segment1.state == STATE_ON
# Test adding if segment shows up again, including the master entity
mock_wled.update.return_value = return_value
async_fire_time_changed(hass, dt_util.utcnow() + SCAN_INTERVAL)
await hass.async_block_till_done()
master = hass.states.get("light.wled_rgb_light_master")
segment0 = hass.states.get("light.wled_rgb_light")
segment1 = hass.states.get("light.wled_rgb_light_segment_1")
assert master
assert master.state == STATE_UNAVAILABLE
assert segment0
assert segment0.state == STATE_ON
assert segment1
assert segment1.state == STATE_UNAVAILABLE
@pytest.mark.parametrize("mock_wled", ["wled/rgb_single_segment.json"], indirect=True)
async def test_single_segment_behavior(
hass: HomeAssistant,
init_integration: MockConfigEntry,
mock_wled: MagicMock,
) -> None:
"""Test the behavior of the integration with a single segment."""
device = mock_wled.update.return_value
assert not hass.states.get("light.wled_rgb_light_master")
state = hass.states.get("light.wled_rgb_light")
assert state
assert state.state == STATE_ON
# Test segment brightness takes master into account
device.state.brightness = 100
device.state.segments[0].brightness = 255
async_fire_time_changed(hass, dt_util.utcnow() + SCAN_INTERVAL)
await hass.async_block_till_done()
state = hass.states.get("light.wled_rgb_light")
assert state
assert state.attributes.get(ATTR_BRIGHTNESS) == 100
# Test segment is off when master is off
device.state.on = False
async_fire_time_changed(hass, dt_util.utcnow() + SCAN_INTERVAL)
await hass.async_block_till_done()
state = hass.states.get("light.wled_rgb_light")
assert state
assert state.state == STATE_OFF
# Test master is turned off when turning off a single segment
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: "light.wled_rgb_light", ATTR_TRANSITION: 5},
blocking=True,
)
await hass.async_block_till_done()
assert mock_wled.master.call_count == 1
mock_wled.master.assert_called_with(
on=False,
transition=50,
)
# Test master is turned on when turning on a single segment, and segment
# brightness is set to 255.
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_ON,
{
ATTR_ENTITY_ID: "light.wled_rgb_light",
ATTR_TRANSITION: 5,
ATTR_BRIGHTNESS: 42,
},
blocking=True,
)
await hass.async_block_till_done()
assert mock_wled.segment.call_count == 1
assert mock_wled.master.call_count == 2
mock_wled.segment.assert_called_with(on=True, segment_id=0, brightness=255)
mock_wled.master.assert_called_with(on=True, transition=50, brightness=42)
async def test_light_error(
hass: HomeAssistant,
init_integration: MockConfigEntry,
mock_wled: MagicMock,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test error handling of the WLED lights."""
mock_wled.segment.side_effect = WLEDError
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: "light.wled_rgb_light"},
blocking=True,
)
await hass.async_block_till_done()
state = hass.states.get("light.wled_rgb_light")
assert state
assert state.state == STATE_ON
assert "Invalid response from API" in caplog.text
assert mock_wled.segment.call_count == 1
2021-06-19 15:13:48 +00:00
mock_wled.segment.assert_called_with(on=False, segment_id=0, transition=None)
async def test_light_connection_error(
hass: HomeAssistant,
init_integration: MockConfigEntry,
mock_wled: MagicMock,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test error handling of the WLED switches."""
mock_wled.segment.side_effect = WLEDConnectionError
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: "light.wled_rgb_light"},
blocking=True,
)
await hass.async_block_till_done()
state = hass.states.get("light.wled_rgb_light")
assert state
assert state.state == STATE_UNAVAILABLE
assert "Error communicating with API" in caplog.text
assert mock_wled.segment.call_count == 1
2021-06-19 15:13:48 +00:00
mock_wled.segment.assert_called_with(on=False, segment_id=0, transition=None)
@pytest.mark.parametrize("mock_wled", ["wled/rgbw.json"], indirect=True)
async def test_rgbw_light(
hass: HomeAssistant, init_integration: MockConfigEntry, mock_wled: MagicMock
) -> None:
"""Test RGBW support for WLED."""
state = hass.states.get("light.wled_rgbw_light")
assert state
assert state.state == STATE_ON
assert state.attributes.get(ATTR_RGBW_COLOR) == (255, 0, 0, 139)
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_ON,
{
ATTR_ENTITY_ID: "light.wled_rgbw_light",
ATTR_RGBW_COLOR: (255, 255, 255, 255),
},
blocking=True,
)
await hass.async_block_till_done()
assert mock_wled.segment.call_count == 1
mock_wled.segment.assert_called_with(
color_primary=(255, 255, 255, 255),
on=True,
segment_id=0,
)
@pytest.mark.parametrize("mock_wled", ["wled/rgb_single_segment.json"], indirect=True)
async def test_single_segment_with_keep_master_light(
hass: HomeAssistant,
init_integration: MockConfigEntry,
mock_wled: MagicMock,
) -> None:
"""Test the behavior of the integration with a single segment."""
assert not hass.states.get("light.wled_rgb_light_master")
hass.config_entries.async_update_entry(
init_integration, options={CONF_KEEP_MASTER_LIGHT: True}
)
await hass.async_block_till_done()
state = hass.states.get("light.wled_rgb_light_master")
assert state
assert state.state == STATE_ON