228 lines
7.6 KiB
Python
228 lines
7.6 KiB
Python
"""Tests for wemo_device.py."""
|
|
import asyncio
|
|
from datetime import timedelta
|
|
from unittest.mock import call, patch
|
|
|
|
import async_timeout
|
|
import pytest
|
|
from pywemo.exceptions import ActionException, PyWeMoException
|
|
from pywemo.subscribe import EVENT_TYPE_LONG_PRESS
|
|
|
|
from homeassistant import runner
|
|
from homeassistant.components.wemo import CONF_DISCOVERY, CONF_STATIC, wemo_device
|
|
from homeassistant.components.wemo.const import DOMAIN, WEMO_SUBSCRIPTION_EVENT
|
|
from homeassistant.core import callback
|
|
from homeassistant.helpers import device_registry
|
|
from homeassistant.helpers.update_coordinator import UpdateFailed
|
|
from homeassistant.setup import async_setup_component
|
|
from homeassistant.util.dt import utcnow
|
|
|
|
from .conftest import MOCK_FIRMWARE_VERSION, MOCK_HOST, MOCK_SERIAL_NUMBER
|
|
|
|
from tests.common import async_fire_time_changed
|
|
|
|
asyncio.set_event_loop_policy(runner.HassEventLoopPolicy(True))
|
|
|
|
|
|
@pytest.fixture
|
|
def pywemo_model():
|
|
"""Pywemo LightSwitch models use the switch platform."""
|
|
return "LightSwitchLongPress"
|
|
|
|
|
|
async def test_async_register_device_longpress_fails(hass, pywemo_device):
|
|
"""Device is still registered if ensure_long_press_virtual_device fails."""
|
|
with patch.object(pywemo_device, "ensure_long_press_virtual_device") as elp:
|
|
elp.side_effect = PyWeMoException
|
|
assert await async_setup_component(
|
|
hass,
|
|
DOMAIN,
|
|
{
|
|
DOMAIN: {
|
|
CONF_DISCOVERY: False,
|
|
CONF_STATIC: [MOCK_HOST],
|
|
},
|
|
},
|
|
)
|
|
await hass.async_block_till_done()
|
|
dr = device_registry.async_get(hass)
|
|
device_entries = list(dr.devices.values())
|
|
assert len(device_entries) == 1
|
|
device = wemo_device.async_get_coordinator(hass, device_entries[0].id)
|
|
assert device.supports_long_press is False
|
|
|
|
|
|
async def test_long_press_event(hass, pywemo_registry, wemo_entity):
|
|
"""Device fires a long press event."""
|
|
device = wemo_device.async_get_coordinator(hass, wemo_entity.device_id)
|
|
got_event = asyncio.Event()
|
|
event_data = {}
|
|
|
|
@callback
|
|
def async_event_received(event):
|
|
nonlocal event_data
|
|
event_data = event.data
|
|
got_event.set()
|
|
|
|
hass.bus.async_listen_once(WEMO_SUBSCRIPTION_EVENT, async_event_received)
|
|
|
|
await hass.async_add_executor_job(
|
|
pywemo_registry.callbacks[device.wemo.name],
|
|
device.wemo,
|
|
EVENT_TYPE_LONG_PRESS,
|
|
"testing_params",
|
|
)
|
|
|
|
async with async_timeout.timeout(8):
|
|
await got_event.wait()
|
|
|
|
assert event_data == {
|
|
"device_id": wemo_entity.device_id,
|
|
"name": device.wemo.name,
|
|
"params": "testing_params",
|
|
"type": EVENT_TYPE_LONG_PRESS,
|
|
"unique_id": device.wemo.serialnumber,
|
|
}
|
|
|
|
|
|
async def test_subscription_callback(hass, pywemo_registry, wemo_entity):
|
|
"""Device processes a registry subscription callback."""
|
|
device = wemo_device.async_get_coordinator(hass, wemo_entity.device_id)
|
|
device.last_update_success = False
|
|
|
|
got_callback = asyncio.Event()
|
|
|
|
@callback
|
|
def async_received_callback():
|
|
got_callback.set()
|
|
|
|
device.async_add_listener(async_received_callback)
|
|
|
|
await hass.async_add_executor_job(
|
|
pywemo_registry.callbacks[device.wemo.name], device.wemo, "", ""
|
|
)
|
|
|
|
async with async_timeout.timeout(8):
|
|
await got_callback.wait()
|
|
assert device.last_update_success
|
|
|
|
|
|
async def test_subscription_update_action_exception(hass, pywemo_device, wemo_entity):
|
|
"""Device handles ActionException on get_state properly."""
|
|
device = wemo_device.async_get_coordinator(hass, wemo_entity.device_id)
|
|
device.last_update_success = True
|
|
|
|
pywemo_device.subscription_update.return_value = False
|
|
pywemo_device.get_state.reset_mock()
|
|
pywemo_device.get_state.side_effect = ActionException
|
|
await hass.async_add_executor_job(
|
|
device.subscription_callback, pywemo_device, "", ""
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
pywemo_device.get_state.assert_called_once_with(True)
|
|
assert device.last_update_success is False
|
|
assert isinstance(device.last_exception, UpdateFailed)
|
|
|
|
|
|
async def test_subscription_update_exception(hass, pywemo_device, wemo_entity):
|
|
"""Device handles Exception on get_state properly."""
|
|
device = wemo_device.async_get_coordinator(hass, wemo_entity.device_id)
|
|
device.last_update_success = True
|
|
|
|
pywemo_device.subscription_update.return_value = False
|
|
pywemo_device.get_state.reset_mock()
|
|
pywemo_device.get_state.side_effect = Exception
|
|
await hass.async_add_executor_job(
|
|
device.subscription_callback, pywemo_device, "", ""
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
pywemo_device.get_state.assert_called_once_with(True)
|
|
assert device.last_update_success is False
|
|
assert isinstance(device.last_exception, Exception)
|
|
|
|
|
|
async def test_async_update_data_subscribed(
|
|
hass, pywemo_registry, pywemo_device, wemo_entity
|
|
):
|
|
"""No update happens when the device is subscribed."""
|
|
device = wemo_device.async_get_coordinator(hass, wemo_entity.device_id)
|
|
pywemo_registry.is_subscribed.return_value = True
|
|
pywemo_device.get_state.reset_mock()
|
|
await device._async_update_data()
|
|
pywemo_device.get_state.assert_not_called()
|
|
|
|
|
|
async def test_device_info(hass, wemo_entity):
|
|
"""Verify the DeviceInfo data is set properly."""
|
|
dr = device_registry.async_get(hass)
|
|
device_entries = list(dr.devices.values())
|
|
|
|
assert len(device_entries) == 1
|
|
assert device_entries[0].connections == {
|
|
("upnp", f"uuid:LightSwitch-1_0-{MOCK_SERIAL_NUMBER}")
|
|
}
|
|
assert device_entries[0].manufacturer == "Belkin"
|
|
assert device_entries[0].model == "LightSwitch"
|
|
assert device_entries[0].sw_version == MOCK_FIRMWARE_VERSION
|
|
|
|
|
|
async def test_dli_device_info(hass, wemo_dli_entity):
|
|
"""Verify the DeviceInfo data for Digital Loggers emulated wemo device."""
|
|
dr = device_registry.async_get(hass)
|
|
device_entries = list(dr.devices.values())
|
|
|
|
assert device_entries[0].configuration_url == "http://127.0.0.1"
|
|
assert device_entries[0].identifiers == {(DOMAIN, "123456789")}
|
|
|
|
|
|
class TestInsight:
|
|
"""Tests specific to the WeMo Insight device."""
|
|
|
|
@pytest.fixture
|
|
def pywemo_model(self):
|
|
"""Pywemo Dimmer models use the light platform (WemoDimmer class)."""
|
|
return "Insight"
|
|
|
|
@pytest.fixture(name="pywemo_device")
|
|
def pywemo_device_fixture(self, pywemo_device):
|
|
"""Fixture for WeMoDevice instances."""
|
|
pywemo_device.insight_params = {
|
|
"currentpower": 1.0,
|
|
"todaymw": 200000000.0,
|
|
"state": 0,
|
|
"onfor": 0,
|
|
"ontoday": 0,
|
|
"ontotal": 0,
|
|
"powerthreshold": 0,
|
|
}
|
|
yield pywemo_device
|
|
|
|
@pytest.mark.parametrize(
|
|
"subscribed,state,expected_calls",
|
|
[
|
|
(False, 0, [call(), call(True), call(), call()]),
|
|
(False, 1, [call(), call(True), call(), call()]),
|
|
(True, 0, [call(), call(True), call(), call()]),
|
|
(True, 1, [call(), call(), call()]),
|
|
],
|
|
)
|
|
async def test_should_poll(
|
|
self,
|
|
hass,
|
|
subscribed,
|
|
state,
|
|
expected_calls,
|
|
wemo_entity,
|
|
pywemo_device,
|
|
pywemo_registry,
|
|
):
|
|
"""Validate the should_poll returns the correct value."""
|
|
pywemo_registry.is_subscribed.return_value = subscribed
|
|
pywemo_device.get_state.reset_mock()
|
|
pywemo_device.get_state.return_value = state
|
|
async_fire_time_changed(hass, utcnow() + timedelta(seconds=31))
|
|
await hass.async_block_till_done()
|
|
pywemo_device.get_state.assert_has_calls(expected_calls)
|