Fix HEOS discovery could result in multiple config entries (#22903)

* Prevent duplicate entries from discovery

* Update reqs files

* Prevent duplicate entries from discovery
This commit is contained in:
Andrew Sayre 2019-04-08 21:24:40 -05:00 committed by GitHub
parent d577955d1e
commit 38f063a158
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 68 additions and 29 deletions

View File

@ -19,7 +19,7 @@ from .const import (
COMMAND_RETRY_ATTEMPTS, COMMAND_RETRY_DELAY, DATA_CONTROLLER,
DATA_SOURCE_MANAGER, DOMAIN, SIGNAL_HEOS_SOURCES_UPDATED)
REQUIREMENTS = ['pyheos==0.3.0']
REQUIREMENTS = ['pyheos==0.3.1']
CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({

View File

@ -23,8 +23,13 @@ class HeosFlowHandler(config_entries.ConfigFlow):
async def async_step_discovery(self, discovery_info):
"""Handle a discovered Heos device."""
return await self.async_step_user(
{CONF_HOST: discovery_info[CONF_HOST]})
# Only continue if this is the only active flow
flows = self.hass.config_entries.flow.async_progress()
heos_flows = [flow for flow in flows if flow['handler'] == DOMAIN]
if len(heos_flows) == 1:
return await self.async_step_user(
{CONF_HOST: discovery_info[CONF_HOST]})
return self.async_abort(reason='already_setup')
async def async_step_import(self, user_input=None):
"""Occurs when an entry is setup through config."""

View File

@ -3,7 +3,7 @@
"name": "Heos",
"documentation": "https://www.home-assistant.io/components/heos",
"requirements": [
"pyheos==0.3.0"
"pyheos==0.3.1"
],
"dependencies": [],
"codeowners": [

View File

@ -1064,7 +1064,7 @@ pygtt==1.1.2
pyhaversion==2.0.3
# homeassistant.components.heos
pyheos==0.3.0
pyheos==0.3.1
# homeassistant.components.hikvision
pyhik==0.2.2

View File

@ -204,7 +204,7 @@ pydeconz==54
pydispatcher==2.0.5
# homeassistant.components.heos
pyheos==0.3.0
pyheos==0.3.1
# homeassistant.components.homematic
pyhomematic==0.1.58

View File

@ -103,3 +103,21 @@ def input_sources_fixture() -> Sequence[InputSource]:
def dispatcher_fixture() -> Dispatcher:
"""Create a dispatcher for testing."""
return Dispatcher()
@pytest.fixture(name="discovery_data")
def discovery_data_fixture() -> dict:
"""Return mock discovery data for testing."""
return {
'host': '127.0.0.1',
'manufacturer': 'Denon',
'model_name': 'HEOS Drive',
'model_number': 'DWSA-10 4.0',
'name': 'Office',
'port': 60006,
'serial': None,
'ssdp_description':
'http://127.0.0.1:60006/upnp/desc/aios_device/aios_device.xml',
'udn': 'uuid:e61de70c-2250-1c22-0080-0005cdf512be',
'upnp_device_type': 'urn:schemas-denon-com:device:AiosDevice:1'
}

View File

@ -3,6 +3,7 @@ import asyncio
from homeassistant import data_entry_flow
from homeassistant.components.heos.config_flow import HeosFlowHandler
from homeassistant.components.heos.const import DOMAIN
from homeassistant.const import CONF_HOST
@ -57,26 +58,41 @@ async def test_create_entry_when_host_valid(hass, controller):
assert controller.disconnect.call_count == 1
async def test_create_entry_with_discovery(hass, controller):
"""Test result type is create entry when valid through discovery."""
flow = HeosFlowHandler()
flow.hass = hass
data = {
'host': '127.0.0.1',
'manufacturer': 'Denon',
'model_name': 'HEOS Drive',
'model_number': 'DWSA-10 4.0',
'name': 'Office',
'port': 60006,
'serial': None,
'ssdp_description':
'http://127.0.0.1:60006/upnp/desc/aios_device/aios_device.xml',
'udn': 'uuid:e61de70c-2250-1c22-0080-0005cdf512be',
'upnp_device_type': 'urn:schemas-denon-com:device:AiosDevice:1'
}
result = await flow.async_step_discovery(data)
assert result['type'] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
assert result['title'] == 'Controller (127.0.0.1)'
assert result['data'] == {'host': '127.0.0.1'}
assert controller.connect.call_count == 1
assert controller.disconnect.call_count == 1
async def test_create_entry_with_discovery(hass, controller, discovery_data):
"""Test discovery creates entry."""
await hass.config_entries.flow.async_init(
DOMAIN, context={'source': 'discovery'},
data=discovery_data)
await hass.async_block_till_done()
entries = hass.config_entries.async_entries(DOMAIN)
assert len(entries) == 1
assert entries[0].data == {CONF_HOST: discovery_data[CONF_HOST]}
assert entries[0].title == 'Controller (127.0.0.1)'
async def test_entry_already_exists_discovery(
hass, controller, discovery_data, config_entry):
"""Test discovery does not create multiple entries when already setup."""
config_entry.add_to_hass(hass)
await hass.config_entries.flow.async_init(
DOMAIN, context={'source': 'discovery'},
data=discovery_data)
await hass.async_block_till_done()
entries = hass.config_entries.async_entries(DOMAIN)
assert len(entries) == 1
async def test_multiple_discovery_creates_single_entry(
hass, controller, discovery_data):
"""Test discovery of multiple devices creates a single entry."""
hass.async_create_task(
hass.config_entries.flow.async_init(
DOMAIN, context={'source': 'discovery'},
data={CONF_HOST: discovery_data}))
hass.async_create_task(
hass.config_entries.flow.async_init(
DOMAIN, context={'source': 'discovery'},
data={CONF_HOST: discovery_data}))
await hass.async_block_till_done()
entries = hass.config_entries.async_entries(DOMAIN)
assert len(entries) == 1