Make yeelight discovery async (#54711)
This commit is contained in:
parent
bca9360d52
commit
e7a0604a40
11 changed files with 478 additions and 258 deletions
|
@ -1,5 +1,6 @@
|
|||
"""Test Yeelight."""
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
from datetime import timedelta
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
from yeelight import BulbException, BulbType
|
||||
|
||||
|
@ -22,9 +23,9 @@ from homeassistant.const import (
|
|||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.setup import async_setup_component
|
||||
from homeassistant.util import dt as dt_util
|
||||
|
||||
from . import (
|
||||
CAPABILITIES,
|
||||
CONFIG_ENTRY_DATA,
|
||||
ENTITY_AMBILIGHT,
|
||||
ENTITY_BINARY_SENSOR,
|
||||
|
@ -34,12 +35,14 @@ from . import (
|
|||
ID,
|
||||
IP_ADDRESS,
|
||||
MODULE,
|
||||
MODULE_CONFIG_FLOW,
|
||||
SHORT_ID,
|
||||
_mocked_bulb,
|
||||
_patch_discovery,
|
||||
_patch_discovery_interval,
|
||||
_patch_discovery_timeout,
|
||||
)
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
from tests.common import MockConfigEntry, async_fire_time_changed
|
||||
|
||||
|
||||
async def test_ip_changes_fallback_discovery(hass: HomeAssistant):
|
||||
|
@ -51,19 +54,15 @@ async def test_ip_changes_fallback_discovery(hass: HomeAssistant):
|
|||
|
||||
mocked_bulb = _mocked_bulb(True)
|
||||
mocked_bulb.bulb_type = BulbType.WhiteTempMood
|
||||
mocked_bulb.get_capabilities = MagicMock(
|
||||
side_effect=[OSError, CAPABILITIES, CAPABILITIES]
|
||||
)
|
||||
mocked_bulb.async_listen = AsyncMock(side_effect=[BulbException, None, None, None])
|
||||
|
||||
_discovered_devices = [{"capabilities": CAPABILITIES, "ip": IP_ADDRESS}]
|
||||
with patch(f"{MODULE}.AsyncBulb", return_value=mocked_bulb), patch(
|
||||
f"{MODULE}.discover_bulbs", return_value=_discovered_devices
|
||||
):
|
||||
with patch(f"{MODULE}.AsyncBulb", return_value=mocked_bulb), _patch_discovery():
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
binary_sensor_entity_id = ENTITY_BINARY_SENSOR_TEMPLATE.format(
|
||||
f"yeelight_color_{ID}"
|
||||
f"yeelight_color_{SHORT_ID}"
|
||||
)
|
||||
|
||||
type(mocked_bulb).async_get_properties = AsyncMock(None)
|
||||
|
@ -77,6 +76,19 @@ async def test_ip_changes_fallback_discovery(hass: HomeAssistant):
|
|||
entity_registry = er.async_get(hass)
|
||||
assert entity_registry.async_get(binary_sensor_entity_id) is not None
|
||||
|
||||
with patch(f"{MODULE}.AsyncBulb", return_value=mocked_bulb), _patch_discovery():
|
||||
# The discovery should update the ip address
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=2))
|
||||
await hass.async_block_till_done()
|
||||
assert config_entry.data[CONF_HOST] == IP_ADDRESS
|
||||
|
||||
# Make sure we can still reload with the new ip right after we change it
|
||||
with patch(f"{MODULE}.AsyncBulb", return_value=mocked_bulb), _patch_discovery():
|
||||
await hass.config_entries.async_reload(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert entity_registry.async_get(binary_sensor_entity_id) is not None
|
||||
|
||||
|
||||
async def test_ip_changes_id_missing_cannot_fallback(hass: HomeAssistant):
|
||||
"""Test Yeelight ip changes and we fallback to discovery."""
|
||||
|
@ -85,9 +97,7 @@ async def test_ip_changes_id_missing_cannot_fallback(hass: HomeAssistant):
|
|||
|
||||
mocked_bulb = _mocked_bulb(True)
|
||||
mocked_bulb.bulb_type = BulbType.WhiteTempMood
|
||||
mocked_bulb.get_capabilities = MagicMock(
|
||||
side_effect=[OSError, CAPABILITIES, CAPABILITIES]
|
||||
)
|
||||
mocked_bulb.async_listen = AsyncMock(side_effect=[BulbException, None, None, None])
|
||||
|
||||
with patch(f"{MODULE}.AsyncBulb", return_value=mocked_bulb):
|
||||
assert not await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
|
@ -102,9 +112,7 @@ async def test_setup_discovery(hass: HomeAssistant):
|
|||
config_entry.add_to_hass(hass)
|
||||
|
||||
mocked_bulb = _mocked_bulb()
|
||||
with _patch_discovery(MODULE), patch(
|
||||
f"{MODULE}.AsyncBulb", return_value=mocked_bulb
|
||||
):
|
||||
with _patch_discovery(), patch(f"{MODULE}.AsyncBulb", return_value=mocked_bulb):
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
@ -127,9 +135,7 @@ async def test_setup_import(hass: HomeAssistant):
|
|||
"""Test import from yaml."""
|
||||
mocked_bulb = _mocked_bulb()
|
||||
name = "yeelight"
|
||||
with patch(f"{MODULE}.AsyncBulb", return_value=mocked_bulb), patch(
|
||||
f"{MODULE_CONFIG_FLOW}.yeelight.Bulb", return_value=mocked_bulb
|
||||
):
|
||||
with patch(f"{MODULE}.AsyncBulb", return_value=mocked_bulb), _patch_discovery():
|
||||
assert await async_setup_component(
|
||||
hass,
|
||||
DOMAIN,
|
||||
|
@ -162,9 +168,7 @@ async def test_unique_ids_device(hass: HomeAssistant):
|
|||
|
||||
mocked_bulb = _mocked_bulb()
|
||||
mocked_bulb.bulb_type = BulbType.WhiteTempMood
|
||||
with _patch_discovery(MODULE), patch(
|
||||
f"{MODULE}.AsyncBulb", return_value=mocked_bulb
|
||||
):
|
||||
with _patch_discovery(), patch(f"{MODULE}.AsyncBulb", return_value=mocked_bulb):
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
@ -188,9 +192,7 @@ async def test_unique_ids_entry(hass: HomeAssistant):
|
|||
mocked_bulb = _mocked_bulb()
|
||||
mocked_bulb.bulb_type = BulbType.WhiteTempMood
|
||||
|
||||
with _patch_discovery(MODULE), patch(
|
||||
f"{MODULE}.AsyncBulb", return_value=mocked_bulb
|
||||
):
|
||||
with _patch_discovery(), patch(f"{MODULE}.AsyncBulb", return_value=mocked_bulb):
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
@ -220,30 +222,13 @@ async def test_bulb_off_while_adding_in_ha(hass: HomeAssistant):
|
|||
mocked_bulb = _mocked_bulb(True)
|
||||
mocked_bulb.bulb_type = BulbType.WhiteTempMood
|
||||
|
||||
with patch(f"{MODULE}.AsyncBulb", return_value=mocked_bulb), patch(
|
||||
f"{MODULE}.config_flow.yeelight.Bulb", return_value=mocked_bulb
|
||||
):
|
||||
with patch(f"{MODULE}.AsyncBulb", return_value=mocked_bulb), _patch_discovery(
|
||||
no_device=True
|
||||
), _patch_discovery_timeout(), _patch_discovery_interval():
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
binary_sensor_entity_id = ENTITY_BINARY_SENSOR_TEMPLATE.format(
|
||||
IP_ADDRESS.replace(".", "_")
|
||||
)
|
||||
|
||||
type(mocked_bulb).get_capabilities = MagicMock(CAPABILITIES)
|
||||
type(mocked_bulb).get_properties = MagicMock(None)
|
||||
|
||||
await hass.data[DOMAIN][DATA_CONFIG_ENTRIES][config_entry.entry_id][
|
||||
DATA_DEVICE
|
||||
].async_update()
|
||||
hass.data[DOMAIN][DATA_CONFIG_ENTRIES][config_entry.entry_id][
|
||||
DATA_DEVICE
|
||||
].async_update_callback({})
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entity_registry = er.async_get(hass)
|
||||
assert entity_registry.async_get(binary_sensor_entity_id) is not None
|
||||
assert config_entry.state is ConfigEntryState.LOADED
|
||||
|
||||
|
||||
async def test_async_listen_error_late_discovery(hass, caplog):
|
||||
|
@ -251,12 +236,9 @@ async def test_async_listen_error_late_discovery(hass, caplog):
|
|||
config_entry = MockConfigEntry(domain=DOMAIN, data=CONFIG_ENTRY_DATA)
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
mocked_bulb = _mocked_bulb()
|
||||
mocked_bulb.async_listen = AsyncMock(side_effect=BulbException)
|
||||
mocked_bulb = _mocked_bulb(cannot_connect=True)
|
||||
|
||||
with _patch_discovery(MODULE), patch(
|
||||
f"{MODULE}.AsyncBulb", return_value=mocked_bulb
|
||||
):
|
||||
with _patch_discovery(), patch(f"{MODULE}.AsyncBulb", return_value=mocked_bulb):
|
||||
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
@ -264,17 +246,33 @@ async def test_async_listen_error_late_discovery(hass, caplog):
|
|||
assert "Failed to connect to bulb at" in caplog.text
|
||||
|
||||
|
||||
async def test_async_listen_error_has_host(hass: HomeAssistant):
|
||||
async def test_async_listen_error_has_host_with_id(hass: HomeAssistant):
|
||||
"""Test the async listen error."""
|
||||
config_entry = MockConfigEntry(
|
||||
domain=DOMAIN, data={CONF_ID: ID, CONF_HOST: "127.0.0.1"}
|
||||
)
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
mocked_bulb = _mocked_bulb()
|
||||
mocked_bulb.async_listen = AsyncMock(side_effect=BulbException)
|
||||
with _patch_discovery(
|
||||
no_device=True
|
||||
), _patch_discovery_timeout(), _patch_discovery_interval(), patch(
|
||||
f"{MODULE}.AsyncBulb", return_value=_mocked_bulb(cannot_connect=True)
|
||||
):
|
||||
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
|
||||
with patch(f"{MODULE}.AsyncBulb", return_value=mocked_bulb):
|
||||
assert config_entry.state is ConfigEntryState.LOADED
|
||||
|
||||
|
||||
async def test_async_listen_error_has_host_without_id(hass: HomeAssistant):
|
||||
"""Test the async listen error but no id."""
|
||||
config_entry = MockConfigEntry(domain=DOMAIN, data={CONF_HOST: "127.0.0.1"})
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
with _patch_discovery(
|
||||
no_device=True
|
||||
), _patch_discovery_timeout(), _patch_discovery_interval(), patch(
|
||||
f"{MODULE}.AsyncBulb", return_value=_mocked_bulb(cannot_connect=True)
|
||||
):
|
||||
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
|
||||
assert config_entry.state is ConfigEntryState.SETUP_RETRY
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue