2019-03-30 04:10:00 +00:00
|
|
|
"""Tests for the init module."""
|
|
|
|
import asyncio
|
|
|
|
|
2019-05-06 15:53:11 +00:00
|
|
|
from asynctest import Mock, patch
|
2019-04-01 16:58:52 +00:00
|
|
|
from pyheos import CommandError, const
|
|
|
|
import pytest
|
2019-03-30 04:10:00 +00:00
|
|
|
|
2019-05-06 15:53:11 +00:00
|
|
|
from homeassistant.components.heos import (
|
|
|
|
ControllerManager, async_setup_entry, async_unload_entry)
|
2019-04-01 16:58:52 +00:00
|
|
|
from homeassistant.components.heos.const import (
|
2019-05-06 15:53:11 +00:00
|
|
|
DATA_CONTROLLER_MANAGER, DATA_SOURCE_MANAGER, DOMAIN)
|
2019-03-30 04:10:00 +00:00
|
|
|
from homeassistant.components.media_player.const import (
|
|
|
|
DOMAIN as MEDIA_PLAYER_DOMAIN)
|
|
|
|
from homeassistant.const import CONF_HOST
|
2019-04-01 16:58:52 +00:00
|
|
|
from homeassistant.exceptions import ConfigEntryNotReady
|
2019-03-30 04:10:00 +00:00
|
|
|
from homeassistant.setup import async_setup_component
|
|
|
|
|
|
|
|
|
|
|
|
async def test_async_setup_creates_entry(hass, config):
|
|
|
|
"""Test component setup creates entry from config."""
|
|
|
|
assert await async_setup_component(hass, DOMAIN, config)
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
entries = hass.config_entries.async_entries(DOMAIN)
|
|
|
|
assert len(entries) == 1
|
|
|
|
entry = entries[0]
|
|
|
|
assert entry.title == 'Controller (127.0.0.1)'
|
|
|
|
assert entry.data == {CONF_HOST: '127.0.0.1'}
|
|
|
|
|
|
|
|
|
2019-06-12 23:08:08 +00:00
|
|
|
async def test_async_setup_updates_entry(hass, config_entry, config,
|
|
|
|
controller):
|
2019-03-30 04:10:00 +00:00
|
|
|
"""Test component setup updates entry from config."""
|
|
|
|
config[DOMAIN][CONF_HOST] = '127.0.0.2'
|
|
|
|
config_entry.add_to_hass(hass)
|
|
|
|
assert await async_setup_component(hass, DOMAIN, config)
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
entries = hass.config_entries.async_entries(DOMAIN)
|
|
|
|
assert len(entries) == 1
|
|
|
|
entry = entries[0]
|
|
|
|
assert entry.title == 'Controller (127.0.0.2)'
|
|
|
|
assert entry.data == {CONF_HOST: '127.0.0.2'}
|
|
|
|
|
|
|
|
|
|
|
|
async def test_async_setup_returns_true(hass, config_entry, config):
|
2019-04-01 16:58:52 +00:00
|
|
|
"""Test component setup from config."""
|
2019-03-30 04:10:00 +00:00
|
|
|
config_entry.add_to_hass(hass)
|
|
|
|
assert await async_setup_component(hass, DOMAIN, config)
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
entries = hass.config_entries.async_entries(DOMAIN)
|
|
|
|
assert len(entries) == 1
|
|
|
|
assert entries[0] == config_entry
|
|
|
|
|
|
|
|
|
2019-03-30 13:52:17 +00:00
|
|
|
async def test_async_setup_no_config_returns_true(hass, config_entry):
|
2019-04-01 16:58:52 +00:00
|
|
|
"""Test component setup from entry only."""
|
2019-03-30 13:52:17 +00:00
|
|
|
config_entry.add_to_hass(hass)
|
|
|
|
assert await async_setup_component(hass, DOMAIN, {})
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
entries = hass.config_entries.async_entries(DOMAIN)
|
|
|
|
assert len(entries) == 1
|
|
|
|
assert entries[0] == config_entry
|
|
|
|
|
|
|
|
|
2019-03-30 04:10:00 +00:00
|
|
|
async def test_async_setup_entry_loads_platforms(
|
2019-04-09 16:21:00 +00:00
|
|
|
hass, config_entry, controller, input_sources, favorites):
|
2019-03-30 04:10:00 +00:00
|
|
|
"""Test load connects to heos, retrieves players, and loads platforms."""
|
|
|
|
config_entry.add_to_hass(hass)
|
|
|
|
with patch.object(
|
|
|
|
hass.config_entries, 'async_forward_entry_setup') as forward_mock:
|
|
|
|
assert await async_setup_entry(hass, config_entry)
|
|
|
|
# Assert platforms loaded
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
assert forward_mock.call_count == 1
|
|
|
|
assert controller.connect.call_count == 1
|
2019-04-09 16:21:00 +00:00
|
|
|
assert controller.get_players.call_count == 1
|
|
|
|
assert controller.get_favorites.call_count == 1
|
|
|
|
assert controller.get_input_sources.call_count == 1
|
|
|
|
controller.disconnect.assert_not_called()
|
2019-05-06 15:53:11 +00:00
|
|
|
assert hass.data[DOMAIN][DATA_CONTROLLER_MANAGER].controller == controller
|
2019-04-09 16:21:00 +00:00
|
|
|
assert hass.data[DOMAIN][MEDIA_PLAYER_DOMAIN] == controller.players
|
|
|
|
assert hass.data[DOMAIN][DATA_SOURCE_MANAGER].favorites == favorites
|
|
|
|
assert hass.data[DOMAIN][DATA_SOURCE_MANAGER].inputs == input_sources
|
|
|
|
|
|
|
|
|
|
|
|
async def test_async_setup_entry_not_signed_in_loads_platforms(
|
|
|
|
hass, config_entry, controller, input_sources, caplog):
|
|
|
|
"""Test setup does not retrieve favorites when not logged in."""
|
|
|
|
config_entry.add_to_hass(hass)
|
|
|
|
controller.is_signed_in = False
|
|
|
|
controller.signed_in_username = None
|
|
|
|
with patch.object(
|
|
|
|
hass.config_entries, 'async_forward_entry_setup') as forward_mock:
|
|
|
|
assert await async_setup_entry(hass, config_entry)
|
|
|
|
# Assert platforms loaded
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
assert forward_mock.call_count == 1
|
|
|
|
assert controller.connect.call_count == 1
|
|
|
|
assert controller.get_players.call_count == 1
|
|
|
|
assert controller.get_favorites.call_count == 0
|
|
|
|
assert controller.get_input_sources.call_count == 1
|
2019-03-30 04:10:00 +00:00
|
|
|
controller.disconnect.assert_not_called()
|
2019-05-06 15:53:11 +00:00
|
|
|
assert hass.data[DOMAIN][DATA_CONTROLLER_MANAGER].controller == controller
|
2019-04-01 16:58:52 +00:00
|
|
|
assert hass.data[DOMAIN][MEDIA_PLAYER_DOMAIN] == controller.players
|
2019-04-09 16:21:00 +00:00
|
|
|
assert hass.data[DOMAIN][DATA_SOURCE_MANAGER].favorites == {}
|
|
|
|
assert hass.data[DOMAIN][DATA_SOURCE_MANAGER].inputs == input_sources
|
2019-05-07 16:39:42 +00:00
|
|
|
assert "127.0.0.1 is not logged in to a HEOS account and will be unable " \
|
|
|
|
"to retrieve HEOS favorites: Use the 'heos.sign_in' service to " \
|
|
|
|
"sign-in to a HEOS account" in caplog.text
|
2019-03-30 04:10:00 +00:00
|
|
|
|
|
|
|
|
|
|
|
async def test_async_setup_entry_connect_failure(
|
|
|
|
hass, config_entry, controller):
|
2019-04-01 16:58:52 +00:00
|
|
|
"""Connection failure raises ConfigEntryNotReady."""
|
2019-03-30 04:10:00 +00:00
|
|
|
config_entry.add_to_hass(hass)
|
|
|
|
errors = [ConnectionError, asyncio.TimeoutError]
|
|
|
|
for error in errors:
|
|
|
|
controller.connect.side_effect = error
|
2019-04-01 16:58:52 +00:00
|
|
|
with pytest.raises(ConfigEntryNotReady):
|
|
|
|
await async_setup_entry(hass, config_entry)
|
|
|
|
await hass.async_block_till_done()
|
2019-03-30 04:10:00 +00:00
|
|
|
assert controller.connect.call_count == 1
|
|
|
|
assert controller.disconnect.call_count == 1
|
|
|
|
controller.connect.reset_mock()
|
|
|
|
controller.disconnect.reset_mock()
|
|
|
|
|
|
|
|
|
|
|
|
async def test_async_setup_entry_player_failure(
|
|
|
|
hass, config_entry, controller):
|
2019-04-01 16:58:52 +00:00
|
|
|
"""Failure to retrieve players/sources raises ConfigEntryNotReady."""
|
2019-03-30 04:10:00 +00:00
|
|
|
config_entry.add_to_hass(hass)
|
|
|
|
errors = [ConnectionError, asyncio.TimeoutError]
|
|
|
|
for error in errors:
|
|
|
|
controller.get_players.side_effect = error
|
2019-04-01 16:58:52 +00:00
|
|
|
with pytest.raises(ConfigEntryNotReady):
|
|
|
|
await async_setup_entry(hass, config_entry)
|
|
|
|
await hass.async_block_till_done()
|
2019-03-30 04:10:00 +00:00
|
|
|
assert controller.connect.call_count == 1
|
|
|
|
assert controller.disconnect.call_count == 1
|
|
|
|
controller.connect.reset_mock()
|
|
|
|
controller.disconnect.reset_mock()
|
|
|
|
|
|
|
|
|
|
|
|
async def test_unload_entry(hass, config_entry, controller):
|
|
|
|
"""Test entries are unloaded correctly."""
|
2019-05-06 15:53:11 +00:00
|
|
|
controller_manager = Mock(ControllerManager)
|
|
|
|
hass.data[DOMAIN] = {DATA_CONTROLLER_MANAGER: controller_manager}
|
2019-03-30 04:10:00 +00:00
|
|
|
with patch.object(hass.config_entries, 'async_forward_entry_unload',
|
|
|
|
return_value=True) as unload:
|
|
|
|
assert await async_unload_entry(hass, config_entry)
|
|
|
|
await hass.async_block_till_done()
|
2019-05-06 15:53:11 +00:00
|
|
|
assert controller_manager.disconnect.call_count == 1
|
2019-03-30 04:10:00 +00:00
|
|
|
assert unload.call_count == 1
|
2019-04-01 16:58:52 +00:00
|
|
|
assert DOMAIN not in hass.data
|
|
|
|
|
|
|
|
|
|
|
|
async def test_update_sources_retry(hass, config_entry, config, controller,
|
|
|
|
caplog):
|
|
|
|
"""Test update sources retries on failures to max attempts."""
|
|
|
|
config_entry.add_to_hass(hass)
|
|
|
|
assert await async_setup_component(hass, DOMAIN, config)
|
|
|
|
controller.get_favorites.reset_mock()
|
|
|
|
controller.get_input_sources.reset_mock()
|
|
|
|
source_manager = hass.data[DOMAIN][DATA_SOURCE_MANAGER]
|
|
|
|
source_manager.retry_delay = 0
|
|
|
|
source_manager.max_retry_attempts = 1
|
|
|
|
controller.get_favorites.side_effect = CommandError("Test", "test", 0)
|
|
|
|
controller.dispatcher.send(
|
2019-05-02 05:39:59 +00:00
|
|
|
const.SIGNAL_CONTROLLER_EVENT, const.EVENT_SOURCES_CHANGED, {})
|
2019-04-01 16:58:52 +00:00
|
|
|
# Wait until it's finished
|
|
|
|
while "Unable to update sources" not in caplog.text:
|
|
|
|
await asyncio.sleep(0.1)
|
|
|
|
assert controller.get_favorites.call_count == 2
|