core/tests/components/tradfri/test_light.py

311 lines
7.9 KiB
Python

"""Tradfri lights platform tests."""
from typing import Any
import pytest
from pytradfri.const import ATTR_DEVICE_STATE, ATTR_LIGHT_CONTROL, ATTR_REACHABLE_STATE
from pytradfri.device import Device
from homeassistant.components.light import (
ATTR_BRIGHTNESS,
ATTR_COLOR_MODE,
ATTR_COLOR_TEMP,
ATTR_HS_COLOR,
ATTR_MAX_MIREDS,
ATTR_MIN_MIREDS,
ATTR_SUPPORTED_COLOR_MODES,
DOMAIN as LIGHT_DOMAIN,
ColorMode,
)
from homeassistant.components.tradfri.const import DOMAIN
from homeassistant.const import (
SERVICE_TURN_OFF,
SERVICE_TURN_ON,
STATE_OFF,
STATE_ON,
STATE_UNAVAILABLE,
)
from homeassistant.core import HomeAssistant
from .common import CommandStore, setup_integration
from tests.common import load_fixture
@pytest.fixture(scope="module")
def bulb_w() -> str:
"""Return a bulb W response."""
return load_fixture("bulb_w.json", DOMAIN)
@pytest.fixture(scope="module")
def bulb_ws() -> str:
"""Return a bulb WS response."""
return load_fixture("bulb_ws.json", DOMAIN)
@pytest.fixture(scope="module")
def bulb_cws() -> str:
"""Return a bulb CWS response."""
return load_fixture("bulb_cws.json", DOMAIN)
@pytest.mark.parametrize(
("device", "entity_id", "state_attributes"),
[
(
"bulb_w",
"light.test_w",
{
ATTR_BRIGHTNESS: 250,
ATTR_SUPPORTED_COLOR_MODES: [ColorMode.BRIGHTNESS],
ATTR_COLOR_MODE: ColorMode.BRIGHTNESS,
},
),
(
"bulb_ws",
"light.test_ws",
{
ATTR_BRIGHTNESS: 250,
ATTR_COLOR_TEMP: 400,
ATTR_MIN_MIREDS: 250,
ATTR_MAX_MIREDS: 454,
ATTR_SUPPORTED_COLOR_MODES: [ColorMode.COLOR_TEMP],
ATTR_COLOR_MODE: ColorMode.COLOR_TEMP,
},
),
(
"bulb_cws",
"light.test_cws",
{
ATTR_BRIGHTNESS: 250,
ATTR_HS_COLOR: (29.812, 65.252),
ATTR_SUPPORTED_COLOR_MODES: [ColorMode.HS],
ATTR_COLOR_MODE: ColorMode.HS,
},
),
],
indirect=["device"],
)
async def test_light_state(
hass: HomeAssistant,
device: Device,
entity_id: str,
state_attributes: dict[str, Any],
) -> None:
"""Test light state."""
await setup_integration(hass)
state = hass.states.get(entity_id)
assert state
assert state.state == STATE_ON
for key, value in state_attributes.items():
assert state.attributes[key] == value
@pytest.mark.parametrize("device", ["bulb_w"], indirect=True)
async def test_light_available(
hass: HomeAssistant,
command_store: CommandStore,
device: Device,
) -> None:
"""Test light available property."""
entity_id = "light.test_w"
await setup_integration(hass)
state = hass.states.get(entity_id)
assert state
assert state.state == STATE_ON
await command_store.trigger_observe_callback(
hass, device, {ATTR_REACHABLE_STATE: 0}
)
state = hass.states.get(entity_id)
assert state
assert state.state == STATE_UNAVAILABLE
@pytest.mark.parametrize(
"transition",
[{}, {"transition": 0}, {"transition": 1}],
ids=["transition_none", "transition_0", "transition_1"],
)
@pytest.mark.parametrize(
("device", "entity_id", "service_data", "state_attributes"),
[
# turn_on
(
"bulb_w",
"light.test_w",
{},
{},
),
# brightness > 0
(
"bulb_w",
"light.test_w",
{"brightness": 100},
{"brightness": 100},
),
# brightness == 1
(
"bulb_w",
"light.test_w",
{"brightness": 1},
{"brightness": 1},
),
# brightness > 254
(
"bulb_w",
"light.test_w",
{"brightness": 1000},
{"brightness": 254},
),
# color_temp
(
"bulb_ws",
"light.test_ws",
{"color_temp": 250},
{"color_temp": 250},
),
# color_temp < 250
(
"bulb_ws",
"light.test_ws",
{"color_temp": 1},
{"color_temp": 250},
),
# color_temp > 454
(
"bulb_ws",
"light.test_ws",
{"color_temp": 1000},
{"color_temp": 454},
),
# hs_color
(
"bulb_cws",
"light.test_cws",
{"hs_color": [300, 100]},
{"hs_color": [300, 100]},
),
# ct + brightness
(
"bulb_ws",
"light.test_ws",
{"color_temp": 250, "brightness": 200},
{"color_temp": 250, "brightness": 200},
),
# ct + brightness (no temp support)
(
"bulb_cws",
"light.test_cws",
{"color_temp": 250, "brightness": 200},
{"hs_color": [26.807, 34.869], "brightness": 200},
),
# ct + brightness (no temp or color support)
(
"bulb_w",
"light.test_w",
{"color_temp": 250, "brightness": 200},
{"brightness": 200},
),
# hs + brightness
(
"bulb_cws",
"light.test_cws",
{"hs_color": [300, 100], "brightness": 200},
{"hs_color": [300, 100], "brightness": 200},
),
],
indirect=["device"],
ids=[
"turn_on",
"brightness > 0",
"brightness == 1",
"brightness > 254",
"color_temp",
"color_temp < 250",
"color_temp > 454",
"hs_color",
"ct + brightness",
"ct + brightness (no temp support)",
"ct + brightness (no temp or color support)",
"hs + brightness",
],
)
async def test_turn_on(
hass: HomeAssistant,
command_store: CommandStore,
device: Device,
entity_id: str,
service_data: dict[str, Any],
transition: dict[str, int],
state_attributes: dict[str, Any],
) -> None:
"""Test turning on a light."""
# Make sure the light is off.
device.raw[ATTR_LIGHT_CONTROL][0][ATTR_DEVICE_STATE] = 0
await setup_integration(hass)
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_ON,
{"entity_id": entity_id, **service_data, **transition},
blocking=True,
)
await hass.async_block_till_done()
await command_store.trigger_observe_callback(
hass, device, {ATTR_LIGHT_CONTROL: [{ATTR_DEVICE_STATE: 1}]}
)
state = hass.states.get(entity_id)
assert state
assert state.state == STATE_ON
for key, value in state_attributes.items():
# Allow some rounding error in color conversions.
assert state.attributes[key] == pytest.approx(value, abs=0.01)
@pytest.mark.parametrize(
"transition",
[{}, {"transition": 0}, {"transition": 1}],
ids=["transition_none", "transition_0", "transition_1"],
)
@pytest.mark.parametrize(
("device", "entity_id"),
[
("bulb_w", "light.test_w"),
("bulb_ws", "light.test_ws"),
("bulb_cws", "light.test_cws"),
],
indirect=["device"],
)
async def test_turn_off(
hass: HomeAssistant,
command_store: CommandStore,
device: Device,
entity_id: str,
transition: dict[str, int],
) -> None:
"""Test turning off a light."""
await setup_integration(hass)
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_OFF,
{"entity_id": entity_id, **transition},
blocking=True,
)
await hass.async_block_till_done()
await command_store.trigger_observe_callback(
hass, device, {ATTR_LIGHT_CONTROL: [{ATTR_DEVICE_STATE: 0}]}
)
state = hass.states.get(entity_id)
assert state
assert state.state == STATE_OFF