mirror of
https://github.com/home-assistant/core.git
synced 2026-07-15 02:23:47 +01:00
Add light platform to systemnexa2 (#163710)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
@@ -6,4 +6,4 @@ from homeassistant.const import Platform
|
||||
|
||||
DOMAIN = "systemnexa2"
|
||||
MANUFACTURER = "NEXA"
|
||||
PLATFORMS: Final = [Platform.SWITCH]
|
||||
PLATFORMS: Final = [Platform.LIGHT, Platform.SWITCH]
|
||||
|
||||
@@ -156,6 +156,12 @@ class SystemNexa2DataUpdateCoordinator(DataUpdateCoordinator[SystemNexa2Data]):
|
||||
"""Toggle the device."""
|
||||
await self._async_sn2_call_with_error_handling(self.device.toggle())
|
||||
|
||||
async def async_set_brightness(self, value: float) -> None:
|
||||
"""Set the brightness of the device (0.0 to 1.0)."""
|
||||
await self._async_sn2_call_with_error_handling(
|
||||
self.device.set_brightness(value)
|
||||
)
|
||||
|
||||
async def async_setting_enable(self, setting: OnOffSetting) -> None:
|
||||
"""Enable a device setting."""
|
||||
await self._async_sn2_call_with_error_handling(setting.enable(self.device))
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
"""Light entity for the SystemNexa2 integration."""
|
||||
|
||||
from typing import Any
|
||||
|
||||
from homeassistant.components.light import ATTR_BRIGHTNESS, ColorMode, LightEntity
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
|
||||
from .coordinator import SystemNexa2ConfigEntry, SystemNexa2DataUpdateCoordinator
|
||||
from .entity import SystemNexa2Entity
|
||||
|
||||
PARALLEL_UPDATES = 0
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
entry: SystemNexa2ConfigEntry,
|
||||
async_add_entities: AddConfigEntryEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up lights based on a config entry."""
|
||||
coordinator = entry.runtime_data
|
||||
|
||||
# Only add light entity for dimmable devices
|
||||
if coordinator.data.info_data.dimmable:
|
||||
async_add_entities([SystemNexa2Light(coordinator)])
|
||||
|
||||
|
||||
class SystemNexa2Light(SystemNexa2Entity, LightEntity):
|
||||
"""Representation of a dimmable SystemNexa2 light."""
|
||||
|
||||
_attr_translation_key = "light"
|
||||
_attr_color_mode = ColorMode.BRIGHTNESS
|
||||
_attr_supported_color_modes = {ColorMode.BRIGHTNESS}
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: SystemNexa2DataUpdateCoordinator,
|
||||
) -> None:
|
||||
"""Initialize the light."""
|
||||
super().__init__(
|
||||
coordinator=coordinator,
|
||||
key="light",
|
||||
)
|
||||
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn on the light."""
|
||||
# Check if we're setting brightness
|
||||
if ATTR_BRIGHTNESS in kwargs:
|
||||
brightness = kwargs[ATTR_BRIGHTNESS]
|
||||
# Convert HomeAssistant brightness (0-255) to device brightness (0-1.0)
|
||||
value = brightness / 255
|
||||
await self.coordinator.async_set_brightness(value)
|
||||
else:
|
||||
await self.coordinator.async_turn_on()
|
||||
|
||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||
"""Turn off the light."""
|
||||
await self.coordinator.async_turn_off()
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool | None:
|
||||
"""Return true if the light is on."""
|
||||
if self.coordinator.data.state is None:
|
||||
return None
|
||||
# Consider the light on if brightness is greater than 0
|
||||
return self.coordinator.data.state > 0
|
||||
|
||||
@property
|
||||
def brightness(self) -> int | None:
|
||||
"""Return the brightness of the light (0-255)."""
|
||||
if self.coordinator.data.state is None:
|
||||
return None
|
||||
# Convert device brightness (0-1.0) to HomeAssistant brightness (0-255)
|
||||
return max(0, min(255, round(self.coordinator.data.state * 255)))
|
||||
@@ -31,6 +31,11 @@
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"light": {
|
||||
"light": {
|
||||
"name": "Light"
|
||||
}
|
||||
},
|
||||
"switch": {
|
||||
"433mhz": {
|
||||
"name": "433 MHz"
|
||||
@@ -45,7 +50,7 @@
|
||||
"name": "Physical button"
|
||||
},
|
||||
"relay_1": {
|
||||
"name": "Relay 1"
|
||||
"name": "Relay"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
from collections.abc import Generator
|
||||
from ipaddress import ip_address
|
||||
from typing import Any
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
import pytest
|
||||
@@ -14,6 +15,39 @@ from homeassistant.helpers.service_info.zeroconf import ZeroconfServiceInfo
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
@pytest.fixture(params=[False])
|
||||
def dimmable(request: pytest.FixtureRequest) -> bool:
|
||||
"""Return whether device is dimmable."""
|
||||
return request.param
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def device_info(dimmable: bool) -> dict[str, Any]:
|
||||
"""Return device configuration based on type."""
|
||||
# Create mock settings (same for all devices)
|
||||
mock_setting_433mhz = MagicMock(spec=OnOffSetting)
|
||||
mock_setting_433mhz.name = "433Mhz"
|
||||
mock_setting_433mhz.enable = AsyncMock()
|
||||
mock_setting_433mhz.disable = AsyncMock()
|
||||
mock_setting_433mhz.is_enabled = MagicMock(return_value=True)
|
||||
|
||||
mock_setting_cloud = MagicMock(spec=OnOffSetting)
|
||||
mock_setting_cloud.name = "Cloud Access"
|
||||
mock_setting_cloud.enable = AsyncMock()
|
||||
mock_setting_cloud.disable = AsyncMock()
|
||||
mock_setting_cloud.is_enabled = MagicMock(return_value=False)
|
||||
|
||||
return {
|
||||
"name": "In-Wall Dimmer" if dimmable else "Outdoor Smart Plug",
|
||||
"model": "WBD-01" if dimmable else "WPO-01",
|
||||
"unique_id": "aabbccddee01" if dimmable else "aabbccddee02",
|
||||
"host": "10.0.0.101" if dimmable else "10.0.0.100",
|
||||
"initial_state": 0.5 if dimmable else 1.0,
|
||||
"settings": [mock_setting_433mhz, mock_setting_cloud],
|
||||
"dimmable": dimmable,
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_setup_entry() -> Generator[AsyncMock]:
|
||||
"""Override async_setup_entry."""
|
||||
@@ -24,7 +58,7 @@ def mock_setup_entry() -> Generator[AsyncMock]:
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_system_nexa_2_device() -> Generator[MagicMock]:
|
||||
def mock_system_nexa_2_device(device_info: dict[str, Any]) -> Generator[MagicMock]:
|
||||
"""Mock the System Nexa 2 API."""
|
||||
with (
|
||||
patch(
|
||||
@@ -36,30 +70,17 @@ def mock_system_nexa_2_device() -> Generator[MagicMock]:
|
||||
):
|
||||
device = mock_device.return_value
|
||||
device.info_data = InformationData(
|
||||
name="Test Device",
|
||||
model="Test Model",
|
||||
unique_id="test_device_id",
|
||||
name=device_info["name"],
|
||||
model=device_info["model"],
|
||||
unique_id=device_info["unique_id"],
|
||||
sw_version="Test Model Version",
|
||||
hw_version="Test HW Version",
|
||||
wifi_dbm=-50,
|
||||
wifi_ssid="Test WiFi SSID",
|
||||
dimmable=False,
|
||||
dimmable=device_info["dimmable"],
|
||||
)
|
||||
|
||||
# Create mock OnOffSettings
|
||||
mock_setting_433mhz = MagicMock(spec=OnOffSetting)
|
||||
mock_setting_433mhz.name = "433Mhz"
|
||||
mock_setting_433mhz.enable = AsyncMock()
|
||||
mock_setting_433mhz.disable = AsyncMock()
|
||||
mock_setting_433mhz.is_enabled = MagicMock(return_value=True)
|
||||
|
||||
mock_setting_cloud = MagicMock(spec=OnOffSetting)
|
||||
mock_setting_cloud.name = "Cloud Access"
|
||||
mock_setting_cloud.enable = AsyncMock()
|
||||
mock_setting_cloud.disable = AsyncMock()
|
||||
mock_setting_cloud.is_enabled = MagicMock(return_value=False)
|
||||
|
||||
device.settings = [mock_setting_433mhz, mock_setting_cloud]
|
||||
device.settings = device_info["settings"]
|
||||
device.get_info = AsyncMock()
|
||||
device.get_info.return_value = InformationUpdate(information=device.info_data)
|
||||
|
||||
@@ -72,13 +93,14 @@ def mock_system_nexa_2_device() -> Generator[MagicMock]:
|
||||
"on_update"
|
||||
)
|
||||
if on_update:
|
||||
await on_update(StateChange(state=1.0))
|
||||
await on_update(StateChange(state=device_info["initial_state"]))
|
||||
|
||||
device.connect = AsyncMock(side_effect=mock_connect)
|
||||
device.disconnect = AsyncMock()
|
||||
device.turn_on = AsyncMock()
|
||||
device.turn_off = AsyncMock()
|
||||
device.toggle = AsyncMock()
|
||||
device.set_brightness = AsyncMock()
|
||||
mock_device.is_device_supported = MagicMock(return_value=(True, ""))
|
||||
mock_device.initiate_device = AsyncMock(return_value=device)
|
||||
|
||||
@@ -86,16 +108,16 @@ def mock_system_nexa_2_device() -> Generator[MagicMock]:
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_config_entry() -> MockConfigEntry:
|
||||
def mock_config_entry(device_info: dict[str, Any]) -> MockConfigEntry:
|
||||
"""Return a mock config entry."""
|
||||
return MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
unique_id="test_device_id",
|
||||
unique_id=device_info["unique_id"],
|
||||
data={
|
||||
CONF_HOST: "10.0.0.100",
|
||||
CONF_NAME: "Test Device",
|
||||
CONF_DEVICE_ID: "test_device_id",
|
||||
CONF_MODEL: "Test Model",
|
||||
CONF_HOST: device_info["host"],
|
||||
CONF_NAME: device_info["name"],
|
||||
CONF_DEVICE_ID: device_info["unique_id"],
|
||||
CONF_MODEL: device_info["model"],
|
||||
},
|
||||
)
|
||||
|
||||
@@ -121,5 +143,5 @@ def mock_zeroconf_discovery_info():
|
||||
name="systemnexa2_test._systemnexa2._tcp.local.",
|
||||
port=80,
|
||||
type="_systemnexa2._tcp.local.",
|
||||
properties={"id": "test_device_id", "model": "Test Model", "version": "1.0.0"},
|
||||
properties={"id": "aabbccddee02", "model": "WPO-01", "version": "1.0.0"},
|
||||
)
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
# serializer version: 1
|
||||
# name: test_light_entities[True][light.in_wall_dimmer_light-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'supported_color_modes': list([
|
||||
<ColorMode.BRIGHTNESS: 'brightness'>,
|
||||
]),
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'light',
|
||||
'entity_category': None,
|
||||
'entity_id': 'light.in_wall_dimmer_light',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Light',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Light',
|
||||
'platform': 'systemnexa2',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'light',
|
||||
'unique_id': 'aabbccddee01-light',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_light_entities[True][light.in_wall_dimmer_light-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'brightness': 128,
|
||||
'color_mode': <ColorMode.BRIGHTNESS: 'brightness'>,
|
||||
'friendly_name': 'In-Wall Dimmer Light',
|
||||
'supported_color_modes': list([
|
||||
<ColorMode.BRIGHTNESS: 'brightness'>,
|
||||
]),
|
||||
'supported_features': <LightEntityFeature: 0>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'light.in_wall_dimmer_light',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'on',
|
||||
})
|
||||
# ---
|
||||
@@ -1,5 +1,5 @@
|
||||
# serializer version: 1
|
||||
# name: test_switch_entities[switch.test_device_433_mhz-entry]
|
||||
# name: test_switch_entities[False][switch.outdoor_smart_plug_433_mhz-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
@@ -12,7 +12,7 @@
|
||||
'disabled_by': None,
|
||||
'domain': 'switch',
|
||||
'entity_category': <EntityCategory.CONFIG: 'config'>,
|
||||
'entity_id': 'switch.test_device_433_mhz',
|
||||
'entity_id': 'switch.outdoor_smart_plug_433_mhz',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
@@ -31,25 +31,25 @@
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': '433mhz',
|
||||
'unique_id': 'test_device_id-433Mhz',
|
||||
'unique_id': 'aabbccddee02-433Mhz',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_switch_entities[switch.test_device_433_mhz-state]
|
||||
# name: test_switch_entities[False][switch.outdoor_smart_plug_433_mhz-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'switch',
|
||||
'friendly_name': 'Test Device 433 MHz',
|
||||
'friendly_name': 'Outdoor Smart Plug 433 MHz',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'switch.test_device_433_mhz',
|
||||
'entity_id': 'switch.outdoor_smart_plug_433_mhz',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'on',
|
||||
})
|
||||
# ---
|
||||
# name: test_switch_entities[switch.test_device_cloud_access-entry]
|
||||
# name: test_switch_entities[False][switch.outdoor_smart_plug_cloud_access-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
@@ -62,7 +62,7 @@
|
||||
'disabled_by': None,
|
||||
'domain': 'switch',
|
||||
'entity_category': <EntityCategory.CONFIG: 'config'>,
|
||||
'entity_id': 'switch.test_device_cloud_access',
|
||||
'entity_id': 'switch.outdoor_smart_plug_cloud_access',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
@@ -81,25 +81,25 @@
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'cloud_access',
|
||||
'unique_id': 'test_device_id-Cloud Access',
|
||||
'unique_id': 'aabbccddee02-Cloud Access',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_switch_entities[switch.test_device_cloud_access-state]
|
||||
# name: test_switch_entities[False][switch.outdoor_smart_plug_cloud_access-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'switch',
|
||||
'friendly_name': 'Test Device Cloud access',
|
||||
'friendly_name': 'Outdoor Smart Plug Cloud access',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'switch.test_device_cloud_access',
|
||||
'entity_id': 'switch.outdoor_smart_plug_cloud_access',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
# name: test_switch_entities[switch.test_device_relay_1-entry]
|
||||
# name: test_switch_entities[False][switch.outdoor_smart_plug_relay-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
@@ -112,7 +112,7 @@
|
||||
'disabled_by': None,
|
||||
'domain': 'switch',
|
||||
'entity_category': None,
|
||||
'entity_id': 'switch.test_device_relay_1',
|
||||
'entity_id': 'switch.outdoor_smart_plug_relay',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
@@ -120,28 +120,28 @@
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Relay 1',
|
||||
'object_id_base': 'Relay',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Relay 1',
|
||||
'original_name': 'Relay',
|
||||
'platform': 'systemnexa2',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'relay_1',
|
||||
'unique_id': 'test_device_id-relay_1',
|
||||
'unique_id': 'aabbccddee02-relay_1',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_switch_entities[switch.test_device_relay_1-state]
|
||||
# name: test_switch_entities[False][switch.outdoor_smart_plug_relay-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'Test Device Relay 1',
|
||||
'friendly_name': 'Outdoor Smart Plug Relay',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'switch.test_device_relay_1',
|
||||
'entity_id': 'switch.outdoor_smart_plug_relay',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
|
||||
@@ -30,14 +30,14 @@ async def test_full_flow(hass: HomeAssistant, mock_setup_entry: AsyncMock) -> No
|
||||
result["flow_id"], {CONF_HOST: "10.0.0.131"}
|
||||
)
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == "Test Device (Test Model)"
|
||||
assert result["title"] == "Outdoor Smart Plug (WPO-01)"
|
||||
assert result["data"] == {
|
||||
CONF_HOST: "10.0.0.131",
|
||||
CONF_NAME: "Test Device",
|
||||
CONF_DEVICE_ID: "test_device_id",
|
||||
CONF_MODEL: "Test Model",
|
||||
CONF_NAME: "Outdoor Smart Plug",
|
||||
CONF_DEVICE_ID: "aabbccddee02",
|
||||
CONF_MODEL: "WPO-01",
|
||||
}
|
||||
assert result["result"].unique_id == "test_device_id"
|
||||
assert result["result"].unique_id == "aabbccddee02"
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ async def test_connection_error_and_recovery(
|
||||
result["flow_id"], {CONF_HOST: "10.0.0.131"}
|
||||
)
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == "Test Device (Test Model)"
|
||||
assert result["title"] == "Outdoor Smart Plug (WPO-01)"
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
@@ -164,12 +164,12 @@ async def test_valid_hostname(hass: HomeAssistant, mock_setup_entry: AsyncMock)
|
||||
result["flow_id"], {CONF_HOST: "valid-hostname.local"}
|
||||
)
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == "Test Device (Test Model)"
|
||||
assert result["title"] == "Outdoor Smart Plug (WPO-01)"
|
||||
assert result["data"] == {
|
||||
CONF_HOST: "valid-hostname.local",
|
||||
CONF_NAME: "Test Device",
|
||||
CONF_DEVICE_ID: "test_device_id",
|
||||
CONF_MODEL: "Test Model",
|
||||
CONF_NAME: "Outdoor Smart Plug",
|
||||
CONF_DEVICE_ID: "aabbccddee02",
|
||||
CONF_MODEL: "WPO-01",
|
||||
}
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
@@ -192,7 +192,7 @@ async def test_unsupported_device(
|
||||
assert result["type"] is FlowResultType.ABORT
|
||||
assert result["reason"] == "unsupported_model"
|
||||
assert result["description_placeholders"] == {
|
||||
"model": "Test Model",
|
||||
"model": "WPO-01",
|
||||
"sw_version": "Test Model Version",
|
||||
}
|
||||
|
||||
@@ -215,12 +215,12 @@ async def test_zeroconf_discovery(
|
||||
result["flow_id"], user_input={}
|
||||
)
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == "systemnexa2_test (Test Model)"
|
||||
assert result["title"] == "systemnexa2_test (WPO-01)"
|
||||
assert result["data"] == {
|
||||
CONF_HOST: "10.0.0.131",
|
||||
CONF_NAME: "systemnexa2_test",
|
||||
CONF_DEVICE_ID: "test_device_id",
|
||||
CONF_MODEL: "Test Model",
|
||||
CONF_DEVICE_ID: "aabbccddee02",
|
||||
CONF_MODEL: "WPO-01",
|
||||
}
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
@@ -249,8 +249,8 @@ async def test_device_with_none_values(
|
||||
device = mock_system_nexa_2_device.return_value
|
||||
# Create new InformationData with None unique_id
|
||||
device.info_data = InformationData(
|
||||
name="Test Device",
|
||||
model="Test Model",
|
||||
name="Outdoor Smart Plug",
|
||||
model="WPO-01",
|
||||
unique_id=None,
|
||||
sw_version="Test Model Version",
|
||||
hw_version="Test HW Version",
|
||||
@@ -281,7 +281,7 @@ async def test_zeroconf_discovery_none_values(hass: HomeAssistant) -> None:
|
||||
type="_systemnexa2._tcp.local.",
|
||||
properties={
|
||||
"id": None,
|
||||
"model": "Test Model",
|
||||
"model": "WPO-01",
|
||||
"version": "1.0.0",
|
||||
},
|
||||
)
|
||||
|
||||
@@ -0,0 +1,302 @@
|
||||
"""Test the System Nexa 2 light platform."""
|
||||
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
from sn2 import ConnectionStatus, StateChange
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.components.light import ATTR_BRIGHTNESS, DOMAIN as LIGHT_DOMAIN
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID,
|
||||
SERVICE_TURN_OFF,
|
||||
SERVICE_TURN_ON,
|
||||
STATE_OFF,
|
||||
STATE_ON,
|
||||
STATE_UNAVAILABLE,
|
||||
Platform,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
import homeassistant.helpers.entity_registry as er
|
||||
|
||||
from . import find_update_callback
|
||||
|
||||
from tests.common import MockConfigEntry, snapshot_platform
|
||||
|
||||
|
||||
@pytest.mark.parametrize("dimmable", [True], indirect=True)
|
||||
async def test_light_entities(
|
||||
hass: HomeAssistant,
|
||||
snapshot: SnapshotAssertion,
|
||||
entity_registry: er.EntityRegistry,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_system_nexa_2_device: MagicMock,
|
||||
) -> None:
|
||||
"""Test the light entities."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
# Only load the light platform for snapshot testing
|
||||
with patch(
|
||||
"homeassistant.components.systemnexa2.PLATFORMS",
|
||||
[Platform.LIGHT],
|
||||
):
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
await snapshot_platform(
|
||||
hass, entity_registry, snapshot, mock_config_entry.entry_id
|
||||
)
|
||||
|
||||
|
||||
async def test_light_only_for_dimmable_devices(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_system_nexa_2_device: MagicMock,
|
||||
) -> None:
|
||||
"""Test that light entity is only created for dimmable devices."""
|
||||
# The mock_system_nexa_2_device has dimmable=False
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Light entity should NOT exist for non-dimmable device
|
||||
state = hass.states.get("light.outdoor_smart_plug")
|
||||
assert state is None
|
||||
|
||||
|
||||
@pytest.mark.parametrize("dimmable", [True], indirect=True)
|
||||
async def test_light_control_operations(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_system_nexa_2_device: MagicMock,
|
||||
) -> None:
|
||||
"""Test all light control operations (on/off/toggle/dim)."""
|
||||
device = mock_system_nexa_2_device.return_value
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entity_id = "light.in_wall_dimmer_light"
|
||||
|
||||
# Verify initial state (should be on with 50% brightness from fixture)
|
||||
state = hass.states.get(entity_id)
|
||||
assert state is not None
|
||||
assert state.state == STATE_ON
|
||||
|
||||
# Test turn on without brightness
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
device.turn_on.assert_called_once()
|
||||
device.set_brightness.assert_not_called()
|
||||
device.turn_on.reset_mock()
|
||||
|
||||
# Test turn on with brightness=128 (50% in HA scale 0-255)
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_BRIGHTNESS: 128},
|
||||
blocking=True,
|
||||
)
|
||||
device.set_brightness.assert_called_once_with(128 / 255)
|
||||
device.turn_on.assert_not_called()
|
||||
device.set_brightness.reset_mock()
|
||||
|
||||
# Test turn on with brightness=255 (100% in HA scale)
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_BRIGHTNESS: 255},
|
||||
blocking=True,
|
||||
)
|
||||
device.set_brightness.assert_called_once_with(255 / 255)
|
||||
device.set_brightness.reset_mock()
|
||||
|
||||
# Test turn on with brightness=1 (minimum non-zero in HA scale)
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_BRIGHTNESS: 1},
|
||||
blocking=True,
|
||||
)
|
||||
device.set_brightness.assert_called_once_with(1 / 255)
|
||||
device.set_brightness.reset_mock()
|
||||
|
||||
# Test turn off
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_OFF,
|
||||
{ATTR_ENTITY_ID: entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
device.turn_off.assert_called_once()
|
||||
device.turn_off.reset_mock()
|
||||
|
||||
# No reason to test toggle service as its an internal function using turn_on/off
|
||||
|
||||
|
||||
@pytest.mark.parametrize("dimmable", [True], indirect=True)
|
||||
async def test_light_brightness_property(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_system_nexa_2_device: MagicMock,
|
||||
) -> None:
|
||||
"""Test light brightness property conversion."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Find the callback that was registered with the device
|
||||
update_callback = find_update_callback(mock_system_nexa_2_device)
|
||||
|
||||
# Test with state = 0.5 (50% in device scale, should be 128 in HA scale)
|
||||
await update_callback(StateChange(state=0.5))
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("light.in_wall_dimmer_light")
|
||||
assert state is not None
|
||||
assert state.state == STATE_ON
|
||||
assert state.attributes.get(ATTR_BRIGHTNESS) == 128
|
||||
|
||||
# Test with state = 1.0 (100% in device scale, should be 255 in HA scale)
|
||||
await update_callback(StateChange(state=1.0))
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("light.in_wall_dimmer_light")
|
||||
assert state is not None
|
||||
assert state.state == STATE_ON
|
||||
assert state.attributes.get(ATTR_BRIGHTNESS) == 255
|
||||
|
||||
# Test with state = 0.0 (0% - light should be off)
|
||||
await update_callback(StateChange(state=0.0))
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("light.in_wall_dimmer_light")
|
||||
assert state is not None
|
||||
assert state.state == STATE_OFF
|
||||
|
||||
# Test with state = 0.1 (10% in device scale, should be 26 in HA scale)
|
||||
await update_callback(StateChange(state=0.1))
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("light.in_wall_dimmer_light")
|
||||
assert state is not None
|
||||
assert state.state == STATE_ON
|
||||
assert state.attributes.get(ATTR_BRIGHTNESS) == 26
|
||||
|
||||
|
||||
@pytest.mark.parametrize("dimmable", [True], indirect=True)
|
||||
async def test_light_is_on_property(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_system_nexa_2_device: MagicMock,
|
||||
) -> None:
|
||||
"""Test light is_on property."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Find the callback that was registered with the device
|
||||
update_callback = find_update_callback(mock_system_nexa_2_device)
|
||||
|
||||
# Test with state > 0 (light is on)
|
||||
await update_callback(StateChange(state=0.5))
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("light.in_wall_dimmer_light")
|
||||
assert state is not None
|
||||
assert state.state == STATE_ON
|
||||
|
||||
# Test with state = 0 (light is off)
|
||||
await update_callback(StateChange(state=0.0))
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("light.in_wall_dimmer_light")
|
||||
assert state is not None
|
||||
assert state.state == STATE_OFF
|
||||
|
||||
|
||||
@pytest.mark.parametrize("dimmable", [True], indirect=True)
|
||||
async def test_coordinator_connection_status(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_system_nexa_2_device: MagicMock,
|
||||
) -> None:
|
||||
"""Test coordinator handles connection status updates for light."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Find the callback that was registered with the device
|
||||
update_callback = find_update_callback(mock_system_nexa_2_device)
|
||||
|
||||
# Initially, the light should be on (state=0.5 from fixture)
|
||||
state = hass.states.get("light.in_wall_dimmer_light")
|
||||
assert state is not None
|
||||
assert state.state == STATE_ON
|
||||
|
||||
# Simulate device disconnection
|
||||
await update_callback(ConnectionStatus(connected=False))
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("light.in_wall_dimmer_light")
|
||||
assert state is not None
|
||||
assert state.state == STATE_UNAVAILABLE
|
||||
|
||||
# Simulate reconnection and state update
|
||||
await update_callback(ConnectionStatus(connected=True))
|
||||
await update_callback(StateChange(state=0.75))
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("light.in_wall_dimmer_light")
|
||||
assert state is not None
|
||||
assert state.state == STATE_ON
|
||||
assert state.attributes.get(ATTR_BRIGHTNESS) == 191 # 0.75 * 255 ≈ 191
|
||||
|
||||
|
||||
@pytest.mark.parametrize("dimmable", [True], indirect=True)
|
||||
async def test_coordinator_state_change(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_system_nexa_2_device: MagicMock,
|
||||
) -> None:
|
||||
"""Test coordinator handles state change updates for light."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Find the callback that was registered with the device
|
||||
update_callback = find_update_callback(mock_system_nexa_2_device)
|
||||
|
||||
# Change state to off (0.0)
|
||||
await update_callback(StateChange(state=0.0))
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("light.in_wall_dimmer_light")
|
||||
assert state is not None
|
||||
assert state.state == STATE_OFF
|
||||
|
||||
# Change state to 25% (0.25)
|
||||
await update_callback(StateChange(state=0.25))
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("light.in_wall_dimmer_light")
|
||||
assert state is not None
|
||||
assert state.state == STATE_ON
|
||||
assert state.attributes.get(ATTR_BRIGHTNESS) == 64 # 0.25 * 255 ≈ 64
|
||||
|
||||
# Change state to full brightness (1.0)
|
||||
await update_callback(StateChange(state=1.0))
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("light.in_wall_dimmer_light")
|
||||
assert state is not None
|
||||
assert state.state == STATE_ON
|
||||
assert state.attributes.get(ATTR_BRIGHTNESS) == 255
|
||||
@@ -1,9 +1,9 @@
|
||||
"""Test the System Nexa 2 switch platform."""
|
||||
|
||||
from unittest.mock import AsyncMock, MagicMock
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
from sn2 import ConnectionStatus, OnOffSetting, SettingsUpdate, StateChange
|
||||
from sn2 import ConnectionStatus, SettingsUpdate, StateChange
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
|
||||
@@ -52,18 +52,16 @@ async def test_switch_turn_on_off_toggle(
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Get the coordinator and update it with state
|
||||
entry = hass.config_entries.async_get_entry(mock_config_entry.entry_id)
|
||||
assert entry
|
||||
coordinator = entry.runtime_data
|
||||
await coordinator._async_handle_update(StateChange(state=0.0))
|
||||
# Find the callback that was registered with the device
|
||||
update_callback = find_update_callback(mock_system_nexa_2_device)
|
||||
await update_callback(StateChange(state=0.0))
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Test turn on
|
||||
await hass.services.async_call(
|
||||
SWITCH_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: "switch.test_device_relay_1"},
|
||||
{ATTR_ENTITY_ID: "switch.outdoor_smart_plug_relay"},
|
||||
blocking=True,
|
||||
)
|
||||
device.turn_on.assert_called_once()
|
||||
@@ -72,7 +70,7 @@ async def test_switch_turn_on_off_toggle(
|
||||
await hass.services.async_call(
|
||||
SWITCH_DOMAIN,
|
||||
SERVICE_TURN_OFF,
|
||||
{ATTR_ENTITY_ID: "switch.test_device_relay_1"},
|
||||
{ATTR_ENTITY_ID: "switch.outdoor_smart_plug_relay"},
|
||||
blocking=True,
|
||||
)
|
||||
device.turn_off.assert_called_once()
|
||||
@@ -81,7 +79,7 @@ async def test_switch_turn_on_off_toggle(
|
||||
await hass.services.async_call(
|
||||
SWITCH_DOMAIN,
|
||||
SERVICE_TOGGLE,
|
||||
{ATTR_ENTITY_ID: "switch.test_device_relay_1"},
|
||||
{ATTR_ENTITY_ID: "switch.outdoor_smart_plug_relay"},
|
||||
blocking=True,
|
||||
)
|
||||
device.toggle.assert_called_once()
|
||||
@@ -98,22 +96,23 @@ async def test_switch_is_on_property(
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Get the coordinator and update it with state
|
||||
entry = hass.config_entries.async_get_entry(mock_config_entry.entry_id)
|
||||
coordinator = entry.runtime_data
|
||||
# Find the callback that was registered with the device
|
||||
update_callback = find_update_callback(mock_system_nexa_2_device)
|
||||
|
||||
# Test with state = 1.0 (on)
|
||||
await coordinator._async_handle_update(StateChange(state=1.0))
|
||||
await update_callback(StateChange(state=1.0))
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("switch.test_device_relay_1")
|
||||
state = hass.states.get("switch.outdoor_smart_plug_relay")
|
||||
assert state is not None
|
||||
assert state.state == "on"
|
||||
|
||||
# Test with state = 0.0 (off)
|
||||
await coordinator._async_handle_update(StateChange(state=0.0))
|
||||
await update_callback(StateChange(state=0.0))
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("switch.test_device_relay_1")
|
||||
state = hass.states.get("switch.outdoor_smart_plug_relay")
|
||||
assert state is not None
|
||||
assert state.state == "off"
|
||||
|
||||
|
||||
@@ -125,39 +124,26 @@ async def test_configuration_switches(
|
||||
"""Test configuration switch entities."""
|
||||
device = mock_system_nexa_2_device.return_value
|
||||
|
||||
# Create mock OnOffSettings with keys matching SWITCH_TYPES
|
||||
mock_setting_433mhz = MagicMock(spec=OnOffSetting)
|
||||
mock_setting_433mhz.name = "433Mhz" # Must match key in SWITCH_TYPES
|
||||
mock_setting_433mhz.enable = AsyncMock()
|
||||
mock_setting_433mhz.disable = AsyncMock()
|
||||
mock_setting_433mhz.is_enabled = MagicMock(return_value=True)
|
||||
|
||||
mock_setting_cloud = MagicMock(spec=OnOffSetting)
|
||||
mock_setting_cloud.name = "Cloud Access" # Must match key in SWITCH_TYPES
|
||||
mock_setting_cloud.enable = AsyncMock()
|
||||
mock_setting_cloud.disable = AsyncMock()
|
||||
mock_setting_cloud.is_enabled = MagicMock(return_value=False)
|
||||
|
||||
# Set settings before setup
|
||||
device.settings = [mock_setting_433mhz, mock_setting_cloud]
|
||||
# Settings are already configured in the fixture
|
||||
mock_setting_433mhz = device.settings[0] # 433Mhz
|
||||
mock_setting_cloud = device.settings[1] # Cloud Access
|
||||
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Make coordinator data available
|
||||
entry = hass.config_entries.async_get_entry(mock_config_entry.entry_id)
|
||||
coordinator = entry.runtime_data
|
||||
await coordinator._async_handle_update(StateChange(state=1.0))
|
||||
# Find the callback that was registered with the device
|
||||
update_callback = find_update_callback(mock_system_nexa_2_device)
|
||||
await update_callback(StateChange(state=1.0))
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Check 433mhz switch state (should be on)
|
||||
state = hass.states.get("switch.test_device_433_mhz")
|
||||
state = hass.states.get("switch.outdoor_smart_plug_433_mhz")
|
||||
assert state is not None
|
||||
assert state.state == "on"
|
||||
|
||||
# Check cloud_access switch state (should be off)
|
||||
state = hass.states.get("switch.test_device_cloud_access")
|
||||
state = hass.states.get("switch.outdoor_smart_plug_cloud_access")
|
||||
assert state is not None
|
||||
assert state.state == "off"
|
||||
|
||||
@@ -165,7 +151,7 @@ async def test_configuration_switches(
|
||||
await hass.services.async_call(
|
||||
SWITCH_DOMAIN,
|
||||
SERVICE_TURN_OFF,
|
||||
{ATTR_ENTITY_ID: "switch.test_device_433_mhz"},
|
||||
{ATTR_ENTITY_ID: "switch.outdoor_smart_plug_433_mhz"},
|
||||
blocking=True,
|
||||
)
|
||||
mock_setting_433mhz.disable.assert_called_once_with(device)
|
||||
@@ -174,7 +160,7 @@ async def test_configuration_switches(
|
||||
await hass.services.async_call(
|
||||
SWITCH_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: "switch.test_device_cloud_access"},
|
||||
{ATTR_ENTITY_ID: "switch.outdoor_smart_plug_cloud_access"},
|
||||
blocking=True,
|
||||
)
|
||||
mock_setting_cloud.enable.assert_called_once_with(device)
|
||||
@@ -193,8 +179,8 @@ async def test_coordinator_connection_status(
|
||||
# Find the callback that was registered with the device
|
||||
update_callback = find_update_callback(mock_system_nexa_2_device)
|
||||
|
||||
# Initially, the relay switch should be off (state=1.0 from fixture)
|
||||
state = hass.states.get("switch.test_device_relay_1")
|
||||
# Initially, the relay switch should be on (state=1.0 from fixture)
|
||||
state = hass.states.get("switch.outdoor_smart_plug_relay")
|
||||
assert state is not None
|
||||
assert state.state == STATE_ON
|
||||
|
||||
@@ -202,7 +188,8 @@ async def test_coordinator_connection_status(
|
||||
await update_callback(ConnectionStatus(connected=False))
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("switch.test_device_relay_1")
|
||||
state = hass.states.get("switch.outdoor_smart_plug_relay")
|
||||
assert state is not None
|
||||
assert state.state == STATE_UNAVAILABLE
|
||||
|
||||
# Simulate reconnection and state update
|
||||
@@ -210,7 +197,8 @@ async def test_coordinator_connection_status(
|
||||
await update_callback(StateChange(state=1.0))
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("switch.test_device_relay_1")
|
||||
state = hass.states.get("switch.outdoor_smart_plug_relay")
|
||||
assert state is not None
|
||||
assert state.state == STATE_ON
|
||||
|
||||
|
||||
@@ -231,7 +219,7 @@ async def test_coordinator_state_change(
|
||||
await update_callback(StateChange(state=0.0))
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("switch.test_device_relay_1")
|
||||
state = hass.states.get("switch.outdoor_smart_plug_relay")
|
||||
assert state is not None
|
||||
assert state.state == STATE_OFF
|
||||
|
||||
@@ -239,7 +227,8 @@ async def test_coordinator_state_change(
|
||||
await update_callback(StateChange(state=1.0))
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("switch.test_device_relay_1")
|
||||
state = hass.states.get("switch.outdoor_smart_plug_relay")
|
||||
assert state is not None
|
||||
assert state.state == STATE_ON
|
||||
|
||||
|
||||
@@ -257,7 +246,7 @@ async def test_coordinator_settings_update(
|
||||
update_callback = find_update_callback(mock_system_nexa_2_device)
|
||||
|
||||
# Get initial state of 433Mhz switch (should be on from fixture)
|
||||
state = hass.states.get("switch.test_device_433_mhz")
|
||||
state = hass.states.get("switch.outdoor_smart_plug_433_mhz")
|
||||
assert state is not None
|
||||
assert state.state == STATE_ON
|
||||
|
||||
@@ -271,5 +260,6 @@ async def test_coordinator_settings_update(
|
||||
await update_callback(StateChange(state=1.0))
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("switch.test_device_433_mhz")
|
||||
state = hass.states.get("switch.outdoor_smart_plug_433_mhz")
|
||||
assert state is not None
|
||||
assert state.state == STATE_OFF
|
||||
|
||||
Reference in New Issue
Block a user