Fixing tplink issues with offline devices during setup (#23668)
* Fixing tplink issues with offline devices during setup. * Fixing circleci errors. * Adding code to defer the creation of entities that are not online. * Addressing code review changes and cleaning up a little. * Fixing tests and static analysis. * Adding test to satisfy coverage requirements. * Resolving merge conflicts. * Fixing issue where lights don't appear in the integration page. * Using pyHS100 properties for most sysinfo. Addressing some PR feedback. * Addressing some PR feedback. * Better testing async_add_entities_retry Testing for static dimmers. Making greater use of conf constants. * Fixing all static analysis issues. * Adding non-blocking call for getting discovering devices. * Address PR feedback
This commit is contained in:
parent
6f299e7245
commit
bf91a8c1b3
7 changed files with 541 additions and 139 deletions
|
@ -1,12 +1,20 @@
|
|||
"""Tests for the TP-Link component."""
|
||||
from unittest.mock import patch
|
||||
from typing import Dict, Any
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
from pyHS100 import SmartPlug, SmartBulb, SmartDevice, SmartDeviceException
|
||||
|
||||
from homeassistant import config_entries, data_entry_flow
|
||||
from homeassistant.components import tplink
|
||||
from homeassistant.components.tplink.common import (
|
||||
CONF_DISCOVERY,
|
||||
CONF_DIMMER,
|
||||
CONF_LIGHT,
|
||||
CONF_SWITCH,
|
||||
)
|
||||
from homeassistant.const import CONF_HOST
|
||||
from homeassistant.setup import async_setup_component
|
||||
from pyHS100 import SmartPlug, SmartBulb
|
||||
from tests.common import MockDependency, MockConfigEntry, mock_coro
|
||||
|
||||
MOCK_PYHS100 = MockDependency("pyHS100")
|
||||
|
@ -15,8 +23,8 @@ MOCK_PYHS100 = MockDependency("pyHS100")
|
|||
async def test_creating_entry_tries_discover(hass):
|
||||
"""Test setting up does discovery."""
|
||||
with MOCK_PYHS100, patch(
|
||||
"homeassistant.components.tplink.async_setup_entry",
|
||||
return_value=mock_coro(True),
|
||||
"homeassistant.components.tplink.async_setup_entry",
|
||||
return_value=mock_coro(True),
|
||||
) as mock_setup, patch(
|
||||
"pyHS100.Discover.discover", return_value={"host": 1234}
|
||||
):
|
||||
|
@ -41,7 +49,7 @@ async def test_configuring_tplink_causes_discovery(hass):
|
|||
"""Test that specifying empty config does discovery."""
|
||||
with MOCK_PYHS100, patch("pyHS100.Discover.discover") as discover:
|
||||
discover.return_value = {"host": 1234}
|
||||
await async_setup_component(hass, tplink.DOMAIN, {"tplink": {}})
|
||||
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(discover.mock_calls) == 1
|
||||
|
@ -58,45 +66,111 @@ async def test_configuring_tplink_causes_discovery(hass):
|
|||
async def test_configuring_device_types(hass, name, cls, platform, count):
|
||||
"""Test that light or switch platform list is filled correctly."""
|
||||
with patch("pyHS100.Discover.discover") as discover, patch(
|
||||
"pyHS100.SmartDevice._query_helper"
|
||||
"pyHS100.SmartDevice._query_helper"
|
||||
):
|
||||
discovery_data = {
|
||||
"123.123.123.{}".format(c): cls("123.123.123.123")
|
||||
for c in range(count)
|
||||
}
|
||||
discover.return_value = discovery_data
|
||||
await async_setup_component(hass, tplink.DOMAIN, {"tplink": {}})
|
||||
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(discover.mock_calls) == 1
|
||||
assert len(hass.data[tplink.DOMAIN][platform]) == count
|
||||
|
||||
|
||||
class UnknownSmartDevice(SmartDevice):
|
||||
"""Dummy class for testing."""
|
||||
|
||||
@property
|
||||
def has_emeter(self) -> bool:
|
||||
"""Do nothing."""
|
||||
pass
|
||||
|
||||
def turn_off(self) -> None:
|
||||
"""Do nothing."""
|
||||
pass
|
||||
|
||||
def turn_on(self) -> None:
|
||||
"""Do nothing."""
|
||||
pass
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool:
|
||||
"""Do nothing."""
|
||||
pass
|
||||
|
||||
@property
|
||||
def state_information(self) -> Dict[str, Any]:
|
||||
"""Do nothing."""
|
||||
pass
|
||||
|
||||
|
||||
async def test_configuring_devices_from_multiple_sources(hass):
|
||||
"""Test static and discover devices are not duplicated."""
|
||||
with patch("pyHS100.Discover.discover") as discover, patch(
|
||||
"pyHS100.SmartDevice._query_helper"
|
||||
):
|
||||
discover_device_fail = SmartPlug("123.123.123.123")
|
||||
discover_device_fail.get_sysinfo = MagicMock(
|
||||
side_effect=SmartDeviceException()
|
||||
)
|
||||
|
||||
discover.return_value = {
|
||||
"123.123.123.1": SmartBulb("123.123.123.1"),
|
||||
"123.123.123.2": SmartPlug("123.123.123.2"),
|
||||
"123.123.123.3": SmartBulb("123.123.123.3"),
|
||||
"123.123.123.4": SmartPlug("123.123.123.4"),
|
||||
"123.123.123.123": discover_device_fail,
|
||||
"123.123.123.124": UnknownSmartDevice("123.123.123.124")
|
||||
}
|
||||
|
||||
await async_setup_component(hass, tplink.DOMAIN, {
|
||||
tplink.DOMAIN: {
|
||||
CONF_LIGHT: [
|
||||
{CONF_HOST: "123.123.123.1"},
|
||||
],
|
||||
CONF_SWITCH: [
|
||||
{CONF_HOST: "123.123.123.2"},
|
||||
],
|
||||
CONF_DIMMER: [
|
||||
{CONF_HOST: "123.123.123.22"},
|
||||
],
|
||||
}
|
||||
})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(discover.mock_calls) == 1
|
||||
assert len(hass.data[tplink.DOMAIN][CONF_LIGHT]) == 3
|
||||
assert len(hass.data[tplink.DOMAIN][CONF_SWITCH]) == 2
|
||||
|
||||
|
||||
async def test_is_dimmable(hass):
|
||||
"""Test that is_dimmable switches are correctly added as lights."""
|
||||
with patch("pyHS100.Discover.discover") as discover, patch(
|
||||
"homeassistant.components.tplink.light.async_setup_entry",
|
||||
return_value=mock_coro(True),
|
||||
"homeassistant.components.tplink.light.async_setup_entry",
|
||||
return_value=mock_coro(True),
|
||||
) as setup, patch("pyHS100.SmartDevice._query_helper"), patch(
|
||||
"pyHS100.SmartPlug.is_dimmable", True
|
||||
):
|
||||
dimmable_switch = SmartPlug("123.123.123.123")
|
||||
discover.return_value = {"host": dimmable_switch}
|
||||
|
||||
await async_setup_component(hass, tplink.DOMAIN, {"tplink": {}})
|
||||
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(discover.mock_calls) == 1
|
||||
assert len(setup.mock_calls) == 1
|
||||
assert len(hass.data[tplink.DOMAIN]["light"]) == 1
|
||||
assert len(hass.data[tplink.DOMAIN]["switch"]) == 0
|
||||
assert len(hass.data[tplink.DOMAIN][CONF_LIGHT]) == 1
|
||||
assert not hass.data[tplink.DOMAIN][CONF_SWITCH]
|
||||
|
||||
|
||||
async def test_configuring_discovery_disabled(hass):
|
||||
"""Test that discover does not get called when disabled."""
|
||||
with MOCK_PYHS100, patch(
|
||||
"homeassistant.components.tplink.async_setup_entry",
|
||||
return_value=mock_coro(True),
|
||||
"homeassistant.components.tplink.async_setup_entry",
|
||||
return_value=mock_coro(True),
|
||||
) as mock_setup, patch(
|
||||
"pyHS100.Discover.discover", return_value=[]
|
||||
) as discover:
|
||||
|
@ -107,22 +181,22 @@ async def test_configuring_discovery_disabled(hass):
|
|||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(discover.mock_calls) == 0
|
||||
assert len(mock_setup.mock_calls) == 1
|
||||
assert discover.call_count == 0
|
||||
assert mock_setup.call_count == 1
|
||||
|
||||
|
||||
async def test_platforms_are_initialized(hass):
|
||||
"""Test that platforms are initialized per configuration array."""
|
||||
config = {
|
||||
"tplink": {
|
||||
"discovery": False,
|
||||
"light": [{"host": "123.123.123.123"}],
|
||||
"switch": [{"host": "321.321.321.321"}],
|
||||
tplink.DOMAIN: {
|
||||
CONF_DISCOVERY: False,
|
||||
CONF_LIGHT: [{CONF_HOST: "123.123.123.123"}],
|
||||
CONF_SWITCH: [{CONF_HOST: "321.321.321.321"}],
|
||||
}
|
||||
}
|
||||
|
||||
with patch("pyHS100.Discover.discover") as discover, patch(
|
||||
"pyHS100.SmartDevice._query_helper"
|
||||
"pyHS100.SmartDevice._query_helper"
|
||||
), patch(
|
||||
"homeassistant.components.tplink.light.async_setup_entry",
|
||||
return_value=mock_coro(True),
|
||||
|
@ -136,21 +210,21 @@ async def test_platforms_are_initialized(hass):
|
|||
await async_setup_component(hass, tplink.DOMAIN, config)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(discover.mock_calls) == 0
|
||||
assert len(light_setup.mock_calls) == 1
|
||||
assert len(switch_setup.mock_calls) == 1
|
||||
assert discover.call_count == 0
|
||||
assert light_setup.call_count == 1
|
||||
assert switch_setup.call_count == 1
|
||||
|
||||
|
||||
async def test_no_config_creates_no_entry(hass):
|
||||
"""Test for when there is no tplink in config."""
|
||||
with MOCK_PYHS100, patch(
|
||||
"homeassistant.components.tplink.async_setup_entry",
|
||||
return_value=mock_coro(True),
|
||||
"homeassistant.components.tplink.async_setup_entry",
|
||||
return_value=mock_coro(True),
|
||||
) as mock_setup:
|
||||
await async_setup_component(hass, tplink.DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(mock_setup.mock_calls) == 0
|
||||
assert mock_setup.call_count == 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize("platform", ["switch", "light"])
|
||||
|
@ -161,14 +235,14 @@ async def test_unload(hass, platform):
|
|||
entry.add_to_hass(hass)
|
||||
|
||||
with patch("pyHS100.SmartDevice._query_helper"), patch(
|
||||
"homeassistant.components.tplink.{}"
|
||||
".async_setup_entry".format(platform),
|
||||
return_value=mock_coro(True),
|
||||
"homeassistant.components.tplink.{}"
|
||||
".async_setup_entry".format(platform),
|
||||
return_value=mock_coro(True),
|
||||
) as light_setup:
|
||||
config = {
|
||||
"tplink": {
|
||||
platform: [{"host": "123.123.123.123"}],
|
||||
"discovery": False,
|
||||
tplink.DOMAIN: {
|
||||
platform: [{CONF_HOST: "123.123.123.123"}],
|
||||
CONF_DISCOVERY: False,
|
||||
}
|
||||
}
|
||||
assert await async_setup_component(hass, tplink.DOMAIN, config)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue