mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 05:07:41 +00:00
Implemented RestoreEntity for Dynalite (#73911)
* Implemented RestoreEntity Merged commit conflict * removed accidental change * Update homeassistant/components/dynalite/dynalitebase.py Co-authored-by: Erik Montnemery <erik@montnemery.com> * added tests for the state * added tests for switch state * moved to ATTR_x and STATE_x instead of strings some fixes to test_cover * moved blind to DEVICE_CLASS_BLIND * used correct constant instead of deprecated * Implemented RestoreEntity * removed accidental change * added tests for the state * added tests for switch state * moved to ATTR_x and STATE_x instead of strings some fixes to test_cover * fixed isort issue from merge Co-authored-by: Erik Montnemery <erik@montnemery.com>
This commit is contained in:
parent
4bb1f4ec79
commit
b6c27585c7
@ -2,7 +2,12 @@
|
|||||||
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from homeassistant.components.cover import DEVICE_CLASSES, CoverDeviceClass, CoverEntity
|
from homeassistant.components.cover import (
|
||||||
|
ATTR_CURRENT_POSITION,
|
||||||
|
DEVICE_CLASSES,
|
||||||
|
CoverDeviceClass,
|
||||||
|
CoverEntity,
|
||||||
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
@ -78,6 +83,12 @@ class DynaliteCover(DynaliteBase, CoverEntity):
|
|||||||
"""Stop the cover."""
|
"""Stop the cover."""
|
||||||
await self._device.async_stop_cover(**kwargs)
|
await self._device.async_stop_cover(**kwargs)
|
||||||
|
|
||||||
|
def initialize_state(self, state):
|
||||||
|
"""Initialize the state from cache."""
|
||||||
|
target_level = state.attributes.get(ATTR_CURRENT_POSITION)
|
||||||
|
if target_level is not None:
|
||||||
|
self._device.init_level(target_level)
|
||||||
|
|
||||||
|
|
||||||
class DynaliteCoverWithTilt(DynaliteCover):
|
class DynaliteCoverWithTilt(DynaliteCover):
|
||||||
"""Representation of a Dynalite Channel as a Home Assistant Cover that uses up and down for tilt."""
|
"""Representation of a Dynalite Channel as a Home Assistant Cover that uses up and down for tilt."""
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
"""Support for the Dynalite devices as entities."""
|
"""Support for the Dynalite devices as entities."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
from collections.abc import Callable
|
from collections.abc import Callable
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||||
from homeassistant.helpers.entity import DeviceInfo, Entity
|
from homeassistant.helpers.entity import DeviceInfo
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
from homeassistant.helpers.restore_state import RestoreEntity
|
||||||
|
|
||||||
from .bridge import DynaliteBridge
|
from .bridge import DynaliteBridge
|
||||||
from .const import DOMAIN, LOGGER
|
from .const import DOMAIN, LOGGER
|
||||||
@ -36,7 +38,7 @@ def async_setup_entry_base(
|
|||||||
bridge.register_add_devices(platform, async_add_entities_platform)
|
bridge.register_add_devices(platform, async_add_entities_platform)
|
||||||
|
|
||||||
|
|
||||||
class DynaliteBase(Entity):
|
class DynaliteBase(RestoreEntity, ABC):
|
||||||
"""Base class for the Dynalite entities."""
|
"""Base class for the Dynalite entities."""
|
||||||
|
|
||||||
def __init__(self, device: Any, bridge: DynaliteBridge) -> None:
|
def __init__(self, device: Any, bridge: DynaliteBridge) -> None:
|
||||||
@ -70,8 +72,16 @@ class DynaliteBase(Entity):
|
|||||||
)
|
)
|
||||||
|
|
||||||
async def async_added_to_hass(self) -> None:
|
async def async_added_to_hass(self) -> None:
|
||||||
"""Added to hass so need to register to dispatch."""
|
"""Added to hass so need to restore state and register to dispatch."""
|
||||||
# register for device specific update
|
# register for device specific update
|
||||||
|
await super().async_added_to_hass()
|
||||||
|
|
||||||
|
cur_state = await self.async_get_last_state()
|
||||||
|
if cur_state:
|
||||||
|
self.initialize_state(cur_state)
|
||||||
|
else:
|
||||||
|
LOGGER.info("Restore state not available for %s", self.entity_id)
|
||||||
|
|
||||||
self._unsub_dispatchers.append(
|
self._unsub_dispatchers.append(
|
||||||
async_dispatcher_connect(
|
async_dispatcher_connect(
|
||||||
self.hass,
|
self.hass,
|
||||||
@ -88,6 +98,10 @@ class DynaliteBase(Entity):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def initialize_state(self, state):
|
||||||
|
"""Initialize the state from cache."""
|
||||||
|
|
||||||
async def async_will_remove_from_hass(self) -> None:
|
async def async_will_remove_from_hass(self) -> None:
|
||||||
"""Unregister signal dispatch listeners when being removed."""
|
"""Unregister signal dispatch listeners when being removed."""
|
||||||
for unsub in self._unsub_dispatchers:
|
for unsub in self._unsub_dispatchers:
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from homeassistant.components.light import ColorMode, LightEntity
|
from homeassistant.components.light import ATTR_BRIGHTNESS, ColorMode, LightEntity
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
@ -44,3 +44,9 @@ class DynaliteLight(DynaliteBase, LightEntity):
|
|||||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||||
"""Turn the light off."""
|
"""Turn the light off."""
|
||||||
await self._device.async_turn_off(**kwargs)
|
await self._device.async_turn_off(**kwargs)
|
||||||
|
|
||||||
|
def initialize_state(self, state):
|
||||||
|
"""Initialize the state from cache."""
|
||||||
|
target_level = state.attributes.get(ATTR_BRIGHTNESS)
|
||||||
|
if target_level is not None:
|
||||||
|
self._device.init_level(target_level)
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/integrations/dynalite",
|
"documentation": "https://www.home-assistant.io/integrations/dynalite",
|
||||||
"codeowners": ["@ziv1234"],
|
"codeowners": ["@ziv1234"],
|
||||||
"requirements": ["dynalite_devices==0.1.46"],
|
"requirements": ["dynalite_devices==0.1.47"],
|
||||||
"iot_class": "local_push",
|
"iot_class": "local_push",
|
||||||
"loggers": ["dynalite_devices_lib"]
|
"loggers": ["dynalite_devices_lib"]
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ from typing import Any
|
|||||||
|
|
||||||
from homeassistant.components.switch import SwitchEntity
|
from homeassistant.components.switch import SwitchEntity
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.const import STATE_ON
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
@ -36,3 +37,8 @@ class DynaliteSwitch(DynaliteBase, SwitchEntity):
|
|||||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||||
"""Turn the switch off."""
|
"""Turn the switch off."""
|
||||||
await self._device.async_turn_off()
|
await self._device.async_turn_off()
|
||||||
|
|
||||||
|
def initialize_state(self, state):
|
||||||
|
"""Initialize the state from cache."""
|
||||||
|
target_level = 1 if state.state == STATE_ON else 0
|
||||||
|
self._device.init_level(target_level)
|
||||||
|
@ -609,7 +609,7 @@ dwdwfsapi==1.0.5
|
|||||||
dweepy==0.3.0
|
dweepy==0.3.0
|
||||||
|
|
||||||
# homeassistant.components.dynalite
|
# homeassistant.components.dynalite
|
||||||
dynalite_devices==0.1.46
|
dynalite_devices==0.1.47
|
||||||
|
|
||||||
# homeassistant.components.rainforest_eagle
|
# homeassistant.components.rainforest_eagle
|
||||||
eagle100==0.1.1
|
eagle100==0.1.1
|
||||||
|
@ -471,7 +471,7 @@ doorbirdpy==2.1.0
|
|||||||
dsmr_parser==0.33
|
dsmr_parser==0.33
|
||||||
|
|
||||||
# homeassistant.components.dynalite
|
# homeassistant.components.dynalite
|
||||||
dynalite_devices==0.1.46
|
dynalite_devices==0.1.47
|
||||||
|
|
||||||
# homeassistant.components.rainforest_eagle
|
# homeassistant.components.rainforest_eagle
|
||||||
eagle100==0.1.1
|
eagle100==0.1.1
|
||||||
|
@ -70,10 +70,12 @@ async def test_add_devices_then_register(hass):
|
|||||||
device1.category = "light"
|
device1.category = "light"
|
||||||
device1.name = "NAME"
|
device1.name = "NAME"
|
||||||
device1.unique_id = "unique1"
|
device1.unique_id = "unique1"
|
||||||
|
device1.brightness = 1
|
||||||
device2 = Mock()
|
device2 = Mock()
|
||||||
device2.category = "switch"
|
device2.category = "switch"
|
||||||
device2.name = "NAME2"
|
device2.name = "NAME2"
|
||||||
device2.unique_id = "unique2"
|
device2.unique_id = "unique2"
|
||||||
|
device2.brightness = 1
|
||||||
new_device_func([device1, device2])
|
new_device_func([device1, device2])
|
||||||
device3 = Mock()
|
device3 = Mock()
|
||||||
device3.category = "switch"
|
device3.category = "switch"
|
||||||
@ -103,10 +105,12 @@ async def test_register_then_add_devices(hass):
|
|||||||
device1.category = "light"
|
device1.category = "light"
|
||||||
device1.name = "NAME"
|
device1.name = "NAME"
|
||||||
device1.unique_id = "unique1"
|
device1.unique_id = "unique1"
|
||||||
|
device1.brightness = 1
|
||||||
device2 = Mock()
|
device2 = Mock()
|
||||||
device2.category = "switch"
|
device2.category = "switch"
|
||||||
device2.name = "NAME2"
|
device2.name = "NAME2"
|
||||||
device2.unique_id = "unique2"
|
device2.unique_id = "unique2"
|
||||||
|
device2.brightness = 1
|
||||||
new_device_func([device1, device2])
|
new_device_func([device1, device2])
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert hass.states.get("light.name")
|
assert hass.states.get("light.name")
|
||||||
|
@ -1,8 +1,25 @@
|
|||||||
"""Test Dynalite cover."""
|
"""Test Dynalite cover."""
|
||||||
|
from unittest.mock import Mock
|
||||||
|
|
||||||
from dynalite_devices_lib.cover import DynaliteTimeCoverWithTiltDevice
|
from dynalite_devices_lib.cover import DynaliteTimeCoverWithTiltDevice
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant.const import ATTR_DEVICE_CLASS, ATTR_FRIENDLY_NAME
|
from homeassistant.components.cover import (
|
||||||
|
ATTR_CURRENT_POSITION,
|
||||||
|
ATTR_CURRENT_TILT_POSITION,
|
||||||
|
ATTR_POSITION,
|
||||||
|
ATTR_TILT_POSITION,
|
||||||
|
CoverDeviceClass,
|
||||||
|
)
|
||||||
|
from homeassistant.const import (
|
||||||
|
ATTR_DEVICE_CLASS,
|
||||||
|
ATTR_FRIENDLY_NAME,
|
||||||
|
STATE_CLOSED,
|
||||||
|
STATE_CLOSING,
|
||||||
|
STATE_OPEN,
|
||||||
|
STATE_OPENING,
|
||||||
|
)
|
||||||
|
from homeassistant.core import State
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
|
|
||||||
from .common import (
|
from .common import (
|
||||||
@ -14,12 +31,25 @@ from .common import (
|
|||||||
run_service_tests,
|
run_service_tests,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from tests.common import mock_restore_cache
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def mock_device():
|
def mock_device():
|
||||||
"""Mock a Dynalite device."""
|
"""Mock a Dynalite device."""
|
||||||
mock_dev = create_mock_device("cover", DynaliteTimeCoverWithTiltDevice)
|
mock_dev = create_mock_device("cover", DynaliteTimeCoverWithTiltDevice)
|
||||||
mock_dev.device_class = "blind"
|
mock_dev.device_class = CoverDeviceClass.BLIND.value
|
||||||
|
mock_dev.current_cover_position = 0
|
||||||
|
mock_dev.current_cover_tilt_position = 0
|
||||||
|
mock_dev.is_opening = False
|
||||||
|
mock_dev.is_closing = False
|
||||||
|
mock_dev.is_closed = True
|
||||||
|
|
||||||
|
def mock_init_level(target):
|
||||||
|
mock_dev.is_closed = target == 0
|
||||||
|
|
||||||
|
type(mock_dev).init_level = Mock(side_effect=mock_init_level)
|
||||||
|
|
||||||
return mock_dev
|
return mock_dev
|
||||||
|
|
||||||
|
|
||||||
@ -29,11 +59,11 @@ async def test_cover_setup(hass, mock_device):
|
|||||||
entity_state = hass.states.get("cover.name")
|
entity_state = hass.states.get("cover.name")
|
||||||
assert entity_state.attributes[ATTR_FRIENDLY_NAME] == mock_device.name
|
assert entity_state.attributes[ATTR_FRIENDLY_NAME] == mock_device.name
|
||||||
assert (
|
assert (
|
||||||
entity_state.attributes["current_position"]
|
entity_state.attributes[ATTR_CURRENT_POSITION]
|
||||||
== mock_device.current_cover_position
|
== mock_device.current_cover_position
|
||||||
)
|
)
|
||||||
assert (
|
assert (
|
||||||
entity_state.attributes["current_tilt_position"]
|
entity_state.attributes[ATTR_CURRENT_TILT_POSITION]
|
||||||
== mock_device.current_cover_tilt_position
|
== mock_device.current_cover_tilt_position
|
||||||
)
|
)
|
||||||
assert entity_state.attributes[ATTR_DEVICE_CLASS] == mock_device.device_class
|
assert entity_state.attributes[ATTR_DEVICE_CLASS] == mock_device.device_class
|
||||||
@ -48,7 +78,7 @@ async def test_cover_setup(hass, mock_device):
|
|||||||
{
|
{
|
||||||
ATTR_SERVICE: "set_cover_position",
|
ATTR_SERVICE: "set_cover_position",
|
||||||
ATTR_METHOD: "async_set_cover_position",
|
ATTR_METHOD: "async_set_cover_position",
|
||||||
ATTR_ARGS: {"position": 50},
|
ATTR_ARGS: {ATTR_POSITION: 50},
|
||||||
},
|
},
|
||||||
{ATTR_SERVICE: "open_cover_tilt", ATTR_METHOD: "async_open_cover_tilt"},
|
{ATTR_SERVICE: "open_cover_tilt", ATTR_METHOD: "async_open_cover_tilt"},
|
||||||
{ATTR_SERVICE: "close_cover_tilt", ATTR_METHOD: "async_close_cover_tilt"},
|
{ATTR_SERVICE: "close_cover_tilt", ATTR_METHOD: "async_close_cover_tilt"},
|
||||||
@ -56,7 +86,7 @@ async def test_cover_setup(hass, mock_device):
|
|||||||
{
|
{
|
||||||
ATTR_SERVICE: "set_cover_tilt_position",
|
ATTR_SERVICE: "set_cover_tilt_position",
|
||||||
ATTR_METHOD: "async_set_cover_tilt_position",
|
ATTR_METHOD: "async_set_cover_tilt_position",
|
||||||
ATTR_ARGS: {"tilt_position": 50},
|
ATTR_ARGS: {ATTR_TILT_POSITION: 50},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -91,14 +121,38 @@ async def test_cover_positions(hass, mock_device):
|
|||||||
"""Test that the state updates in the various positions."""
|
"""Test that the state updates in the various positions."""
|
||||||
update_func = await create_entity_from_device(hass, mock_device)
|
update_func = await create_entity_from_device(hass, mock_device)
|
||||||
await check_cover_position(
|
await check_cover_position(
|
||||||
hass, update_func, mock_device, True, False, False, "closing"
|
hass, update_func, mock_device, True, False, False, STATE_CLOSING
|
||||||
)
|
)
|
||||||
await check_cover_position(
|
await check_cover_position(
|
||||||
hass, update_func, mock_device, False, True, False, "opening"
|
hass, update_func, mock_device, False, True, False, STATE_OPENING
|
||||||
)
|
)
|
||||||
await check_cover_position(
|
await check_cover_position(
|
||||||
hass, update_func, mock_device, False, False, True, "closed"
|
hass, update_func, mock_device, False, False, True, STATE_CLOSED
|
||||||
)
|
)
|
||||||
await check_cover_position(
|
await check_cover_position(
|
||||||
hass, update_func, mock_device, False, False, False, "open"
|
hass, update_func, mock_device, False, False, False, STATE_OPEN
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_cover_restore_state(hass, mock_device):
|
||||||
|
"""Test restore from cache."""
|
||||||
|
mock_restore_cache(
|
||||||
|
hass,
|
||||||
|
[State("cover.name", STATE_OPEN, attributes={ATTR_CURRENT_POSITION: 77})],
|
||||||
|
)
|
||||||
|
await create_entity_from_device(hass, mock_device)
|
||||||
|
mock_device.init_level.assert_called_once_with(77)
|
||||||
|
entity_state = hass.states.get("cover.name")
|
||||||
|
assert entity_state.state == STATE_OPEN
|
||||||
|
|
||||||
|
|
||||||
|
async def test_cover_restore_state_bad_cache(hass, mock_device):
|
||||||
|
"""Test restore from a cache without the attribute."""
|
||||||
|
mock_restore_cache(
|
||||||
|
hass,
|
||||||
|
[State("cover.name", STATE_OPEN, attributes={"bla bla": 77})],
|
||||||
|
)
|
||||||
|
await create_entity_from_device(hass, mock_device)
|
||||||
|
mock_device.init_level.assert_not_called()
|
||||||
|
entity_state = hass.states.get("cover.name")
|
||||||
|
assert entity_state.state == STATE_CLOSED
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
"""Test Dynalite light."""
|
"""Test Dynalite light."""
|
||||||
|
from unittest.mock import Mock, PropertyMock
|
||||||
|
|
||||||
from dynalite_devices_lib.light import DynaliteChannelLightDevice
|
from dynalite_devices_lib.light import DynaliteChannelLightDevice
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant.components.light import (
|
from homeassistant.components.light import (
|
||||||
|
ATTR_BRIGHTNESS,
|
||||||
ATTR_COLOR_MODE,
|
ATTR_COLOR_MODE,
|
||||||
ATTR_SUPPORTED_COLOR_MODES,
|
ATTR_SUPPORTED_COLOR_MODES,
|
||||||
ColorMode,
|
ColorMode,
|
||||||
@ -10,8 +13,11 @@ from homeassistant.components.light import (
|
|||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_FRIENDLY_NAME,
|
ATTR_FRIENDLY_NAME,
|
||||||
ATTR_SUPPORTED_FEATURES,
|
ATTR_SUPPORTED_FEATURES,
|
||||||
|
STATE_OFF,
|
||||||
|
STATE_ON,
|
||||||
STATE_UNAVAILABLE,
|
STATE_UNAVAILABLE,
|
||||||
)
|
)
|
||||||
|
from homeassistant.core import State
|
||||||
|
|
||||||
from .common import (
|
from .common import (
|
||||||
ATTR_METHOD,
|
ATTR_METHOD,
|
||||||
@ -22,11 +28,25 @@ from .common import (
|
|||||||
run_service_tests,
|
run_service_tests,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from tests.common import mock_restore_cache
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def mock_device():
|
def mock_device():
|
||||||
"""Mock a Dynalite device."""
|
"""Mock a Dynalite device."""
|
||||||
return create_mock_device("light", DynaliteChannelLightDevice)
|
mock_dev = create_mock_device("light", DynaliteChannelLightDevice)
|
||||||
|
mock_dev.brightness = 0
|
||||||
|
|
||||||
|
def mock_is_on():
|
||||||
|
return mock_dev.brightness != 0
|
||||||
|
|
||||||
|
type(mock_dev).is_on = PropertyMock(side_effect=mock_is_on)
|
||||||
|
|
||||||
|
def mock_init_level(target):
|
||||||
|
mock_dev.brightness = target
|
||||||
|
|
||||||
|
type(mock_dev).init_level = Mock(side_effect=mock_init_level)
|
||||||
|
return mock_dev
|
||||||
|
|
||||||
|
|
||||||
async def test_light_setup(hass, mock_device):
|
async def test_light_setup(hass, mock_device):
|
||||||
@ -34,10 +54,9 @@ async def test_light_setup(hass, mock_device):
|
|||||||
await create_entity_from_device(hass, mock_device)
|
await create_entity_from_device(hass, mock_device)
|
||||||
entity_state = hass.states.get("light.name")
|
entity_state = hass.states.get("light.name")
|
||||||
assert entity_state.attributes[ATTR_FRIENDLY_NAME] == mock_device.name
|
assert entity_state.attributes[ATTR_FRIENDLY_NAME] == mock_device.name
|
||||||
assert entity_state.attributes["brightness"] == mock_device.brightness
|
|
||||||
assert entity_state.attributes[ATTR_COLOR_MODE] == ColorMode.BRIGHTNESS
|
|
||||||
assert entity_state.attributes[ATTR_SUPPORTED_COLOR_MODES] == [ColorMode.BRIGHTNESS]
|
assert entity_state.attributes[ATTR_SUPPORTED_COLOR_MODES] == [ColorMode.BRIGHTNESS]
|
||||||
assert entity_state.attributes[ATTR_SUPPORTED_FEATURES] == 0
|
assert entity_state.attributes[ATTR_SUPPORTED_FEATURES] == 0
|
||||||
|
assert entity_state.state == STATE_OFF
|
||||||
await run_service_tests(
|
await run_service_tests(
|
||||||
hass,
|
hass,
|
||||||
mock_device,
|
mock_device,
|
||||||
@ -67,3 +86,29 @@ async def test_remove_config_entry(hass, mock_device):
|
|||||||
assert await hass.config_entries.async_remove(entry_id)
|
assert await hass.config_entries.async_remove(entry_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert not hass.states.get("light.name")
|
assert not hass.states.get("light.name")
|
||||||
|
|
||||||
|
|
||||||
|
async def test_light_restore_state(hass, mock_device):
|
||||||
|
"""Test restore from cache."""
|
||||||
|
mock_restore_cache(
|
||||||
|
hass,
|
||||||
|
[State("light.name", STATE_ON, attributes={ATTR_BRIGHTNESS: 77})],
|
||||||
|
)
|
||||||
|
await create_entity_from_device(hass, mock_device)
|
||||||
|
mock_device.init_level.assert_called_once_with(77)
|
||||||
|
entity_state = hass.states.get("light.name")
|
||||||
|
assert entity_state.state == STATE_ON
|
||||||
|
assert entity_state.attributes[ATTR_BRIGHTNESS] == 77
|
||||||
|
assert entity_state.attributes[ATTR_COLOR_MODE] == ColorMode.BRIGHTNESS
|
||||||
|
|
||||||
|
|
||||||
|
async def test_light_restore_state_bad_cache(hass, mock_device):
|
||||||
|
"""Test restore from a cache without the attribute."""
|
||||||
|
mock_restore_cache(
|
||||||
|
hass,
|
||||||
|
[State("light.name", "abc", attributes={"blabla": 77})],
|
||||||
|
)
|
||||||
|
await create_entity_from_device(hass, mock_device)
|
||||||
|
mock_device.init_level.assert_not_called()
|
||||||
|
entity_state = hass.states.get("light.name")
|
||||||
|
assert entity_state.state == STATE_OFF
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
"""Test Dynalite switch."""
|
"""Test Dynalite switch."""
|
||||||
|
|
||||||
|
from unittest.mock import Mock
|
||||||
|
|
||||||
from dynalite_devices_lib.switch import DynalitePresetSwitchDevice
|
from dynalite_devices_lib.switch import DynalitePresetSwitchDevice
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant.const import ATTR_FRIENDLY_NAME
|
from homeassistant.const import ATTR_FRIENDLY_NAME, STATE_OFF, STATE_ON
|
||||||
|
from homeassistant.core import State
|
||||||
|
|
||||||
from .common import (
|
from .common import (
|
||||||
ATTR_METHOD,
|
ATTR_METHOD,
|
||||||
@ -13,11 +16,20 @@ from .common import (
|
|||||||
run_service_tests,
|
run_service_tests,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from tests.common import mock_restore_cache
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def mock_device():
|
def mock_device():
|
||||||
"""Mock a Dynalite device."""
|
"""Mock a Dynalite device."""
|
||||||
return create_mock_device("switch", DynalitePresetSwitchDevice)
|
mock_dev = create_mock_device("switch", DynalitePresetSwitchDevice)
|
||||||
|
mock_dev.is_on = False
|
||||||
|
|
||||||
|
def mock_init_level(level):
|
||||||
|
mock_dev.is_on = level
|
||||||
|
|
||||||
|
type(mock_dev).init_level = Mock(side_effect=mock_init_level)
|
||||||
|
return mock_dev
|
||||||
|
|
||||||
|
|
||||||
async def test_switch_setup(hass, mock_device):
|
async def test_switch_setup(hass, mock_device):
|
||||||
@ -25,6 +37,7 @@ async def test_switch_setup(hass, mock_device):
|
|||||||
await create_entity_from_device(hass, mock_device)
|
await create_entity_from_device(hass, mock_device)
|
||||||
entity_state = hass.states.get("switch.name")
|
entity_state = hass.states.get("switch.name")
|
||||||
assert entity_state.attributes[ATTR_FRIENDLY_NAME] == mock_device.name
|
assert entity_state.attributes[ATTR_FRIENDLY_NAME] == mock_device.name
|
||||||
|
assert entity_state.state == STATE_OFF
|
||||||
await run_service_tests(
|
await run_service_tests(
|
||||||
hass,
|
hass,
|
||||||
mock_device,
|
mock_device,
|
||||||
@ -34,3 +47,21 @@ async def test_switch_setup(hass, mock_device):
|
|||||||
{ATTR_SERVICE: "turn_off", ATTR_METHOD: "async_turn_off"},
|
{ATTR_SERVICE: "turn_off", ATTR_METHOD: "async_turn_off"},
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("saved_state, level", [(STATE_ON, 1), (STATE_OFF, 0)])
|
||||||
|
async def test_switch_restore_state(hass, mock_device, saved_state, level):
|
||||||
|
"""Test restore from cache."""
|
||||||
|
mock_restore_cache(
|
||||||
|
hass,
|
||||||
|
[
|
||||||
|
State(
|
||||||
|
"switch.name",
|
||||||
|
saved_state,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
await create_entity_from_device(hass, mock_device)
|
||||||
|
mock_device.init_level.assert_called_once_with(level)
|
||||||
|
entity_state = hass.states.get("switch.name")
|
||||||
|
assert entity_state.state == saved_state
|
||||||
|
Loading…
x
Reference in New Issue
Block a user