core/tests/components/wled/test_switch.py

166 lines
5.2 KiB
Python
Raw Normal View History

"""Tests for the WLED switch platform."""
import json
from unittest.mock import MagicMock
2021-01-01 21:31:56 +00:00
import pytest
2023-03-06 00:46:53 +00:00
from syrupy.assertion import SnapshotAssertion
from wled import Device as WLEDDevice, WLEDConnectionError, WLEDError
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
2023-03-06 00:46:53 +00:00
from homeassistant.components.wled.const import SCAN_INTERVAL
from homeassistant.const import (
ATTR_ENTITY_ID,
SERVICE_TURN_OFF,
SERVICE_TURN_ON,
STATE_OFF,
STATE_ON,
STATE_UNAVAILABLE,
)
from homeassistant.core import HomeAssistant
2022-05-24 14:30:41 +00:00
from homeassistant.exceptions import HomeAssistantError
2023-03-06 00:46:53 +00:00
from homeassistant.helpers import device_registry as dr, entity_registry as er
import homeassistant.util.dt as dt_util
2023-02-20 12:00:02 +00:00
from tests.common import async_fire_time_changed, load_fixture
pytestmark = pytest.mark.usefixtures("init_integration")
2023-03-06 00:46:53 +00:00
@pytest.mark.parametrize(
("entity_id", "method", "called_with_on", "called_with_off"),
[
(
"switch.wled_rgb_light_nightlight",
"nightlight",
{"on": True},
{"on": False},
),
(
"switch.wled_rgb_light_reverse",
"segment",
{"segment_id": 0, "reverse": True},
{"segment_id": 0, "reverse": False},
),
(
"switch.wled_rgb_light_sync_receive",
"sync",
{"receive": True},
{"receive": False},
),
(
"switch.wled_rgb_light_sync_send",
"sync",
{"send": True},
{"send": False},
),
],
)
async def test_switch_state(
2023-03-06 00:46:53 +00:00
hass: HomeAssistant,
device_registry: dr.DeviceRegistry,
entity_registry: er.EntityRegistry,
snapshot: SnapshotAssertion,
mock_wled: MagicMock,
entity_id: str,
method: str,
called_with_on: dict[str, bool | int],
called_with_off: dict[str, bool | int],
) -> None:
"""Test the creation and values of the WLED switches."""
2023-03-06 00:46:53 +00:00
assert (state := hass.states.get(entity_id))
assert state == snapshot
2023-03-06 00:46:53 +00:00
assert (entity_entry := entity_registry.async_get(state.entity_id))
assert entity_entry == snapshot
2023-03-06 00:46:53 +00:00
assert entity_entry.device_id
assert (device_entry := device_registry.async_get(entity_entry.device_id))
assert device_entry == snapshot
2023-03-06 00:46:53 +00:00
# Test on/off services
method_mock = getattr(mock_wled, method)
await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_ON,
2023-03-06 00:46:53 +00:00
{ATTR_ENTITY_ID: state.entity_id},
blocking=True,
)
2023-03-06 00:46:53 +00:00
assert method_mock.call_count == 1
method_mock.assert_called_with(**called_with_on)
await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_OFF,
2023-03-06 00:46:53 +00:00
{ATTR_ENTITY_ID: state.entity_id},
blocking=True,
)
2023-03-06 00:46:53 +00:00
assert method_mock.call_count == 2
method_mock.assert_called_with(**called_with_off)
2023-03-06 00:46:53 +00:00
# Test invalid response, not becoming unavailable
method_mock.side_effect = WLEDError
2022-05-24 14:30:41 +00:00
with pytest.raises(HomeAssistantError, match="Invalid response from WLED API"):
await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_ON,
2023-03-06 00:46:53 +00:00
{ATTR_ENTITY_ID: state.entity_id},
2022-05-24 14:30:41 +00:00
blocking=True,
)
2023-03-06 00:46:53 +00:00
assert method_mock.call_count == 3
assert (state := hass.states.get(state.entity_id))
assert state.state != STATE_UNAVAILABLE
2023-03-06 00:46:53 +00:00
# Test connection error, leading to becoming unavailable
method_mock.side_effect = WLEDConnectionError
2022-05-24 14:30:41 +00:00
with pytest.raises(HomeAssistantError, match="Error communicating with WLED API"):
await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_ON,
2023-03-06 00:46:53 +00:00
{ATTR_ENTITY_ID: state.entity_id},
2022-05-24 14:30:41 +00:00
blocking=True,
)
2023-03-06 00:46:53 +00:00
assert method_mock.call_count == 4
assert (state := hass.states.get(state.entity_id))
assert state.state == STATE_UNAVAILABLE
2023-02-20 12:00:02 +00:00
@pytest.mark.parametrize("device_fixture", ["rgb_single_segment"])
async def test_switch_dynamically_handle_segments(
hass: HomeAssistant,
mock_wled: MagicMock,
) -> None:
"""Test if a new/deleted segment is dynamically added/removed."""
2023-03-06 00:46:53 +00:00
assert (segment0 := hass.states.get("switch.wled_rgb_light_reverse"))
assert segment0.state == STATE_OFF
2023-03-06 00:46:53 +00:00
assert not hass.states.get("switch.wled_rgb_light_segment_1_reverse")
# Test adding a segment dynamically...
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()
2023-03-06 00:46:53 +00:00
assert (segment0 := hass.states.get("switch.wled_rgb_light_reverse"))
assert segment0.state == STATE_OFF
2023-03-06 00:46:53 +00:00
assert (segment1 := hass.states.get("switch.wled_rgb_light_segment_1_reverse"))
assert segment1.state == STATE_ON
# Test remove segment again...
mock_wled.update.return_value = return_value
async_fire_time_changed(hass, dt_util.utcnow() + SCAN_INTERVAL)
await hass.async_block_till_done()
2023-03-06 00:46:53 +00:00
assert (segment0 := hass.states.get("switch.wled_rgb_light_reverse"))
assert segment0.state == STATE_OFF
2023-03-06 00:46:53 +00:00
assert (segment1 := hass.states.get("switch.wled_rgb_light_segment_1_reverse"))
assert segment1.state == STATE_UNAVAILABLE