mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 00:37:53 +00:00
Add config entry for Sonos + Cast (#14955)
* Add config entry for Sonos * Lint * Use add_job * Add Cast config entry * Lint * Rename DOMAIN import * Mock pychromecast in test
This commit is contained in:
parent
c8e0de19b6
commit
2c6e6c2a6f
@ -61,6 +61,9 @@ omit =
|
||||
homeassistant/components/coinbase.py
|
||||
homeassistant/components/sensor/coinbase.py
|
||||
|
||||
homeassistant/components/cast/*
|
||||
homeassistant/components/*/cast.py
|
||||
|
||||
homeassistant/components/comfoconnect.py
|
||||
homeassistant/components/*/comfoconnect.py
|
||||
|
||||
@ -252,6 +255,9 @@ omit =
|
||||
homeassistant/components/smappee.py
|
||||
homeassistant/components/*/smappee.py
|
||||
|
||||
homeassistant/components/sonos/__init__.py
|
||||
homeassistant/components/*/sonos.py
|
||||
|
||||
homeassistant/components/tado.py
|
||||
homeassistant/components/*/tado.py
|
||||
|
||||
@ -482,7 +488,6 @@ omit =
|
||||
homeassistant/components/media_player/aquostv.py
|
||||
homeassistant/components/media_player/bluesound.py
|
||||
homeassistant/components/media_player/braviatv.py
|
||||
homeassistant/components/media_player/cast.py
|
||||
homeassistant/components/media_player/channels.py
|
||||
homeassistant/components/media_player/clementine.py
|
||||
homeassistant/components/media_player/cmus.py
|
||||
@ -518,7 +523,6 @@ omit =
|
||||
homeassistant/components/media_player/russound_rnet.py
|
||||
homeassistant/components/media_player/snapcast.py
|
||||
homeassistant/components/media_player/songpal.py
|
||||
homeassistant/components/media_player/sonos.py
|
||||
homeassistant/components/media_player/spotify.py
|
||||
homeassistant/components/media_player/squeezebox.py
|
||||
homeassistant/components/media_player/ue_smart_radio.py
|
||||
|
15
homeassistant/components/cast/.translations/en.json
Normal file
15
homeassistant/components/cast/.translations/en.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"no_devices_found": "No Google Cast devices found on the network.",
|
||||
"single_instance_allowed": "Only a single configuration of Google Cast is necessary."
|
||||
},
|
||||
"step": {
|
||||
"confirm": {
|
||||
"description": "Do you want to setup Google Cast?",
|
||||
"title": "Google Cast"
|
||||
}
|
||||
},
|
||||
"title": "Google Cast"
|
||||
}
|
||||
}
|
30
homeassistant/components/cast/__init__.py
Normal file
30
homeassistant/components/cast/__init__.py
Normal file
@ -0,0 +1,30 @@
|
||||
"""Component to embed Google Cast."""
|
||||
from homeassistant.helpers import config_entry_flow
|
||||
|
||||
|
||||
DOMAIN = 'cast'
|
||||
REQUIREMENTS = ['pychromecast==2.1.0']
|
||||
|
||||
|
||||
async def async_setup(hass, config):
|
||||
"""Set up the Cast component."""
|
||||
hass.data[DOMAIN] = config.get(DOMAIN, {})
|
||||
return True
|
||||
|
||||
|
||||
async def async_setup_entry(hass, entry):
|
||||
"""Set up Cast from a config entry."""
|
||||
hass.async_add_job(hass.config_entries.async_forward_entry_setup(
|
||||
entry, 'media_player'))
|
||||
return True
|
||||
|
||||
|
||||
async def _async_has_devices(hass):
|
||||
"""Return if there are devices that can be discovered."""
|
||||
from pychromecast.discovery import discover_chromecasts
|
||||
|
||||
return await hass.async_add_job(discover_chromecasts)
|
||||
|
||||
|
||||
config_entry_flow.register_discovery_flow(
|
||||
DOMAIN, 'Google Cast', _async_has_devices)
|
15
homeassistant/components/cast/strings.json
Normal file
15
homeassistant/components/cast/strings.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"config": {
|
||||
"title": "Google Cast",
|
||||
"step": {
|
||||
"confirm": {
|
||||
"title": "Google Cast",
|
||||
"description": "Do you want to setup Google Cast?"
|
||||
}
|
||||
},
|
||||
"abort": {
|
||||
"single_instance_allowed": "Only a single configuration of Google Cast is necessary.",
|
||||
"no_devices_found": "No Google Cast devices found on the network."
|
||||
}
|
||||
}
|
||||
}
|
@ -46,7 +46,9 @@ SERVICE_HOMEKIT = 'homekit'
|
||||
|
||||
CONFIG_ENTRY_HANDLERS = {
|
||||
SERVICE_DECONZ: 'deconz',
|
||||
'google_cast': 'cast',
|
||||
SERVICE_HUE: 'hue',
|
||||
'sonos': 'sonos',
|
||||
}
|
||||
|
||||
SERVICE_HANDLERS = {
|
||||
@ -64,11 +66,9 @@ SERVICE_HANDLERS = {
|
||||
SERVICE_SABNZBD: ('sabnzbd', None),
|
||||
SERVICE_SAMSUNG_PRINTER: ('sensor', 'syncthru'),
|
||||
SERVICE_KONNECTED: ('konnected', None),
|
||||
'google_cast': ('media_player', 'cast'),
|
||||
'panasonic_viera': ('media_player', 'panasonic_viera'),
|
||||
'plex_mediaserver': ('media_player', 'plex'),
|
||||
'roku': ('media_player', 'roku'),
|
||||
'sonos': ('media_player', 'sonos'),
|
||||
'yamaha': ('media_player', 'yamaha'),
|
||||
'logitech_mediaserver': ('media_player', 'squeezebox'),
|
||||
'directv': ('media_player', 'directv'),
|
||||
|
@ -456,6 +456,16 @@ async def async_setup(hass, config):
|
||||
return True
|
||||
|
||||
|
||||
async def async_setup_entry(hass, entry):
|
||||
"""Setup a config entry."""
|
||||
return await hass.data[DOMAIN].async_setup_entry(entry)
|
||||
|
||||
|
||||
async def async_unload_entry(hass, entry):
|
||||
"""Unload a config entry."""
|
||||
return await hass.data[DOMAIN].async_unload_entry(entry)
|
||||
|
||||
|
||||
class MediaPlayerDevice(Entity):
|
||||
"""ABC for media player devices."""
|
||||
|
||||
|
@ -17,6 +17,7 @@ from homeassistant.helpers.typing import HomeAssistantType, ConfigType
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.dispatcher import (dispatcher_send,
|
||||
async_dispatcher_connect)
|
||||
from homeassistant.components.cast import DOMAIN as CAST_DOMAIN
|
||||
from homeassistant.components.media_player import (
|
||||
MEDIA_TYPE_MUSIC, MEDIA_TYPE_TVSHOW, MEDIA_TYPE_MOVIE, SUPPORT_NEXT_TRACK,
|
||||
SUPPORT_PAUSE, SUPPORT_PLAY_MEDIA, SUPPORT_PREVIOUS_TRACK,
|
||||
@ -28,7 +29,7 @@ from homeassistant.const import (
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
import homeassistant.util.dt as dt_util
|
||||
|
||||
REQUIREMENTS = ['pychromecast==2.1.0']
|
||||
DEPENDENCIES = ('cast',)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@ -186,6 +187,26 @@ def _async_create_cast_device(hass: HomeAssistantType,
|
||||
|
||||
async def async_setup_platform(hass: HomeAssistantType, config: ConfigType,
|
||||
async_add_devices, discovery_info=None):
|
||||
"""Set up thet Cast platform.
|
||||
|
||||
Deprecated.
|
||||
"""
|
||||
_LOGGER.warning(
|
||||
'Setting configuration for Cast via platform is deprecated. '
|
||||
'Configure via Cast component instead.')
|
||||
await _async_setup_platform(
|
||||
hass, config, async_add_devices, discovery_info)
|
||||
|
||||
|
||||
async def async_setup_entry(hass, config_entry, async_add_devices):
|
||||
"""Set up Cast from a config entry."""
|
||||
await _async_setup_platform(
|
||||
hass, hass.data[CAST_DOMAIN].get('media_player', {}),
|
||||
async_add_devices, None)
|
||||
|
||||
|
||||
async def _async_setup_platform(hass: HomeAssistantType, config: ConfigType,
|
||||
async_add_devices, discovery_info):
|
||||
"""Set up the cast platform."""
|
||||
import pychromecast
|
||||
|
||||
|
@ -20,13 +20,14 @@ from homeassistant.components.media_player import (
|
||||
SUPPORT_PLAY_MEDIA, SUPPORT_PREVIOUS_TRACK, SUPPORT_SEEK,
|
||||
SUPPORT_SELECT_SOURCE, SUPPORT_SHUFFLE_SET, SUPPORT_STOP,
|
||||
SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_SET, MediaPlayerDevice)
|
||||
from homeassistant.components.sonos import DOMAIN as SONOS_DOMAIN
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID, ATTR_TIME, CONF_HOSTS, STATE_IDLE, STATE_OFF, STATE_PAUSED,
|
||||
STATE_PLAYING)
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.util.dt import utcnow
|
||||
|
||||
REQUIREMENTS = ['SoCo==0.14']
|
||||
DEPENDENCIES = ('sonos',)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@ -49,7 +50,7 @@ SERVICE_CLEAR_TIMER = 'sonos_clear_sleep_timer'
|
||||
SERVICE_UPDATE_ALARM = 'sonos_update_alarm'
|
||||
SERVICE_SET_OPTION = 'sonos_set_option'
|
||||
|
||||
DATA_SONOS = 'sonos'
|
||||
DATA_SONOS = 'sonos_devices'
|
||||
|
||||
SOURCE_LINEIN = 'Line-in'
|
||||
SOURCE_TV = 'TV'
|
||||
@ -118,6 +119,26 @@ class SonosData:
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
"""Set up the Sonos platform.
|
||||
|
||||
Deprecated.
|
||||
"""
|
||||
_LOGGER.warning('Loading Sonos via platform config is deprecated.')
|
||||
_setup_platform(hass, config, add_devices, discovery_info)
|
||||
|
||||
|
||||
async def async_setup_entry(hass, config_entry, async_add_devices):
|
||||
"""Set up Sonos from a config entry."""
|
||||
def add_devices(devices, update_before_add=False):
|
||||
"""Sync version of async add devices."""
|
||||
hass.add_job(async_add_devices, devices, update_before_add)
|
||||
|
||||
hass.add_job(_setup_platform, hass,
|
||||
hass.data[SONOS_DOMAIN].get('media_player', {}),
|
||||
add_devices, None)
|
||||
|
||||
|
||||
def _setup_platform(hass, config, add_devices, discovery_info):
|
||||
"""Set up the Sonos platform."""
|
||||
import soco
|
||||
import soco.events
|
||||
|
15
homeassistant/components/sonos/.translations/en.json
Normal file
15
homeassistant/components/sonos/.translations/en.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"no_devices_found": "No Sonos devices found on the network.",
|
||||
"single_instance_allowed": "Only a single configuration of Sonos is necessary."
|
||||
},
|
||||
"step": {
|
||||
"confirm": {
|
||||
"description": "Do you want to setup Sonos?",
|
||||
"title": "Sonos"
|
||||
}
|
||||
},
|
||||
"title": "Sonos"
|
||||
}
|
||||
}
|
29
homeassistant/components/sonos/__init__.py
Normal file
29
homeassistant/components/sonos/__init__.py
Normal file
@ -0,0 +1,29 @@
|
||||
"""Component to embed Sonos."""
|
||||
from homeassistant.helpers import config_entry_flow
|
||||
|
||||
|
||||
DOMAIN = 'sonos'
|
||||
REQUIREMENTS = ['SoCo==0.14']
|
||||
|
||||
|
||||
async def async_setup(hass, config):
|
||||
"""Set up the Sonos component."""
|
||||
hass.data[DOMAIN] = config.get(DOMAIN, {})
|
||||
return True
|
||||
|
||||
|
||||
async def async_setup_entry(hass, entry):
|
||||
"""Set up Sonos from a config entry."""
|
||||
hass.async_add_job(hass.config_entries.async_forward_entry_setup(
|
||||
entry, 'media_player'))
|
||||
return True
|
||||
|
||||
|
||||
async def _async_has_devices(hass):
|
||||
"""Return if there are devices that can be discovered."""
|
||||
import soco
|
||||
|
||||
return await hass.async_add_job(soco.discover)
|
||||
|
||||
|
||||
config_entry_flow.register_discovery_flow(DOMAIN, 'Sonos', _async_has_devices)
|
15
homeassistant/components/sonos/strings.json
Normal file
15
homeassistant/components/sonos/strings.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"config": {
|
||||
"title": "Sonos",
|
||||
"step": {
|
||||
"confirm": {
|
||||
"title": "Sonos",
|
||||
"description": "Do you want to setup Sonos?"
|
||||
}
|
||||
},
|
||||
"abort": {
|
||||
"single_instance_allowed": "Only a single configuration of Sonos is necessary.",
|
||||
"no_devices_found": "No Sonos devices found on the network."
|
||||
}
|
||||
}
|
||||
}
|
@ -127,9 +127,11 @@ _LOGGER = logging.getLogger(__name__)
|
||||
HANDLERS = Registry()
|
||||
# Components that have config flows. In future we will auto-generate this list.
|
||||
FLOWS = [
|
||||
'cast',
|
||||
'deconz',
|
||||
'hue',
|
||||
'nest',
|
||||
'sonos',
|
||||
'zone',
|
||||
]
|
||||
|
||||
|
85
homeassistant/helpers/config_entry_flow.py
Normal file
85
homeassistant/helpers/config_entry_flow.py
Normal file
@ -0,0 +1,85 @@
|
||||
"""Helpers for data entry flows for config entries."""
|
||||
from functools import partial
|
||||
|
||||
from homeassistant.core import callback
|
||||
from homeassistant import config_entries, data_entry_flow
|
||||
|
||||
|
||||
def register_discovery_flow(domain, title, discovery_function):
|
||||
"""Register flow for discovered integrations that not require auth."""
|
||||
config_entries.HANDLERS.register(domain)(
|
||||
partial(DiscoveryFlowHandler, domain, title, discovery_function))
|
||||
|
||||
|
||||
class DiscoveryFlowHandler(data_entry_flow.FlowHandler):
|
||||
"""Handle a discovery config flow."""
|
||||
|
||||
VERSION = 1
|
||||
|
||||
def __init__(self, domain, title, discovery_function):
|
||||
"""Initialize the discovery config flow."""
|
||||
self._domain = domain
|
||||
self._title = title
|
||||
self._discovery_function = discovery_function
|
||||
|
||||
async def async_step_init(self, user_input=None):
|
||||
"""Handle a flow initialized by the user."""
|
||||
if self._async_current_entries():
|
||||
return self.async_abort(
|
||||
reason='single_instance_allowed'
|
||||
)
|
||||
|
||||
# Get current discovered entries.
|
||||
in_progress = self._async_in_progress()
|
||||
|
||||
has_devices = in_progress
|
||||
if not has_devices:
|
||||
has_devices = await self.hass.async_add_job(
|
||||
self._discovery_function, self.hass)
|
||||
|
||||
if not has_devices:
|
||||
return self.async_abort(
|
||||
reason='no_devices_found'
|
||||
)
|
||||
|
||||
# Cancel the discovered one.
|
||||
for flow in in_progress:
|
||||
self.hass.config_entries.flow.async_abort(flow['flow_id'])
|
||||
|
||||
return self.async_create_entry(
|
||||
title=self._title,
|
||||
data={},
|
||||
)
|
||||
|
||||
async def async_step_confirm(self, user_input=None):
|
||||
"""Confirm setup."""
|
||||
if user_input is not None:
|
||||
return self.async_create_entry(
|
||||
title=self._title,
|
||||
data={},
|
||||
)
|
||||
|
||||
return self.async_show_form(
|
||||
step_id='confirm',
|
||||
)
|
||||
|
||||
async def async_step_discovery(self, discovery_info):
|
||||
"""Handle a flow initialized by discovery."""
|
||||
if self._async_in_progress() or self._async_current_entries():
|
||||
return self.async_abort(
|
||||
reason='single_instance_allowed'
|
||||
)
|
||||
|
||||
return await self.async_step_confirm()
|
||||
|
||||
@callback
|
||||
def _async_current_entries(self):
|
||||
"""Return current entries."""
|
||||
return self.hass.config_entries.async_entries(self._domain)
|
||||
|
||||
@callback
|
||||
def _async_in_progress(self):
|
||||
"""Return other in progress flows for current domain."""
|
||||
return [flw for flw in self.hass.config_entries.flow.async_progress()
|
||||
if flw['handler'] == self._domain and
|
||||
flw['flow_id'] != self.flow_id]
|
@ -54,7 +54,7 @@ PyXiaomiGateway==0.9.5
|
||||
# homeassistant.components.remember_the_milk
|
||||
RtmAPI==0.7.0
|
||||
|
||||
# homeassistant.components.media_player.sonos
|
||||
# homeassistant.components.sonos
|
||||
SoCo==0.14
|
||||
|
||||
# homeassistant.components.sensor.travisci
|
||||
@ -773,7 +773,7 @@ pyblackbird==0.5
|
||||
# homeassistant.components.media_player.channels
|
||||
pychannels==1.0.0
|
||||
|
||||
# homeassistant.components.media_player.cast
|
||||
# homeassistant.components.cast
|
||||
pychromecast==2.1.0
|
||||
|
||||
# homeassistant.components.media_player.cmus
|
||||
|
@ -24,7 +24,7 @@ HAP-python==2.2.2
|
||||
# homeassistant.components.notify.html5
|
||||
PyJWT==1.6.0
|
||||
|
||||
# homeassistant.components.media_player.sonos
|
||||
# homeassistant.components.sonos
|
||||
SoCo==0.14
|
||||
|
||||
# homeassistant.components.device_tracker.automatic
|
||||
|
1
tests/components/cast/__init__.py
Normal file
1
tests/components/cast/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
"""Tests for the Cast component."""
|
22
tests/components/cast/test_init.py
Normal file
22
tests/components/cast/test_init.py
Normal file
@ -0,0 +1,22 @@
|
||||
"""Tests for the Cast config flow."""
|
||||
from unittest.mock import patch
|
||||
|
||||
from homeassistant import data_entry_flow
|
||||
from homeassistant.components import cast
|
||||
|
||||
from tests.common import MockDependency, mock_coro
|
||||
|
||||
|
||||
async def test_creating_entry_sets_up_media_player(hass):
|
||||
"""Test setting up Cast loads the media player."""
|
||||
with patch('homeassistant.components.media_player.cast.async_setup_entry',
|
||||
return_value=mock_coro(True)) as mock_setup, \
|
||||
MockDependency('pychromecast', 'discovery'), \
|
||||
patch('pychromecast.discovery.discover_chromecasts',
|
||||
return_value=True):
|
||||
result = await hass.config_entries.flow.async_init(cast.DOMAIN)
|
||||
assert result['type'] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(mock_setup.mock_calls) == 1
|
1
tests/components/sonos/__init__.py
Normal file
1
tests/components/sonos/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
"""Tests for the Sonos component."""
|
20
tests/components/sonos/test_init.py
Normal file
20
tests/components/sonos/test_init.py
Normal file
@ -0,0 +1,20 @@
|
||||
"""Tests for the Sonos config flow."""
|
||||
from unittest.mock import patch
|
||||
|
||||
from homeassistant import data_entry_flow
|
||||
from homeassistant.components import sonos
|
||||
|
||||
from tests.common import mock_coro
|
||||
|
||||
|
||||
async def test_creating_entry_sets_up_media_player(hass):
|
||||
"""Test setting up Sonos loads the media player."""
|
||||
with patch('homeassistant.components.media_player.sonos.async_setup_entry',
|
||||
return_value=mock_coro(True)) as mock_setup, \
|
||||
patch('soco.discover', return_value=True):
|
||||
result = await hass.config_entries.flow.async_init(sonos.DOMAIN)
|
||||
assert result['type'] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(mock_setup.mock_calls) == 1
|
116
tests/helpers/test_config_entry_flow.py
Normal file
116
tests/helpers/test_config_entry_flow.py
Normal file
@ -0,0 +1,116 @@
|
||||
"""Tests for the Config Entry Flow helper."""
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant import config_entries, data_entry_flow, loader
|
||||
from homeassistant.helpers import config_entry_flow
|
||||
from tests.common import MockConfigEntry, MockModule
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def flow_conf(hass):
|
||||
"""Register a handler."""
|
||||
handler_conf = {
|
||||
'discovered': False,
|
||||
}
|
||||
|
||||
async def has_discovered_devices(hass):
|
||||
"""Mock if we have discovered devices."""
|
||||
return handler_conf['discovered']
|
||||
|
||||
with patch.dict(config_entries.HANDLERS):
|
||||
config_entry_flow.register_discovery_flow(
|
||||
'test', 'Test', has_discovered_devices)
|
||||
yield handler_conf
|
||||
|
||||
|
||||
async def test_single_entry_allowed(hass, flow_conf):
|
||||
"""Test only a single entry is allowed."""
|
||||
flow = config_entries.HANDLERS['test']()
|
||||
flow.hass = hass
|
||||
|
||||
MockConfigEntry(domain='test').add_to_hass(hass)
|
||||
result = await flow.async_step_init()
|
||||
|
||||
assert result['type'] == data_entry_flow.RESULT_TYPE_ABORT
|
||||
assert result['reason'] == 'single_instance_allowed'
|
||||
|
||||
|
||||
async def test_user_no_devices_found(hass, flow_conf):
|
||||
"""Test if no devices found."""
|
||||
flow = config_entries.HANDLERS['test']()
|
||||
flow.hass = hass
|
||||
|
||||
result = await flow.async_step_init()
|
||||
|
||||
assert result['type'] == data_entry_flow.RESULT_TYPE_ABORT
|
||||
assert result['reason'] == 'no_devices_found'
|
||||
|
||||
|
||||
async def test_user_no_confirmation(hass, flow_conf):
|
||||
"""Test user requires no confirmation to setup."""
|
||||
flow = config_entries.HANDLERS['test']()
|
||||
flow.hass = hass
|
||||
flow_conf['discovered'] = True
|
||||
|
||||
result = await flow.async_step_init()
|
||||
|
||||
assert result['type'] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||
|
||||
|
||||
async def test_discovery_single_instance(hass, flow_conf):
|
||||
"""Test we ask for confirmation via discovery."""
|
||||
flow = config_entries.HANDLERS['test']()
|
||||
flow.hass = hass
|
||||
|
||||
MockConfigEntry(domain='test').add_to_hass(hass)
|
||||
result = await flow.async_step_discovery({})
|
||||
|
||||
assert result['type'] == data_entry_flow.RESULT_TYPE_ABORT
|
||||
assert result['reason'] == 'single_instance_allowed'
|
||||
|
||||
|
||||
async def test_discovery_confirmation(hass, flow_conf):
|
||||
"""Test we ask for confirmation via discovery."""
|
||||
flow = config_entries.HANDLERS['test']()
|
||||
flow.hass = hass
|
||||
|
||||
result = await flow.async_step_discovery({})
|
||||
|
||||
assert result['type'] == data_entry_flow.RESULT_TYPE_FORM
|
||||
assert result['step_id'] == 'confirm'
|
||||
|
||||
result = await flow.async_step_confirm({})
|
||||
assert result['type'] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||
|
||||
|
||||
async def test_multiple_discoveries(hass, flow_conf):
|
||||
"""Test we only create one instance for multiple discoveries."""
|
||||
loader.set_component(hass, 'test', MockModule('test'))
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
'test', source=data_entry_flow.SOURCE_DISCOVERY, data={})
|
||||
assert result['type'] == data_entry_flow.RESULT_TYPE_FORM
|
||||
|
||||
# Second discovery
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
'test', source=data_entry_flow.SOURCE_DISCOVERY, data={})
|
||||
assert result['type'] == data_entry_flow.RESULT_TYPE_ABORT
|
||||
|
||||
|
||||
async def test_user_init_trumps_discovery(hass, flow_conf):
|
||||
"""Test a user initialized one will finish and cancel discovered one."""
|
||||
loader.set_component(hass, 'test', MockModule('test'))
|
||||
|
||||
# Discovery starts flow
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
'test', source=data_entry_flow.SOURCE_DISCOVERY, data={})
|
||||
assert result['type'] == data_entry_flow.RESULT_TYPE_FORM
|
||||
|
||||
# User starts flow
|
||||
result = await hass.config_entries.flow.async_init('test', data={})
|
||||
assert result['type'] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||
|
||||
# Discovery flow has been aborted
|
||||
assert len(hass.config_entries.flow.async_progress()) == 0
|
Loading…
x
Reference in New Issue
Block a user