deCONZ - retry if setup fails (#17772)
* Make component retry if setup fails * Improve overall test coverage
This commit is contained in:
parent
145677ed75
commit
a9140dc8f5
19 changed files with 823 additions and 475 deletions
|
@ -1,11 +1,11 @@
|
|||
"""Test deCONZ component setup process."""
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
from homeassistant.components import deconz
|
||||
from homeassistant.components.deconz import DATA_DECONZ_ID
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||
from homeassistant.setup import async_setup_component
|
||||
from tests.common import mock_coro
|
||||
from homeassistant.components import deconz
|
||||
|
||||
from tests.common import mock_coro, MockConfigEntry
|
||||
|
||||
|
||||
CONFIG = {
|
||||
"config": {
|
||||
|
@ -99,173 +99,113 @@ async def test_setup_entry_no_available_bridge(hass):
|
|||
|
||||
async def test_setup_entry_successful(hass):
|
||||
"""Test setup entry is successful."""
|
||||
entry = Mock()
|
||||
entry.data = {'host': '1.2.3.4', 'port': 80, 'api_key': '1234567890ABCDEF'}
|
||||
with patch.object(hass, 'async_create_task') as mock_add_job, \
|
||||
patch.object(hass, 'config_entries') as mock_config_entries, \
|
||||
patch('pydeconz.DeconzSession.async_get_state',
|
||||
return_value=mock_coro(CONFIG)), \
|
||||
patch('pydeconz.DeconzSession.start', return_value=True), \
|
||||
entry = MockConfigEntry(domain=deconz.DOMAIN, data={
|
||||
'host': '1.2.3.4', 'port': 80, 'api_key': '1234567890ABCDEF'
|
||||
})
|
||||
entry.add_to_hass(hass)
|
||||
mock_registry = Mock()
|
||||
with patch.object(deconz, 'DeconzGateway') as mock_gateway, \
|
||||
patch('homeassistant.helpers.device_registry.async_get_registry',
|
||||
return_value=mock_coro(Mock())):
|
||||
return_value=mock_coro(mock_registry)):
|
||||
mock_gateway.return_value.async_setup.return_value = mock_coro(True)
|
||||
assert await deconz.async_setup_entry(hass, entry) is True
|
||||
assert hass.data[deconz.DOMAIN]
|
||||
assert hass.data[deconz.DATA_DECONZ_ID] == {}
|
||||
assert len(hass.data[deconz.DATA_DECONZ_UNSUB]) == 1
|
||||
assert len(mock_add_job.mock_calls) == \
|
||||
len(deconz.SUPPORTED_PLATFORMS)
|
||||
assert len(mock_config_entries.async_forward_entry_setup.mock_calls) == \
|
||||
len(deconz.SUPPORTED_PLATFORMS)
|
||||
assert mock_config_entries.async_forward_entry_setup.mock_calls[0][1] == \
|
||||
(entry, 'binary_sensor')
|
||||
assert mock_config_entries.async_forward_entry_setup.mock_calls[1][1] == \
|
||||
(entry, 'cover')
|
||||
assert mock_config_entries.async_forward_entry_setup.mock_calls[2][1] == \
|
||||
(entry, 'light')
|
||||
assert mock_config_entries.async_forward_entry_setup.mock_calls[3][1] == \
|
||||
(entry, 'scene')
|
||||
assert mock_config_entries.async_forward_entry_setup.mock_calls[4][1] == \
|
||||
(entry, 'sensor')
|
||||
assert mock_config_entries.async_forward_entry_setup.mock_calls[5][1] == \
|
||||
(entry, 'switch')
|
||||
|
||||
|
||||
async def test_unload_entry(hass):
|
||||
"""Test being able to unload an entry."""
|
||||
entry = Mock()
|
||||
entry.data = {'host': '1.2.3.4', 'port': 80, 'api_key': '1234567890ABCDEF'}
|
||||
entry.async_unload.return_value = mock_coro(True)
|
||||
deconzmock = Mock()
|
||||
deconzmock.async_load_parameters.return_value = mock_coro(True)
|
||||
deconzmock.sensors = {}
|
||||
with patch('pydeconz.DeconzSession', return_value=deconzmock):
|
||||
entry = MockConfigEntry(domain=deconz.DOMAIN, data={
|
||||
'host': '1.2.3.4', 'port': 80, 'api_key': '1234567890ABCDEF'
|
||||
})
|
||||
entry.add_to_hass(hass)
|
||||
mock_registry = Mock()
|
||||
with patch.object(deconz, 'DeconzGateway') as mock_gateway, \
|
||||
patch('homeassistant.helpers.device_registry.async_get_registry',
|
||||
return_value=mock_coro(mock_registry)):
|
||||
mock_gateway.return_value.async_setup.return_value = mock_coro(True)
|
||||
assert await deconz.async_setup_entry(hass, entry) is True
|
||||
|
||||
assert deconz.DATA_DECONZ_EVENT in hass.data
|
||||
|
||||
hass.data[deconz.DATA_DECONZ_EVENT].append(Mock())
|
||||
hass.data[deconz.DATA_DECONZ_ID] = {'id': 'deconzid'}
|
||||
mock_gateway.return_value.async_reset.return_value = mock_coro(True)
|
||||
assert await deconz.async_unload_entry(hass, entry)
|
||||
assert deconz.DOMAIN not in hass.data
|
||||
assert len(hass.data[deconz.DATA_DECONZ_UNSUB]) == 0
|
||||
assert len(hass.data[deconz.DATA_DECONZ_EVENT]) == 0
|
||||
assert len(hass.data[deconz.DATA_DECONZ_ID]) == 0
|
||||
|
||||
|
||||
async def test_add_new_device(hass):
|
||||
"""Test adding a new device generates a signal for platforms."""
|
||||
entry = Mock()
|
||||
entry.data = {'host': '1.2.3.4', 'port': 80,
|
||||
'api_key': '1234567890ABCDEF', 'allow_clip_sensor': False}
|
||||
new_event = {
|
||||
"t": "event",
|
||||
"e": "added",
|
||||
"r": "sensors",
|
||||
"id": "1",
|
||||
"sensor": {
|
||||
"config": {
|
||||
"on": "True",
|
||||
"reachable": "True"
|
||||
},
|
||||
"name": "event",
|
||||
"state": {},
|
||||
"type": "ZHASwitch"
|
||||
}
|
||||
}
|
||||
with patch.object(deconz, 'async_dispatcher_send') as mock_dispatch_send, \
|
||||
patch('pydeconz.DeconzSession.async_get_state',
|
||||
return_value=mock_coro(CONFIG)), \
|
||||
patch('pydeconz.DeconzSession.start', return_value=True):
|
||||
assert await deconz.async_setup_entry(hass, entry) is True
|
||||
hass.data[deconz.DOMAIN].async_event_handler(new_event)
|
||||
await hass.async_block_till_done()
|
||||
assert len(mock_dispatch_send.mock_calls) == 1
|
||||
assert len(mock_dispatch_send.mock_calls[0]) == 3
|
||||
|
||||
|
||||
async def test_add_new_remote(hass):
|
||||
"""Test new added device creates a new remote."""
|
||||
entry = Mock()
|
||||
entry.data = {'host': '1.2.3.4', 'port': 80,
|
||||
'api_key': '1234567890ABCDEF', 'allow_clip_sensor': False}
|
||||
remote = Mock()
|
||||
remote.name = 'name'
|
||||
remote.type = 'ZHASwitch'
|
||||
remote.register_async_callback = Mock()
|
||||
with patch('pydeconz.DeconzSession.async_get_state',
|
||||
return_value=mock_coro(CONFIG)), \
|
||||
patch('pydeconz.DeconzSession.start', return_value=True):
|
||||
assert await deconz.async_setup_entry(hass, entry) is True
|
||||
async_dispatcher_send(hass, 'deconz_new_sensor', [remote])
|
||||
await hass.async_block_till_done()
|
||||
assert len(hass.data[deconz.DATA_DECONZ_EVENT]) == 1
|
||||
|
||||
|
||||
async def test_do_not_allow_clip_sensor(hass):
|
||||
"""Test that clip sensors can be ignored."""
|
||||
entry = Mock()
|
||||
entry.data = {'host': '1.2.3.4', 'port': 80,
|
||||
'api_key': '1234567890ABCDEF', 'allow_clip_sensor': False}
|
||||
remote = Mock()
|
||||
remote.name = 'name'
|
||||
remote.type = 'CLIPSwitch'
|
||||
remote.register_async_callback = Mock()
|
||||
with patch('pydeconz.DeconzSession.async_get_state',
|
||||
return_value=mock_coro(CONFIG)), \
|
||||
patch('pydeconz.DeconzSession.start', return_value=True):
|
||||
assert await deconz.async_setup_entry(hass, entry) is True
|
||||
|
||||
async_dispatcher_send(hass, 'deconz_new_sensor', [remote])
|
||||
await hass.async_block_till_done()
|
||||
assert len(hass.data[deconz.DATA_DECONZ_EVENT]) == 0
|
||||
|
||||
|
||||
async def test_service_configure(hass):
|
||||
"""Test that service invokes pydeconz with the correct path and data."""
|
||||
entry = Mock()
|
||||
entry.data = {'host': '1.2.3.4', 'port': 80, 'api_key': '1234567890ABCDEF'}
|
||||
with patch('pydeconz.DeconzSession.async_get_state',
|
||||
return_value=mock_coro(CONFIG)), \
|
||||
patch('pydeconz.DeconzSession.start', return_value=True), \
|
||||
entry = MockConfigEntry(domain=deconz.DOMAIN, data={
|
||||
'host': '1.2.3.4', 'port': 80, 'api_key': '1234567890ABCDEF'
|
||||
})
|
||||
entry.add_to_hass(hass)
|
||||
mock_registry = Mock()
|
||||
with patch.object(deconz, 'DeconzGateway') as mock_gateway, \
|
||||
patch('homeassistant.helpers.device_registry.async_get_registry',
|
||||
return_value=mock_coro(Mock())):
|
||||
return_value=mock_coro(mock_registry)):
|
||||
mock_gateway.return_value.async_setup.return_value = mock_coro(True)
|
||||
assert await deconz.async_setup_entry(hass, entry) is True
|
||||
|
||||
hass.data[DATA_DECONZ_ID] = {
|
||||
hass.data[deconz.DOMAIN].deconz_ids = {
|
||||
'light.test': '/light/1'
|
||||
}
|
||||
data = {'on': True, 'attr1': 10, 'attr2': 20}
|
||||
|
||||
# only field
|
||||
with patch('pydeconz.DeconzSession.async_put_state') as async_put_state:
|
||||
with patch('pydeconz.DeconzSession.async_put_state',
|
||||
return_value=mock_coro(True)):
|
||||
await hass.services.async_call('deconz', 'configure', service_data={
|
||||
'field': '/light/42', 'data': data
|
||||
})
|
||||
await hass.async_block_till_done()
|
||||
async_put_state.assert_called_with('/light/42', data)
|
||||
|
||||
# only entity
|
||||
with patch('pydeconz.DeconzSession.async_put_state') as async_put_state:
|
||||
with patch('pydeconz.DeconzSession.async_put_state',
|
||||
return_value=mock_coro(True)):
|
||||
await hass.services.async_call('deconz', 'configure', service_data={
|
||||
'entity': 'light.test', 'data': data
|
||||
})
|
||||
await hass.async_block_till_done()
|
||||
async_put_state.assert_called_with('/light/1', data)
|
||||
|
||||
# entity + field
|
||||
with patch('pydeconz.DeconzSession.async_put_state') as async_put_state:
|
||||
with patch('pydeconz.DeconzSession.async_put_state',
|
||||
return_value=mock_coro(True)):
|
||||
await hass.services.async_call('deconz', 'configure', service_data={
|
||||
'entity': 'light.test', 'field': '/state', 'data': data})
|
||||
await hass.async_block_till_done()
|
||||
async_put_state.assert_called_with('/light/1/state', data)
|
||||
|
||||
# non-existing entity (or not from deCONZ)
|
||||
with patch('pydeconz.DeconzSession.async_put_state') as async_put_state:
|
||||
with patch('pydeconz.DeconzSession.async_put_state',
|
||||
return_value=mock_coro(True)):
|
||||
await hass.services.async_call('deconz', 'configure', service_data={
|
||||
'entity': 'light.nonexisting', 'field': '/state', 'data': data})
|
||||
await hass.async_block_till_done()
|
||||
async_put_state.assert_not_called()
|
||||
|
||||
# field does not start with /
|
||||
with patch('pydeconz.DeconzSession.async_put_state') as async_put_state:
|
||||
with patch('pydeconz.DeconzSession.async_put_state',
|
||||
return_value=mock_coro(True)):
|
||||
await hass.services.async_call('deconz', 'configure', service_data={
|
||||
'entity': 'light.test', 'field': 'state', 'data': data})
|
||||
await hass.async_block_till_done()
|
||||
async_put_state.assert_not_called()
|
||||
|
||||
|
||||
async def test_service_refresh_devices(hass):
|
||||
"""Test that service can refresh devices."""
|
||||
entry = MockConfigEntry(domain=deconz.DOMAIN, data={
|
||||
'host': '1.2.3.4', 'port': 80, 'api_key': '1234567890ABCDEF'
|
||||
})
|
||||
entry.add_to_hass(hass)
|
||||
mock_registry = Mock()
|
||||
with patch.object(deconz, 'DeconzGateway') as mock_gateway, \
|
||||
patch('homeassistant.helpers.device_registry.async_get_registry',
|
||||
return_value=mock_coro(mock_registry)):
|
||||
mock_gateway.return_value.async_setup.return_value = mock_coro(True)
|
||||
assert await deconz.async_setup_entry(hass, entry) is True
|
||||
|
||||
with patch.object(hass.data[deconz.DOMAIN].api, 'async_load_parameters',
|
||||
return_value=mock_coro(True)):
|
||||
await hass.services.async_call(
|
||||
'deconz', 'device_refresh', service_data={})
|
||||
await hass.async_block_till_done()
|
||||
with patch.object(hass.data[deconz.DOMAIN].api, 'async_load_parameters',
|
||||
return_value=mock_coro(False)):
|
||||
await hass.services.async_call(
|
||||
'deconz', 'device_refresh', service_data={})
|
||||
await hass.async_block_till_done()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue