1
0
mirror of https://github.com/home-assistant/core.git synced 2026-05-28 03:06:30 +01:00
Files
core/tests/components/avea/test_light.py
2026-05-26 16:27:07 +02:00

355 lines
11 KiB
Python

"""Test the Avea light platform."""
from collections.abc import AsyncGenerator
from datetime import timedelta
from unittest.mock import MagicMock, call, patch
from freezegun.api import FrozenDateTimeFactory
import pytest
from homeassistant.components.avea.const import UNKNOWN_NAME
from homeassistant.components.light import (
ATTR_BRIGHTNESS,
ATTR_HS_COLOR,
ATTR_SUPPORTED_COLOR_MODES,
ColorMode,
)
from homeassistant.const import ATTR_ENTITY_ID, STATE_OFF, STATE_ON
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr
from . import AVEA_DISCOVERY_INFO, AVEA_FIRMWARE_VERSION, AVEA_SERIAL_NUMBER
from tests.common import MockConfigEntry, async_fire_time_changed
@pytest.fixture
def mock_bulb() -> MagicMock:
"""Return a mocked Avea bulb."""
bulb = MagicMock()
bulb.name = "Unknown"
bulb.fw_version = "Unknown"
bulb.hardware_revision = "Unknown"
bulb.manufacturer_name = "Unknown"
bulb.serial_number = "Unknown"
bulb.brightness = 0
bulb.connect.return_value = True
bulb.get_brightness.return_value = 0
bulb.get_fw_version.return_value = AVEA_FIRMWARE_VERSION
bulb.get_hardware_revision.return_value = "Elgato Avea"
bulb.get_manufacturer_name.return_value = "Elgato Systems GmbH"
bulb.get_rgb.return_value = (0, 0, 0)
bulb.get_serial_number.return_value = AVEA_SERIAL_NUMBER
return bulb
@pytest.fixture
async def setup_integration(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_bulb: MagicMock,
) -> AsyncGenerator[MagicMock]:
"""Set up the integration."""
with (
patch(
"homeassistant.components.avea.async_ble_device_from_address",
return_value=AVEA_DISCOVERY_INFO.device,
),
patch("homeassistant.components.avea.avea.Bulb", return_value=mock_bulb),
):
mock_config_entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done()
yield mock_bulb
async def test_init_state(
hass: HomeAssistant,
setup_integration: MagicMock,
) -> None:
"""Test the initial state."""
state = hass.states.get("light.bedroom")
assert state is not None
assert state.state == STATE_OFF
assert state.name == "Bedroom"
assert state.attributes[ATTR_SUPPORTED_COLOR_MODES] == [ColorMode.HS]
async def test_device_info(
device_registry: dr.DeviceRegistry,
setup_integration: MagicMock,
) -> None:
"""Test the device info."""
bulb = setup_integration
device = device_registry.async_get_device(
connections={(dr.CONNECTION_BLUETOOTH, AVEA_DISCOVERY_INFO.address)},
)
assert device is not None
assert device.name == "Bedroom"
assert device.manufacturer == "Elgato Systems GmbH"
assert device.model == "Avea"
assert device.hw_version == "Elgato Avea"
assert device.sw_version == AVEA_FIRMWARE_VERSION
assert device.serial_number == AVEA_SERIAL_NUMBER
bulb.get_manufacturer_name.assert_called_once()
bulb.get_hardware_revision.assert_called_once()
bulb.get_fw_version.assert_called_once()
bulb.get_serial_number.assert_called_once()
async def test_device_info_populates_when_connect_fails(
hass: HomeAssistant,
device_registry: dr.DeviceRegistry,
mock_config_entry: MockConfigEntry,
mock_bulb: MagicMock,
) -> None:
"""Test device info is populated when the shared connection fails."""
mock_bulb.connect.return_value = False
with (
patch(
"homeassistant.components.avea.async_ble_device_from_address",
return_value=AVEA_DISCOVERY_INFO.device,
),
patch("homeassistant.components.avea.avea.Bulb", return_value=mock_bulb),
):
mock_config_entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done()
mock_bulb.connect.assert_called_once()
mock_bulb.get_manufacturer_name.assert_called_once()
mock_bulb.get_hardware_revision.assert_called_once()
mock_bulb.get_fw_version.assert_called_once()
mock_bulb.get_serial_number.assert_called_once()
mock_bulb.disconnect.assert_not_called()
device = device_registry.async_get_device(
connections={(dr.CONNECTION_BLUETOOTH, AVEA_DISCOVERY_INFO.address)},
)
assert device is not None
assert device.manufacturer == "Elgato Systems GmbH"
assert device.model == "Avea"
assert device.hw_version == "Elgato Avea"
assert device.sw_version == AVEA_FIRMWARE_VERSION
assert device.serial_number == AVEA_SERIAL_NUMBER
async def test_device_info_ignores_unknown_values(
hass: HomeAssistant,
device_registry: dr.DeviceRegistry,
mock_config_entry: MockConfigEntry,
mock_bulb: MagicMock,
) -> None:
"""Test unknown device info is not populated."""
mock_bulb.get_manufacturer_name.return_value = UNKNOWN_NAME
mock_bulb.get_hardware_revision.return_value = ""
mock_bulb.get_fw_version.return_value = UNKNOWN_NAME
mock_bulb.get_serial_number.return_value = ""
with (
patch(
"homeassistant.components.avea.async_ble_device_from_address",
return_value=AVEA_DISCOVERY_INFO.device,
),
patch("homeassistant.components.avea.avea.Bulb", return_value=mock_bulb),
):
mock_config_entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done()
device = device_registry.async_get_device(
connections={(dr.CONNECTION_BLUETOOTH, AVEA_DISCOVERY_INFO.address)},
)
assert device is not None
assert device.manufacturer is None
assert device.model == "Avea"
assert device.hw_version is None
assert device.sw_version is None
assert device.serial_number is None
async def test_device_info_is_read_once(
hass: HomeAssistant,
setup_integration: MagicMock,
freezer: FrozenDateTimeFactory,
) -> None:
"""Test device info is read once."""
bulb = setup_integration
bulb.get_manufacturer_name.reset_mock()
bulb.get_hardware_revision.reset_mock()
bulb.get_fw_version.reset_mock()
bulb.get_serial_number.reset_mock()
freezer.tick(timedelta(seconds=30))
async_fire_time_changed(hass)
await hass.async_block_till_done(wait_background_tasks=True)
bulb.get_manufacturer_name.assert_not_called()
bulb.get_hardware_revision.assert_not_called()
bulb.get_fw_version.assert_not_called()
bulb.get_serial_number.assert_not_called()
async def test_turn_on_and_off(
hass: HomeAssistant,
setup_integration: MagicMock,
) -> None:
"""Test turning the light on and off."""
bulb = setup_integration
await hass.services.async_call(
"light",
"turn_on",
{ATTR_ENTITY_ID: "light.bedroom"},
blocking=True,
)
bulb.set_brightness.assert_called_with(4095)
bulb.set_brightness.reset_mock()
await hass.services.async_call(
"light",
"turn_on",
{ATTR_ENTITY_ID: "light.bedroom", ATTR_BRIGHTNESS: 128},
blocking=True,
)
bulb.set_brightness.assert_called_with(2056)
bulb.set_rgb.reset_mock()
await hass.services.async_call(
"light",
"turn_on",
{ATTR_ENTITY_ID: "light.bedroom", ATTR_HS_COLOR: (0, 100)},
blocking=True,
)
bulb.set_rgb.assert_called_with(255, 0, 0)
bulb.set_brightness.reset_mock()
await hass.services.async_call(
"light",
"turn_off",
{ATTR_ENTITY_ID: "light.bedroom"},
blocking=True,
)
bulb.set_brightness.assert_called_with(0)
async def test_turn_on_restores_last_brightness(
hass: HomeAssistant,
setup_integration: MagicMock,
freezer: FrozenDateTimeFactory,
) -> None:
"""Test turning the light on restores the last brightness."""
bulb = setup_integration
bulb.get_brightness.side_effect = [3212, None, None, None]
freezer.tick(timedelta(seconds=30))
async_fire_time_changed(hass)
await hass.async_block_till_done(wait_background_tasks=True)
state = hass.states.get("light.bedroom")
assert state is not None
assert state.attributes[ATTR_BRIGHTNESS] == 200
bulb.set_brightness.reset_mock()
await hass.services.async_call(
"light",
"turn_on",
{ATTR_ENTITY_ID: "light.bedroom", ATTR_BRIGHTNESS: 10},
blocking=True,
)
bulb.set_brightness.assert_called_with(161)
bulb.set_brightness.reset_mock()
await hass.services.async_call(
"light",
"turn_off",
{ATTR_ENTITY_ID: "light.bedroom"},
blocking=True,
)
bulb.set_brightness.assert_called_with(0)
state = hass.states.get("light.bedroom")
assert state is not None
assert state.state == STATE_OFF
assert state.attributes[ATTR_BRIGHTNESS] is None
bulb.set_brightness.reset_mock()
await hass.services.async_call(
"light",
"turn_on",
{ATTR_ENTITY_ID: "light.bedroom"},
blocking=True,
)
bulb.set_brightness.assert_called_with(161)
async def test_update_state(
hass: HomeAssistant, setup_integration: MagicMock, freezer: FrozenDateTimeFactory
) -> None:
"""Test updating the entity state."""
state = hass.states.get("light.bedroom")
assert state is not None
assert state.state == STATE_OFF
assert state.attributes[ATTR_BRIGHTNESS] is None
bulb = setup_integration
bulb.reset_mock()
bulb.connect.return_value = True
bulb.get_brightness.return_value = 2048
bulb.get_rgb.return_value = (0, 255, 0)
freezer.tick(timedelta(seconds=30))
async_fire_time_changed(hass)
await hass.async_block_till_done(wait_background_tasks=True)
bulb.connect.assert_called_once()
bulb.get_brightness.assert_called_once()
bulb.get_rgb.assert_called_once()
bulb.disconnect.assert_called_once()
bulb.assert_has_calls(
[
call.connect(),
call.get_brightness(),
call.get_rgb(),
call.disconnect(),
]
)
state = hass.states.get("light.bedroom")
assert state is not None
assert state.state == STATE_ON
assert state.attributes[ATTR_BRIGHTNESS] == 128
assert state.attributes[ATTR_HS_COLOR] == (120.0, 100.0)
async def test_update_state_uses_cached_values_when_connect_fails(
hass: HomeAssistant, setup_integration: MagicMock, freezer: FrozenDateTimeFactory
) -> None:
"""Test updating the entity state when the shared connection fails."""
bulb = setup_integration
bulb.reset_mock()
bulb.connect.return_value = False
bulb.get_brightness.return_value = 2048
bulb.get_rgb.return_value = (0, 255, 0)
freezer.tick(timedelta(seconds=30))
async_fire_time_changed(hass)
await hass.async_block_till_done(wait_background_tasks=True)
bulb.connect.assert_called_once()
bulb.get_brightness.assert_called_once()
bulb.get_rgb.assert_called_once()
bulb.disconnect.assert_not_called()
state = hass.states.get("light.bedroom")
assert state is not None
assert state.state == STATE_ON
assert state.attributes[ATTR_BRIGHTNESS] == 128
assert state.attributes[ATTR_HS_COLOR] == (120.0, 100.0)