From 32045011748c9738f06871da5992c32c85863003 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 23 Jul 2018 15:08:03 +0200 Subject: [PATCH] Cast/Sonos: create config entry if manually configured (#15630) * Cast/Sonos: create config entry if manually configured * Add test for helper --- homeassistant/components/cast/__init__.py | 10 ++++++- homeassistant/components/sonos/__init__.py | 10 ++++++- homeassistant/helpers/config_entry_flow.py | 12 +++++++++ tests/components/cast/test_init.py | 31 ++++++++++++++++++++++ tests/components/sonos/test_init.py | 27 +++++++++++++++++++ tests/helpers/test_config_entry_flow.py | 21 +++++++++++++++ 6 files changed, 109 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/cast/__init__.py b/homeassistant/components/cast/__init__.py index 966107bcb36ae..aadf0103c5a6f 100644 --- a/homeassistant/components/cast/__init__.py +++ b/homeassistant/components/cast/__init__.py @@ -1,4 +1,5 @@ """Component to embed Google Cast.""" +from homeassistant import data_entry_flow from homeassistant.helpers import config_entry_flow @@ -8,7 +9,14 @@ async def async_setup(hass, config): """Set up the Cast component.""" - hass.data[DOMAIN] = config.get(DOMAIN, {}) + conf = config.get(DOMAIN) + + hass.data[DOMAIN] = conf or {} + + if conf is not None: + hass.async_create_task(hass.config_entries.flow.async_init( + DOMAIN, source=data_entry_flow.SOURCE_IMPORT)) + return True diff --git a/homeassistant/components/sonos/__init__.py b/homeassistant/components/sonos/__init__.py index c67a3dffaaf22..4c5592c02c22a 100644 --- a/homeassistant/components/sonos/__init__.py +++ b/homeassistant/components/sonos/__init__.py @@ -1,4 +1,5 @@ """Component to embed Sonos.""" +from homeassistant import data_entry_flow from homeassistant.helpers import config_entry_flow @@ -8,7 +9,14 @@ async def async_setup(hass, config): """Set up the Sonos component.""" - hass.data[DOMAIN] = config.get(DOMAIN, {}) + conf = config.get(DOMAIN) + + hass.data[DOMAIN] = conf or {} + + if conf is not None: + hass.async_create_task(hass.config_entries.flow.async_init( + DOMAIN, source=data_entry_flow.SOURCE_IMPORT)) + return True diff --git a/homeassistant/helpers/config_entry_flow.py b/homeassistant/helpers/config_entry_flow.py index 2a4ec2966df96..6f51d9aca2c49 100644 --- a/homeassistant/helpers/config_entry_flow.py +++ b/homeassistant/helpers/config_entry_flow.py @@ -72,6 +72,18 @@ async def async_step_discovery(self, discovery_info): return await self.async_step_confirm() + async def async_step_import(self, _): + """Handle a flow initialized by import.""" + if self._async_in_progress() or self._async_current_entries(): + return self.async_abort( + reason='single_instance_allowed' + ) + + return self.async_create_entry( + title=self._title, + data={}, + ) + @callback def _async_current_entries(self): """Return current entries.""" diff --git a/tests/components/cast/test_init.py b/tests/components/cast/test_init.py index 260856c6742e2..3ed9ea7b88e11 100644 --- a/tests/components/cast/test_init.py +++ b/tests/components/cast/test_init.py @@ -2,6 +2,7 @@ from unittest.mock import patch from homeassistant import data_entry_flow +from homeassistant.setup import async_setup_component from homeassistant.components import cast from tests.common import MockDependency, mock_coro @@ -20,3 +21,33 @@ async def test_creating_entry_sets_up_media_player(hass): await hass.async_block_till_done() assert len(mock_setup.mock_calls) == 1 + + +async def test_configuring_cast_creates_entry(hass): + """Test that specifying config will create an entry.""" + with patch('homeassistant.components.cast.async_setup_entry', + return_value=mock_coro(True)) as mock_setup, \ + MockDependency('pychromecast', 'discovery'), \ + patch('pychromecast.discovery.discover_chromecasts', + return_value=True): + await async_setup_component(hass, cast.DOMAIN, { + 'cast': { + 'some_config': 'to_trigger_import' + } + }) + await hass.async_block_till_done() + + assert len(mock_setup.mock_calls) == 1 + + +async def test_not_configuring_cast_not_creates_entry(hass): + """Test that no config will not create an entry.""" + with patch('homeassistant.components.cast.async_setup_entry', + return_value=mock_coro(True)) as mock_setup, \ + MockDependency('pychromecast', 'discovery'), \ + patch('pychromecast.discovery.discover_chromecasts', + return_value=True): + await async_setup_component(hass, cast.DOMAIN, {}) + await hass.async_block_till_done() + + assert len(mock_setup.mock_calls) == 0 diff --git a/tests/components/sonos/test_init.py b/tests/components/sonos/test_init.py index 2cbc2360fd44d..9fe22fc7e79ee 100644 --- a/tests/components/sonos/test_init.py +++ b/tests/components/sonos/test_init.py @@ -2,6 +2,7 @@ from unittest.mock import patch from homeassistant import data_entry_flow +from homeassistant.setup import async_setup_component from homeassistant.components import sonos from tests.common import mock_coro @@ -18,3 +19,29 @@ async def test_creating_entry_sets_up_media_player(hass): await hass.async_block_till_done() assert len(mock_setup.mock_calls) == 1 + + +async def test_configuring_sonos_creates_entry(hass): + """Test that specifying config will create an entry.""" + with patch('homeassistant.components.sonos.async_setup_entry', + return_value=mock_coro(True)) as mock_setup, \ + patch('soco.discover', return_value=True): + await async_setup_component(hass, sonos.DOMAIN, { + 'sonos': { + 'some_config': 'to_trigger_import' + } + }) + await hass.async_block_till_done() + + assert len(mock_setup.mock_calls) == 1 + + +async def test_not_configuring_sonos_not_creates_entry(hass): + """Test that no config will not create an entry.""" + with patch('homeassistant.components.sonos.async_setup_entry', + return_value=mock_coro(True)) as mock_setup, \ + patch('soco.discover', return_value=True): + await async_setup_component(hass, sonos.DOMAIN, {}) + await hass.async_block_till_done() + + assert len(mock_setup.mock_calls) == 0 diff --git a/tests/helpers/test_config_entry_flow.py b/tests/helpers/test_config_entry_flow.py index d3f13ac43021b..19185e165bccd 100644 --- a/tests/helpers/test_config_entry_flow.py +++ b/tests/helpers/test_config_entry_flow.py @@ -114,3 +114,24 @@ async def test_user_init_trumps_discovery(hass, flow_conf): # Discovery flow has been aborted assert len(hass.config_entries.flow.async_progress()) == 0 + + +async def test_import_no_confirmation(hass, flow_conf): + """Test import requires no confirmation to setup.""" + flow = config_entries.HANDLERS['test']() + flow.hass = hass + flow_conf['discovered'] = True + + result = await flow.async_step_import(None) + assert result['type'] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY + + +async def test_import_single_instance(hass, flow_conf): + """Test import doesn't create second instance.""" + flow = config_entries.HANDLERS['test']() + flow.hass = hass + flow_conf['discovered'] = True + MockConfigEntry(domain='test').add_to_hass(hass) + + result = await flow.async_step_import(None) + assert result['type'] == data_entry_flow.RESULT_TYPE_ABORT