mirror of
https://github.com/home-assistant/core.git
synced 2026-08-24 10:13:52 -05:00
Add DALI scan binary sensor to lunatone (#179068)
This commit is contained in:
@@ -3,7 +3,14 @@
|
||||
import logging
|
||||
from typing import Final
|
||||
|
||||
from lunatone_rest_api_client import Auth, DALIBroadcast, Devices, Info, Sensors
|
||||
from lunatone_rest_api_client import (
|
||||
Auth,
|
||||
DALIBroadcast,
|
||||
DALIScan,
|
||||
Devices,
|
||||
Info,
|
||||
Sensors,
|
||||
)
|
||||
|
||||
from homeassistant.const import CONF_URL, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
@@ -18,11 +25,16 @@ from .coordinator import (
|
||||
LunatoneData,
|
||||
LunatoneDevicesDataUpdateCoordinator,
|
||||
LunatoneInfoDataUpdateCoordinator,
|
||||
LunatoneScanDataUpdateCoordinator,
|
||||
LunatoneSensorsDataUpdateCoordinator,
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
PLATFORMS: Final[list[Platform]] = [Platform.LIGHT, Platform.SENSOR]
|
||||
PLATFORMS: Final[list[Platform]] = [
|
||||
Platform.BINARY_SENSOR,
|
||||
Platform.LIGHT,
|
||||
Platform.SENSOR,
|
||||
]
|
||||
|
||||
|
||||
async def _update_unique_id(
|
||||
@@ -70,6 +82,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: LunatoneConfigEntry) ->
|
||||
"""Set up Lunatone from a config entry."""
|
||||
auth_api = Auth(async_get_clientsession(hass), entry.data[CONF_URL])
|
||||
info_api = Info(auth_api)
|
||||
dali_scan_api = DALIScan(auth_api)
|
||||
devices_api = Devices(info_api)
|
||||
sensors_api = Sensors(auth_api)
|
||||
|
||||
@@ -110,6 +123,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: LunatoneConfigEntry) ->
|
||||
coordinator_sensors = LunatoneSensorsDataUpdateCoordinator(hass, entry, sensors_api)
|
||||
await coordinator_sensors.async_config_entry_first_refresh()
|
||||
|
||||
coordinator_scan = LunatoneScanDataUpdateCoordinator(hass, entry, dali_scan_api)
|
||||
await coordinator_scan.async_config_entry_first_refresh()
|
||||
|
||||
dali_line_broadcasts = [
|
||||
DALIBroadcast(auth_api, int(line)) for line in coordinator_info.data.lines
|
||||
]
|
||||
@@ -118,6 +134,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: LunatoneConfigEntry) ->
|
||||
coordinator_info,
|
||||
coordinator_devices,
|
||||
coordinator_sensors,
|
||||
coordinator_scan,
|
||||
dali_line_broadcasts,
|
||||
)
|
||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
"""Platform for Lunatone binary sensor integration."""
|
||||
|
||||
from typing import override
|
||||
|
||||
from homeassistant.components.binary_sensor import (
|
||||
BinarySensorDeviceClass,
|
||||
BinarySensorEntity,
|
||||
)
|
||||
from homeassistant.const import EntityCategory
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.device_registry import DeviceInfo
|
||||
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
from .const import DOMAIN
|
||||
from .coordinator import LunatoneConfigEntry, LunatoneScanDataUpdateCoordinator
|
||||
|
||||
PARALLEL_UPDATES = 0
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: LunatoneConfigEntry,
|
||||
async_add_entities: AddConfigEntryEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up Lunatone binary sensors from the config entry."""
|
||||
coordinator_scan = config_entry.runtime_data.coordinator_scan
|
||||
|
||||
assert config_entry.unique_id is not None
|
||||
|
||||
async_add_entities(
|
||||
[LunatoneDALIScanStatus(coordinator_scan, config_entry.unique_id)]
|
||||
)
|
||||
|
||||
|
||||
class LunatoneDALIScanStatus(
|
||||
CoordinatorEntity[LunatoneScanDataUpdateCoordinator], BinarySensorEntity
|
||||
):
|
||||
"""Representation of a Lunatone DALI scan status."""
|
||||
|
||||
_attr_device_class = BinarySensorDeviceClass.RUNNING
|
||||
_attr_entity_category = EntityCategory.DIAGNOSTIC
|
||||
_attr_has_entity_name = True
|
||||
_attr_translation_key = "scan_status"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: LunatoneScanDataUpdateCoordinator,
|
||||
config_entry_unique_id: str,
|
||||
) -> None:
|
||||
"""Initialize a Lunatone DALI scan status."""
|
||||
super().__init__(coordinator)
|
||||
|
||||
self._config_entry_unique_id = config_entry_unique_id
|
||||
|
||||
self._attr_unique_id = f"{config_entry_unique_id}-scan-progress"
|
||||
self._attr_device_info = DeviceInfo(
|
||||
identifiers={(DOMAIN, self._config_entry_unique_id)},
|
||||
)
|
||||
|
||||
@property
|
||||
@override
|
||||
def is_on(self) -> bool:
|
||||
"""Return true if the DALI scan is on."""
|
||||
return self.coordinator.dali_scan_api.is_busy
|
||||
@@ -8,13 +8,14 @@ from typing import override
|
||||
import aiohttp
|
||||
from lunatone_rest_api_client import (
|
||||
DALIBroadcast,
|
||||
DALIScan,
|
||||
Device,
|
||||
Devices,
|
||||
Info,
|
||||
Sensor,
|
||||
Sensors,
|
||||
)
|
||||
from lunatone_rest_api_client.models import InfoData
|
||||
from lunatone_rest_api_client.models import InfoData, ScanData
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
@@ -24,9 +25,10 @@ from .const import DOMAIN
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
DEFAULT_INFO_SCAN_INTERVAL = timedelta(seconds=60)
|
||||
DEFAULT_DEVICES_SCAN_INTERVAL = timedelta(seconds=10)
|
||||
DEFAULT_SENSORS_SCAN_INTERVAL = timedelta(seconds=30)
|
||||
DEFAULT_INFO_UPDATE_INTERVAL = timedelta(seconds=60)
|
||||
DEFAULT_DEVICES_UPDATE_INTERVAL = timedelta(seconds=10)
|
||||
DEFAULT_SENSORS_UPDATE_INTERVAL = timedelta(seconds=30)
|
||||
DEFAULT_SCAN_UPDATE_INTERVAL = timedelta(seconds=10)
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -36,6 +38,7 @@ class LunatoneData:
|
||||
coordinator_info: LunatoneInfoDataUpdateCoordinator
|
||||
coordinator_devices: LunatoneDevicesDataUpdateCoordinator
|
||||
coordinator_sensors: LunatoneSensorsDataUpdateCoordinator
|
||||
coordinator_scan: LunatoneScanDataUpdateCoordinator
|
||||
dali_line_broadcasts: list[DALIBroadcast]
|
||||
|
||||
|
||||
@@ -57,7 +60,7 @@ class LunatoneInfoDataUpdateCoordinator(DataUpdateCoordinator[InfoData]):
|
||||
config_entry=config_entry,
|
||||
name=f"{DOMAIN}-info",
|
||||
always_update=False,
|
||||
update_interval=DEFAULT_INFO_SCAN_INTERVAL,
|
||||
update_interval=DEFAULT_INFO_UPDATE_INTERVAL,
|
||||
)
|
||||
self.info_api = info_api
|
||||
|
||||
@@ -94,7 +97,7 @@ class LunatoneDevicesDataUpdateCoordinator(DataUpdateCoordinator[dict[int, Devic
|
||||
config_entry=config_entry,
|
||||
name=f"{DOMAIN}-devices",
|
||||
always_update=False,
|
||||
update_interval=DEFAULT_DEVICES_SCAN_INTERVAL,
|
||||
update_interval=DEFAULT_DEVICES_UPDATE_INTERVAL,
|
||||
)
|
||||
self.devices_api = devices_api
|
||||
|
||||
@@ -131,7 +134,7 @@ class LunatoneSensorsDataUpdateCoordinator(DataUpdateCoordinator[dict[int, Senso
|
||||
config_entry=config_entry,
|
||||
name=f"{DOMAIN}-sensors",
|
||||
always_update=False,
|
||||
update_interval=DEFAULT_SENSORS_SCAN_INTERVAL,
|
||||
update_interval=DEFAULT_SENSORS_UPDATE_INTERVAL,
|
||||
)
|
||||
self.sensors_api = sensors_api
|
||||
|
||||
@@ -149,3 +152,46 @@ class LunatoneSensorsDataUpdateCoordinator(DataUpdateCoordinator[dict[int, Senso
|
||||
if self.sensors_api.data is None:
|
||||
raise UpdateFailed("Did not receive sensors data from Lunatone REST API")
|
||||
return {sensor.id: sensor for sensor in self.sensors_api.sensors}
|
||||
|
||||
|
||||
class LunatoneScanDataUpdateCoordinator(DataUpdateCoordinator[ScanData]):
|
||||
"""Data update coordinator for Lunatone scan."""
|
||||
|
||||
config_entry: LunatoneConfigEntry
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
hass: HomeAssistant,
|
||||
config_entry: LunatoneConfigEntry,
|
||||
dali_scan_api: DALIScan,
|
||||
) -> None:
|
||||
"""Initialize the coordinator."""
|
||||
super().__init__(
|
||||
hass,
|
||||
_LOGGER,
|
||||
config_entry=config_entry,
|
||||
name=f"{DOMAIN}-scan",
|
||||
always_update=False,
|
||||
update_interval=DEFAULT_SCAN_UPDATE_INTERVAL,
|
||||
)
|
||||
self.dali_scan_api = dali_scan_api
|
||||
|
||||
@override
|
||||
async def _async_update_data(self) -> ScanData:
|
||||
"""Update scan data."""
|
||||
try:
|
||||
await self.dali_scan_api.async_update()
|
||||
except aiohttp.ClientConnectionError as ex:
|
||||
raise UpdateFailed(
|
||||
"Unable to retrieve scan data from Lunatone REST API"
|
||||
) from ex
|
||||
|
||||
if self.dali_scan_api.data is None:
|
||||
raise UpdateFailed("Did not receive scan data from Lunatone REST API")
|
||||
|
||||
update_interval = DEFAULT_SCAN_UPDATE_INTERVAL
|
||||
if self.dali_scan_api.is_busy:
|
||||
update_interval = timedelta(seconds=1)
|
||||
self.update_interval = update_interval
|
||||
|
||||
return self.dali_scan_api.data
|
||||
|
||||
@@ -37,6 +37,13 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"binary_sensor": {
|
||||
"scan_status": {
|
||||
"name": "DALI scan"
|
||||
}
|
||||
}
|
||||
},
|
||||
"exceptions": {
|
||||
"missing_device_info": {
|
||||
"message": "Unable to read device information. Please verify the device's network connection."
|
||||
|
||||
@@ -4,7 +4,7 @@ from collections.abc import Generator
|
||||
from unittest.mock import AsyncMock, PropertyMock, patch
|
||||
|
||||
from lunatone_rest_api_client import Device, Devices, Info, Sensor, Sensors
|
||||
from lunatone_rest_api_client.models import InfoData, SensorsData
|
||||
from lunatone_rest_api_client.models import InfoData, ScanData, ScanState, SensorsData
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.lunatone.config_flow import LunatoneConfigFlow
|
||||
@@ -161,6 +161,29 @@ def mock_lunatone_sensors() -> Generator[AsyncMock]:
|
||||
yield sensors
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_lunatone_scan() -> Generator[AsyncMock]:
|
||||
"""Mock a Lunatone DALI scan object."""
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.lunatone.DALIScan",
|
||||
autospec=True,
|
||||
) as mock_dali_scan,
|
||||
patch(
|
||||
"homeassistant.components.lunatone.coordinator.DALIScan",
|
||||
new=mock_dali_scan,
|
||||
),
|
||||
):
|
||||
scan = mock_dali_scan.return_value
|
||||
scan.data = ScanData()
|
||||
type(scan).is_busy = PropertyMock(
|
||||
side_effect=lambda: (
|
||||
scan.data.status in {ScanState.ADDRESSING, ScanState.IN_PROGRESS}
|
||||
)
|
||||
)
|
||||
yield scan
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_config_entry() -> MockConfigEntry:
|
||||
"""Return the default mocked config entry."""
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
# serializer version: 1
|
||||
# name: test_setup[binary_sensor.test_dali_scan-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': list([
|
||||
None,
|
||||
]),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'binary_sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'binary_sensor.test_dali_scan',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'DALI scan',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <BinarySensorDeviceClass.RUNNING: 'running'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'DALI scan',
|
||||
'platform': 'lunatone',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'scan_status',
|
||||
'unique_id': 'be37ca9c47c24498a38bc62c7c711840-scan-progress',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_setup[binary_sensor.test_dali_scan-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'running',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Test DALI scan',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'binary_sensor.test_dali_scan',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
@@ -0,0 +1,76 @@
|
||||
"""Tests for the binary sensors provided by the Lunatone integration."""
|
||||
|
||||
from datetime import timedelta
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
from lunatone_rest_api_client.models import ScanData, ScanState
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from . import setup_integration
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
async def test_setup(
|
||||
hass: HomeAssistant,
|
||||
mock_lunatone_info: AsyncMock,
|
||||
mock_lunatone_devices: AsyncMock,
|
||||
mock_lunatone_sensors: AsyncMock,
|
||||
mock_lunatone_scan: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
entity_registry: er.EntityRegistry,
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Test the Lunatone binary sensor setup."""
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
entities = hass.states.async_all(Platform.BINARY_SENSOR)
|
||||
for entity_state in entities:
|
||||
entity_entry = entity_registry.async_get(entity_state.entity_id)
|
||||
assert entity_entry
|
||||
assert entity_entry == snapshot(name=f"{entity_entry.entity_id}-entry")
|
||||
assert entity_state == snapshot(name=f"{entity_entry.entity_id}-state")
|
||||
|
||||
|
||||
async def test_sensor_value_update(
|
||||
hass: HomeAssistant,
|
||||
mock_lunatone_info: AsyncMock,
|
||||
mock_lunatone_devices: AsyncMock,
|
||||
mock_lunatone_sensors: AsyncMock,
|
||||
mock_lunatone_scan: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test the Lunatone DALI scan status value update."""
|
||||
scan_states = iter((ScanState.ADDRESSING, ScanState.DONE))
|
||||
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
coordinator = mock_config_entry.runtime_data.coordinator_scan
|
||||
|
||||
async def fake_update():
|
||||
scan_state = next(scan_states)
|
||||
mock_lunatone_scan.data = ScanData(status=scan_state)
|
||||
|
||||
mock_lunatone_scan.async_update.side_effect = fake_update
|
||||
|
||||
entities = hass.states.async_all(Platform.BINARY_SENSOR)
|
||||
assert entities[0].state == "off"
|
||||
assert coordinator.update_interval == timedelta(seconds=10)
|
||||
|
||||
await coordinator.async_refresh()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entities = hass.states.async_all(Platform.BINARY_SENSOR)
|
||||
assert entities[0].state == "on"
|
||||
assert coordinator.update_interval == timedelta(seconds=1)
|
||||
|
||||
await coordinator.async_refresh()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entities = hass.states.async_all(Platform.BINARY_SENSOR)
|
||||
assert entities[0].state == "off"
|
||||
assert coordinator.update_interval == timedelta(seconds=10)
|
||||
@@ -158,6 +158,7 @@ async def test_zeroconf_flow(
|
||||
mock_lunatone_info: AsyncMock,
|
||||
mock_lunatone_devices: AsyncMock,
|
||||
mock_lunatone_sensors: AsyncMock,
|
||||
mock_lunatone_scan: AsyncMock,
|
||||
) -> None:
|
||||
"""Test zeroconf flow."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
@@ -180,6 +181,7 @@ async def test_zeroconf_flow_abort_duplicate(
|
||||
mock_lunatone_info: AsyncMock,
|
||||
mock_lunatone_devices: AsyncMock,
|
||||
mock_lunatone_sensors: AsyncMock,
|
||||
mock_lunatone_scan: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test zeroconf flow aborts with duplicate."""
|
||||
|
||||
@@ -19,6 +19,7 @@ async def test_config_entry_diagnostics(
|
||||
mock_lunatone_info: AsyncMock,
|
||||
mock_lunatone_devices: AsyncMock,
|
||||
mock_lunatone_sensors: AsyncMock,
|
||||
mock_lunatone_scan: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
|
||||
@@ -20,6 +20,7 @@ async def test_load_unload_config_entry(
|
||||
mock_lunatone_info: AsyncMock,
|
||||
mock_lunatone_devices: AsyncMock,
|
||||
mock_lunatone_sensors: AsyncMock,
|
||||
mock_lunatone_scan: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
device_registry: dr.DeviceRegistry,
|
||||
) -> None:
|
||||
@@ -50,6 +51,7 @@ async def test_config_entry_not_ready_info_api_fail(
|
||||
mock_lunatone_info: AsyncMock,
|
||||
mock_lunatone_devices: AsyncMock,
|
||||
mock_lunatone_sensors: AsyncMock,
|
||||
mock_lunatone_scan: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test config entry not ready due to info API failure."""
|
||||
@@ -74,6 +76,7 @@ async def test_config_entry_not_ready_devices_api_fail(
|
||||
mock_lunatone_info: AsyncMock,
|
||||
mock_lunatone_devices: AsyncMock,
|
||||
mock_lunatone_sensors: AsyncMock,
|
||||
mock_lunatone_scan: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test config entry not ready due to devices API failure."""
|
||||
@@ -100,6 +103,7 @@ async def test_config_entry_not_ready_sensors_api_fail(
|
||||
mock_lunatone_info: AsyncMock,
|
||||
mock_lunatone_devices: AsyncMock,
|
||||
mock_lunatone_sensors: AsyncMock,
|
||||
mock_lunatone_scan: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test config entry not ready due to sensors API failure."""
|
||||
@@ -123,6 +127,37 @@ async def test_config_entry_not_ready_sensors_api_fail(
|
||||
assert mock_config_entry.state is ConfigEntryState.LOADED
|
||||
|
||||
|
||||
async def test_config_entry_not_ready_scan_api_fail(
|
||||
hass: HomeAssistant,
|
||||
mock_lunatone_info: AsyncMock,
|
||||
mock_lunatone_devices: AsyncMock,
|
||||
mock_lunatone_sensors: AsyncMock,
|
||||
mock_lunatone_scan: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test config entry not ready due to sensors API failure."""
|
||||
mock_lunatone_scan.async_update.side_effect = aiohttp.ClientConnectionError()
|
||||
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
mock_lunatone_info.async_update.assert_called_once()
|
||||
mock_lunatone_devices.async_update.assert_called_once()
|
||||
mock_lunatone_sensors.async_update.assert_called_once()
|
||||
mock_lunatone_scan.async_update.assert_called_once()
|
||||
assert mock_config_entry.state is ConfigEntryState.SETUP_RETRY
|
||||
|
||||
mock_lunatone_scan.async_update.side_effect = None
|
||||
|
||||
await hass.config_entries.async_reload(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
mock_lunatone_info.async_update.assert_called()
|
||||
mock_lunatone_devices.async_update.assert_called()
|
||||
mock_lunatone_sensors.async_update.assert_called()
|
||||
mock_lunatone_scan.async_update.assert_called()
|
||||
assert mock_config_entry.state is ConfigEntryState.LOADED
|
||||
|
||||
|
||||
async def test_config_entry_not_ready_no_info_data(
|
||||
hass: HomeAssistant,
|
||||
mock_lunatone_info: AsyncMock,
|
||||
@@ -172,6 +207,26 @@ async def test_config_entry_not_ready_no_sensors_data(
|
||||
assert mock_config_entry.state is ConfigEntryState.SETUP_RETRY
|
||||
|
||||
|
||||
async def test_config_entry_not_ready_no_dali_scan_data(
|
||||
hass: HomeAssistant,
|
||||
mock_lunatone_info: AsyncMock,
|
||||
mock_lunatone_devices: AsyncMock,
|
||||
mock_lunatone_sensors: AsyncMock,
|
||||
mock_lunatone_scan: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test the Lunatone configuration entry not ready due to missing DALI scan data."""
|
||||
mock_lunatone_scan.data = None
|
||||
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
mock_lunatone_info.async_update.assert_called_once()
|
||||
mock_lunatone_devices.async_update.assert_called_once()
|
||||
mock_lunatone_sensors.async_update.assert_called_once()
|
||||
mock_lunatone_scan.async_update.assert_called_once()
|
||||
assert mock_config_entry.state is ConfigEntryState.SETUP_RETRY
|
||||
|
||||
|
||||
async def test_config_entry_not_ready_no_serial_number(
|
||||
hass: HomeAssistant,
|
||||
mock_lunatone_info: AsyncMock,
|
||||
@@ -192,6 +247,7 @@ async def test_config_entry_unique_id_update(
|
||||
mock_lunatone_info: AsyncMock,
|
||||
mock_lunatone_devices: AsyncMock,
|
||||
mock_lunatone_sensors: AsyncMock,
|
||||
mock_lunatone_scan: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
device_registry: dr.DeviceRegistry,
|
||||
entity_registry: er.EntityRegistry,
|
||||
|
||||
@@ -35,6 +35,7 @@ async def test_setup(
|
||||
mock_lunatone_info: AsyncMock,
|
||||
mock_lunatone_devices: AsyncMock,
|
||||
mock_lunatone_sensors: AsyncMock,
|
||||
mock_lunatone_scan: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
device_registry: dr.DeviceRegistry,
|
||||
entity_registry: er.EntityRegistry,
|
||||
@@ -56,6 +57,7 @@ async def test_turn_on_off(
|
||||
mock_lunatone_info: AsyncMock,
|
||||
mock_lunatone_devices: AsyncMock,
|
||||
mock_lunatone_sensors: AsyncMock,
|
||||
mock_lunatone_scan: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test the light can be turned on and off."""
|
||||
@@ -98,6 +100,7 @@ async def test_turn_on_off_with_brightness(
|
||||
mock_lunatone_info: AsyncMock,
|
||||
mock_lunatone_devices: AsyncMock,
|
||||
mock_lunatone_sensors: AsyncMock,
|
||||
mock_lunatone_scan: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test the light can be turned on with brightness."""
|
||||
@@ -158,6 +161,7 @@ async def test_turn_on_off_broadcast(
|
||||
mock_lunatone_info: AsyncMock,
|
||||
mock_lunatone_devices: AsyncMock,
|
||||
mock_lunatone_sensors: AsyncMock,
|
||||
mock_lunatone_scan: AsyncMock,
|
||||
mock_lunatone_dali_broadcast: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
@@ -202,6 +206,7 @@ async def test_line_broadcast_available_status(
|
||||
mock_lunatone_info: AsyncMock,
|
||||
mock_lunatone_devices: AsyncMock,
|
||||
mock_lunatone_sensors: AsyncMock,
|
||||
mock_lunatone_scan: AsyncMock,
|
||||
mock_lunatone_dali_broadcast: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
@@ -234,6 +239,7 @@ async def test_line_broadcast_line_present(
|
||||
mock_lunatone_info: AsyncMock,
|
||||
mock_lunatone_devices: AsyncMock,
|
||||
mock_lunatone_sensors: AsyncMock,
|
||||
mock_lunatone_scan: AsyncMock,
|
||||
mock_lunatone_dali_broadcast: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
@@ -254,6 +260,7 @@ async def test_turn_on_with_color_temperature(
|
||||
mock_lunatone_info: AsyncMock,
|
||||
mock_lunatone_devices: AsyncMock,
|
||||
mock_lunatone_sensors: AsyncMock,
|
||||
mock_lunatone_scan: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
color_temp_kelvin: int,
|
||||
) -> None:
|
||||
@@ -294,6 +301,7 @@ async def test_turn_on_with_rgb_color(
|
||||
mock_lunatone_info: AsyncMock,
|
||||
mock_lunatone_devices: AsyncMock,
|
||||
mock_lunatone_sensors: AsyncMock,
|
||||
mock_lunatone_scan: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
rgb_color: tuple[int, int, int],
|
||||
) -> None:
|
||||
@@ -336,6 +344,7 @@ async def test_turn_on_with_rgbw_color(
|
||||
mock_lunatone_info: AsyncMock,
|
||||
mock_lunatone_devices: AsyncMock,
|
||||
mock_lunatone_sensors: AsyncMock,
|
||||
mock_lunatone_scan: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
rgbw_color: tuple[int, int, int, int],
|
||||
) -> None:
|
||||
|
||||
@@ -21,6 +21,7 @@ async def test_setup(
|
||||
mock_lunatone_info: AsyncMock,
|
||||
mock_lunatone_devices: AsyncMock,
|
||||
mock_lunatone_sensors: AsyncMock,
|
||||
mock_lunatone_scan: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
entity_registry: er.EntityRegistry,
|
||||
snapshot: SnapshotAssertion,
|
||||
@@ -41,6 +42,7 @@ async def test_sensor_value_update(
|
||||
mock_lunatone_info: AsyncMock,
|
||||
mock_lunatone_devices: AsyncMock,
|
||||
mock_lunatone_sensors: AsyncMock,
|
||||
mock_lunatone_scan: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
) -> None:
|
||||
|
||||
Reference in New Issue
Block a user