deCONZ - Allow manual configuration to update existing configuration (#30469)
* Allow manual configuration to update existing configuration * Harmonize testspull/30493/head
parent
639cdf5eef
commit
967fe89f6d
|
@ -147,8 +147,17 @@ class DeconzFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
self.bridge_id = await async_get_bridge_id(
|
||||
session, **self.deconz_config
|
||||
)
|
||||
|
||||
for entry in self.hass.config_entries.async_entries(DOMAIN):
|
||||
if self.bridge_id == entry.unique_id:
|
||||
return self._update_entry(
|
||||
entry,
|
||||
host=self.deconz_config[CONF_HOST],
|
||||
port=self.deconz_config[CONF_PORT],
|
||||
api_key=self.deconz_config[CONF_API_KEY],
|
||||
)
|
||||
|
||||
await self.async_set_unique_id(self.bridge_id)
|
||||
self._abort_if_unique_id_configured()
|
||||
|
||||
except asyncio.TimeoutError:
|
||||
return self.async_abort(reason="no_bridges")
|
||||
|
|
|
@ -1,36 +1,23 @@
|
|||
"""Tests for deCONZ config flow."""
|
||||
import asyncio
|
||||
from copy import deepcopy
|
||||
|
||||
from asynctest import Mock, patch
|
||||
import pydeconz
|
||||
|
||||
from homeassistant.components import ssdp
|
||||
from homeassistant.components.deconz import config_flow
|
||||
from homeassistant.components.deconz.const import CONF_BRIDGEID
|
||||
|
||||
from .test_gateway import (
|
||||
BRIDGEID,
|
||||
DECONZ_WEB_REQUEST,
|
||||
ENTRY_CONFIG,
|
||||
setup_deconz_integration,
|
||||
)
|
||||
from .test_gateway import API_KEY, BRIDGEID, setup_deconz_integration
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
async def test_flow_works(hass, aioclient_mock):
|
||||
"""Test that config flow works."""
|
||||
async def test_flow_1_discovered_bridge(hass, aioclient_mock):
|
||||
"""Test that config flow for one discovered bridge works."""
|
||||
aioclient_mock.get(
|
||||
pydeconz.utils.URL_DISCOVER,
|
||||
json=[{"id": BRIDGEID, "internalipaddress": "1.2.3.4", "internalport": 80}],
|
||||
headers={"content-type": "application/json"},
|
||||
)
|
||||
aioclient_mock.post(
|
||||
"http://1.2.3.4:80/api",
|
||||
json=[{"success": {"username": "1234567890ABCDEF"}}],
|
||||
headers={"content-type": "application/json"},
|
||||
)
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
config_flow.DOMAIN, context={"source": "user"}
|
||||
|
@ -39,6 +26,12 @@ async def test_flow_works(hass, aioclient_mock):
|
|||
assert result["type"] == "form"
|
||||
assert result["step_id"] == "link"
|
||||
|
||||
aioclient_mock.post(
|
||||
"http://1.2.3.4:80/api",
|
||||
json=[{"success": {"username": API_KEY}}],
|
||||
headers={"content-type": "application/json"},
|
||||
)
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={}
|
||||
)
|
||||
|
@ -48,65 +41,17 @@ async def test_flow_works(hass, aioclient_mock):
|
|||
assert result["data"] == {
|
||||
config_flow.CONF_HOST: "1.2.3.4",
|
||||
config_flow.CONF_PORT: 80,
|
||||
config_flow.CONF_API_KEY: "1234567890ABCDEF",
|
||||
config_flow.CONF_API_KEY: API_KEY,
|
||||
}
|
||||
|
||||
|
||||
async def test_user_step_bridge_discovery_fails(hass, aioclient_mock):
|
||||
"""Test config flow works when discovery fails."""
|
||||
with patch(
|
||||
"homeassistant.components.deconz.config_flow.async_discovery",
|
||||
side_effect=asyncio.TimeoutError,
|
||||
):
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
config_flow.DOMAIN, context={"source": "user"}
|
||||
)
|
||||
|
||||
assert result["type"] == "form"
|
||||
assert result["step_id"] == "init"
|
||||
|
||||
|
||||
async def test_user_step_no_discovered_bridges(hass, aioclient_mock):
|
||||
"""Test config flow discovers no bridges."""
|
||||
aioclient_mock.get(
|
||||
pydeconz.utils.URL_DISCOVER,
|
||||
json=[],
|
||||
headers={"content-type": "application/json"},
|
||||
)
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
config_flow.DOMAIN, context={"source": "user"}
|
||||
)
|
||||
|
||||
assert result["type"] == "form"
|
||||
assert result["step_id"] == "init"
|
||||
|
||||
|
||||
async def test_user_step_one_bridge_discovered(hass, aioclient_mock):
|
||||
"""Test config flow discovers one bridge."""
|
||||
aioclient_mock.get(
|
||||
pydeconz.utils.URL_DISCOVER,
|
||||
json=[{"id": "id", "internalipaddress": "1.2.3.4", "internalport": 80}],
|
||||
headers={"content-type": "application/json"},
|
||||
)
|
||||
|
||||
flow = config_flow.DeconzFlowHandler()
|
||||
flow.hass = hass
|
||||
|
||||
result = await flow.async_step_user()
|
||||
|
||||
assert result["type"] == "form"
|
||||
assert result["step_id"] == "link"
|
||||
assert flow.deconz_config[config_flow.CONF_HOST] == "1.2.3.4"
|
||||
|
||||
|
||||
async def test_user_step_two_bridges_discovered(hass, aioclient_mock):
|
||||
"""Test config flow discovers two bridges."""
|
||||
async def test_flow_2_discovered_bridges(hass, aioclient_mock):
|
||||
"""Test that config flow works for multiple discovered bridges."""
|
||||
aioclient_mock.get(
|
||||
pydeconz.utils.URL_DISCOVER,
|
||||
json=[
|
||||
{"id": "id1", "internalipaddress": "1.2.3.4", "internalport": 80},
|
||||
{"id": "id2", "internalipaddress": "5.6.7.8", "internalport": 80},
|
||||
{"id": BRIDGEID, "internalipaddress": "1.2.3.4", "internalport": 80},
|
||||
{"id": "1234E567890A", "internalipaddress": "5.6.7.8", "internalport": 80},
|
||||
],
|
||||
headers={"content-type": "application/json"},
|
||||
)
|
||||
|
@ -115,37 +60,37 @@ async def test_user_step_two_bridges_discovered(hass, aioclient_mock):
|
|||
config_flow.DOMAIN, context={"source": "user"}
|
||||
)
|
||||
|
||||
assert result["data_schema"]({config_flow.CONF_HOST: "1.2.3.4"})
|
||||
assert result["data_schema"]({config_flow.CONF_HOST: "5.6.7.8"})
|
||||
assert result["type"] == "form"
|
||||
assert result["step_id"] == "init"
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={config_flow.CONF_HOST: "1.2.3.4"}
|
||||
)
|
||||
|
||||
async def test_user_step_two_bridges_selection(hass, aioclient_mock):
|
||||
"""Test config flow selection of one of two bridges."""
|
||||
flow = config_flow.DeconzFlowHandler()
|
||||
flow.hass = hass
|
||||
flow.bridges = [
|
||||
{
|
||||
CONF_BRIDGEID: "id1",
|
||||
config_flow.CONF_HOST: "1.2.3.4",
|
||||
config_flow.CONF_PORT: 80,
|
||||
},
|
||||
{
|
||||
CONF_BRIDGEID: "id2",
|
||||
config_flow.CONF_HOST: "5.6.7.8",
|
||||
config_flow.CONF_PORT: 80,
|
||||
},
|
||||
]
|
||||
|
||||
result = await flow.async_step_user(user_input={config_flow.CONF_HOST: "1.2.3.4"})
|
||||
assert result["type"] == "form"
|
||||
assert result["step_id"] == "link"
|
||||
assert flow.deconz_config[config_flow.CONF_HOST] == "1.2.3.4"
|
||||
|
||||
aioclient_mock.post(
|
||||
"http://1.2.3.4:80/api",
|
||||
json=[{"success": {"username": API_KEY}}],
|
||||
headers={"content-type": "application/json"},
|
||||
)
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={}
|
||||
)
|
||||
|
||||
assert result["type"] == "create_entry"
|
||||
assert result["title"] == BRIDGEID
|
||||
assert result["data"] == {
|
||||
config_flow.CONF_HOST: "1.2.3.4",
|
||||
config_flow.CONF_PORT: 80,
|
||||
config_flow.CONF_API_KEY: API_KEY,
|
||||
}
|
||||
|
||||
|
||||
async def test_user_step_manual_configuration_no_bridges_discovered(
|
||||
hass, aioclient_mock
|
||||
):
|
||||
"""Test config flow with manual input."""
|
||||
async def test_flow_manual_configuration(hass, aioclient_mock):
|
||||
"""Test that config flow works with manual configuration after no discovered bridges."""
|
||||
aioclient_mock.get(
|
||||
pydeconz.utils.URL_DISCOVER,
|
||||
json=[],
|
||||
|
@ -158,7 +103,6 @@ async def test_user_step_manual_configuration_no_bridges_discovered(
|
|||
|
||||
assert result["type"] == "form"
|
||||
assert result["step_id"] == "init"
|
||||
assert not hass.config_entries.flow._progress[result["flow_id"]].bridges
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
|
@ -168,63 +112,223 @@ async def test_user_step_manual_configuration_no_bridges_discovered(
|
|||
assert result["type"] == "form"
|
||||
assert result["step_id"] == "link"
|
||||
|
||||
aioclient_mock.post(
|
||||
"http://1.2.3.4:80/api",
|
||||
json=[{"success": {"username": API_KEY}}],
|
||||
headers={"content-type": "application/json"},
|
||||
)
|
||||
|
||||
async def test_user_step_manual_configuration_after_timeout(hass):
|
||||
"""Test config flow with manual input."""
|
||||
with patch(
|
||||
"homeassistant.components.deconz.config_flow.async_discovery",
|
||||
side_effect=asyncio.TimeoutError,
|
||||
):
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
config_flow.DOMAIN, context={"source": "user"}
|
||||
)
|
||||
aioclient_mock.get(
|
||||
f"http://1.2.3.4:80/api/{API_KEY}/config",
|
||||
json={"bridgeid": BRIDGEID},
|
||||
headers={"content-type": "application/json"},
|
||||
)
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={}
|
||||
)
|
||||
|
||||
assert result["type"] == "create_entry"
|
||||
assert result["title"] == BRIDGEID
|
||||
assert result["data"] == {
|
||||
config_flow.CONF_HOST: "1.2.3.4",
|
||||
config_flow.CONF_PORT: 80,
|
||||
config_flow.CONF_API_KEY: API_KEY,
|
||||
}
|
||||
|
||||
|
||||
async def test_manual_configuration_after_discovery_timeout(hass, aioclient_mock):
|
||||
"""Test failed discovery fallbacks to manual configuration."""
|
||||
aioclient_mock.get(pydeconz.utils.URL_DISCOVER, exc=asyncio.TimeoutError)
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
config_flow.DOMAIN, context={"source": "user"}
|
||||
)
|
||||
|
||||
assert result["type"] == "form"
|
||||
assert result["step_id"] == "init"
|
||||
assert not hass.config_entries.flow._progress[result["flow_id"]].bridges
|
||||
|
||||
|
||||
async def test_user_step_manual_configuration_after_ResponseError(hass):
|
||||
"""Test config flow with manual input."""
|
||||
with patch(
|
||||
"homeassistant.components.deconz.config_flow.async_discovery",
|
||||
side_effect=config_flow.ResponseError,
|
||||
):
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
config_flow.DOMAIN, context={"source": "user"}
|
||||
)
|
||||
async def test_manual_configuration_after_discovery_ResponseError(hass, aioclient_mock):
|
||||
"""Test failed discovery fallbacks to manual configuration."""
|
||||
aioclient_mock.get(pydeconz.utils.URL_DISCOVER, exc=config_flow.ResponseError)
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
config_flow.DOMAIN, context={"source": "user"}
|
||||
)
|
||||
|
||||
assert result["type"] == "form"
|
||||
assert result["step_id"] == "init"
|
||||
assert not hass.config_entries.flow._progress[result["flow_id"]].bridges
|
||||
|
||||
|
||||
async def test_link_no_api_key(hass):
|
||||
async def test_manual_configuration_update_configuration(hass, aioclient_mock):
|
||||
"""Test that manual configuration can update existing config entry."""
|
||||
gateway = await setup_deconz_integration(hass)
|
||||
|
||||
aioclient_mock.get(
|
||||
pydeconz.utils.URL_DISCOVER,
|
||||
json=[],
|
||||
headers={"content-type": "application/json"},
|
||||
)
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
config_flow.DOMAIN, context={"source": "user"}
|
||||
)
|
||||
|
||||
assert result["type"] == "form"
|
||||
assert result["step_id"] == "init"
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={config_flow.CONF_HOST: "2.3.4.5", config_flow.CONF_PORT: 80},
|
||||
)
|
||||
|
||||
assert result["type"] == "form"
|
||||
assert result["step_id"] == "link"
|
||||
|
||||
aioclient_mock.post(
|
||||
"http://2.3.4.5:80/api",
|
||||
json=[{"success": {"username": API_KEY}}],
|
||||
headers={"content-type": "application/json"},
|
||||
)
|
||||
|
||||
aioclient_mock.get(
|
||||
f"http://2.3.4.5:80/api/{API_KEY}/config",
|
||||
json={"bridgeid": BRIDGEID},
|
||||
headers={"content-type": "application/json"},
|
||||
)
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={}
|
||||
)
|
||||
|
||||
assert result["type"] == "abort"
|
||||
assert result["reason"] == "updated_instance"
|
||||
assert gateway.config_entry.data[config_flow.CONF_HOST] == "2.3.4.5"
|
||||
|
||||
|
||||
async def test_manual_configuration_dont_update_configuration(hass, aioclient_mock):
|
||||
"""Test that _create_entry work and that bridgeid can be requested."""
|
||||
await setup_deconz_integration(hass)
|
||||
|
||||
aioclient_mock.get(
|
||||
pydeconz.utils.URL_DISCOVER,
|
||||
json=[],
|
||||
headers={"content-type": "application/json"},
|
||||
)
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
config_flow.DOMAIN, context={"source": "user"}
|
||||
)
|
||||
|
||||
assert result["type"] == "form"
|
||||
assert result["step_id"] == "init"
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={config_flow.CONF_HOST: "1.2.3.4", config_flow.CONF_PORT: 80},
|
||||
)
|
||||
|
||||
assert result["type"] == "form"
|
||||
assert result["step_id"] == "link"
|
||||
|
||||
aioclient_mock.post(
|
||||
"http://1.2.3.4:80/api",
|
||||
json=[{"success": {"username": API_KEY}}],
|
||||
headers={"content-type": "application/json"},
|
||||
)
|
||||
|
||||
aioclient_mock.get(
|
||||
f"http://1.2.3.4:80/api/{API_KEY}/config",
|
||||
json={"bridgeid": BRIDGEID},
|
||||
headers={"content-type": "application/json"},
|
||||
)
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={}
|
||||
)
|
||||
|
||||
assert result["type"] == "abort"
|
||||
assert result["reason"] == "already_configured"
|
||||
|
||||
|
||||
async def test_manual_configuration_timeout_get_bridge(hass, aioclient_mock):
|
||||
"""Test that _create_entry handles a timeout."""
|
||||
aioclient_mock.get(
|
||||
pydeconz.utils.URL_DISCOVER,
|
||||
json=[],
|
||||
headers={"content-type": "application/json"},
|
||||
)
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
config_flow.DOMAIN, context={"source": "user"}
|
||||
)
|
||||
|
||||
assert result["type"] == "form"
|
||||
assert result["step_id"] == "init"
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={config_flow.CONF_HOST: "1.2.3.4", config_flow.CONF_PORT: 80},
|
||||
)
|
||||
|
||||
assert result["type"] == "form"
|
||||
assert result["step_id"] == "link"
|
||||
|
||||
aioclient_mock.post(
|
||||
"http://1.2.3.4:80/api",
|
||||
json=[{"success": {"username": API_KEY}}],
|
||||
headers={"content-type": "application/json"},
|
||||
)
|
||||
|
||||
aioclient_mock.get(
|
||||
f"http://1.2.3.4:80/api/{API_KEY}/config", exc=asyncio.TimeoutError
|
||||
)
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={}
|
||||
)
|
||||
|
||||
assert result["type"] == "abort"
|
||||
assert result["reason"] == "no_bridges"
|
||||
|
||||
|
||||
async def test_link_get_api_key_ResponseError(hass, aioclient_mock):
|
||||
"""Test config flow should abort if no API key was possible to retrieve."""
|
||||
flow = config_flow.DeconzFlowHandler()
|
||||
flow.hass = hass
|
||||
flow.deconz_config = {config_flow.CONF_HOST: "1.2.3.4", config_flow.CONF_PORT: 80}
|
||||
aioclient_mock.get(
|
||||
pydeconz.utils.URL_DISCOVER,
|
||||
json=[{"id": BRIDGEID, "internalipaddress": "1.2.3.4", "internalport": 80}],
|
||||
headers={"content-type": "application/json"},
|
||||
)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.deconz.config_flow.async_get_api_key",
|
||||
side_effect=pydeconz.errors.ResponseError,
|
||||
):
|
||||
result = await flow.async_step_link(user_input={})
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
config_flow.DOMAIN, context={"source": "user"}
|
||||
)
|
||||
|
||||
assert result["type"] == "form"
|
||||
assert result["step_id"] == "link"
|
||||
|
||||
aioclient_mock.post("http://1.2.3.4:80/api", exc=pydeconz.errors.ResponseError)
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={}
|
||||
)
|
||||
|
||||
assert result["type"] == "form"
|
||||
assert result["step_id"] == "link"
|
||||
assert result["errors"] == {"base": "no_key"}
|
||||
|
||||
|
||||
async def test_bridge_ssdp_discovery(hass):
|
||||
"""Test a bridge being discovered over ssdp."""
|
||||
async def test_flow_ssdp_discovery(hass, aioclient_mock):
|
||||
"""Test that config flow for one discovered bridge works."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
config_flow.DOMAIN,
|
||||
data={
|
||||
ssdp.ATTR_SSDP_LOCATION: "http://1.2.3.4:80/",
|
||||
ssdp.ATTR_UPNP_MANUFACTURER_URL: config_flow.DECONZ_MANUFACTURERURL,
|
||||
ssdp.ATTR_UPNP_SERIAL: "id",
|
||||
ssdp.ATTR_UPNP_UDN: "uuid:1234",
|
||||
ssdp.ATTR_UPNP_SERIAL: BRIDGEID,
|
||||
},
|
||||
context={"source": "ssdp"},
|
||||
)
|
||||
|
@ -232,8 +336,26 @@ async def test_bridge_ssdp_discovery(hass):
|
|||
assert result["type"] == "form"
|
||||
assert result["step_id"] == "link"
|
||||
|
||||
aioclient_mock.post(
|
||||
"http://1.2.3.4:80/api",
|
||||
json=[{"success": {"username": API_KEY}}],
|
||||
headers={"content-type": "application/json"},
|
||||
)
|
||||
|
||||
async def test_bridge_ssdp_discovery_not_deconz_bridge(hass):
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={}
|
||||
)
|
||||
|
||||
assert result["type"] == "create_entry"
|
||||
assert result["title"] == BRIDGEID
|
||||
assert result["data"] == {
|
||||
config_flow.CONF_HOST: "1.2.3.4",
|
||||
config_flow.CONF_PORT: 80,
|
||||
config_flow.CONF_API_KEY: API_KEY,
|
||||
}
|
||||
|
||||
|
||||
async def test_ssdp_discovery_not_deconz_bridge(hass):
|
||||
"""Test a non deconz bridge being discovered over ssdp."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
config_flow.DOMAIN,
|
||||
|
@ -245,24 +367,14 @@ async def test_bridge_ssdp_discovery_not_deconz_bridge(hass):
|
|||
assert result["reason"] == "not_deconz_bridge"
|
||||
|
||||
|
||||
async def test_bridge_discovery_update_existing_entry(hass):
|
||||
"""Test if a discovered bridge has already been configured."""
|
||||
entry = MockConfigEntry(
|
||||
domain=config_flow.DOMAIN,
|
||||
source="user",
|
||||
data={config_flow.CONF_HOST: "1.2.3.4", config_flow.CONF_PORT: 80},
|
||||
unique_id=BRIDGEID,
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
gateway = Mock()
|
||||
gateway.config_entry = entry
|
||||
hass.data[config_flow.DOMAIN] = {BRIDGEID: gateway}
|
||||
async def test_ssdp_discovery_update_configuration(hass):
|
||||
"""Test if a discovered bridge is configured but updates with new attributes."""
|
||||
gateway = await setup_deconz_integration(hass)
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
config_flow.DOMAIN,
|
||||
data={
|
||||
ssdp.ATTR_SSDP_LOCATION: "http://mock-deconz/",
|
||||
ssdp.ATTR_SSDP_LOCATION: "http://2.3.4.5:80/",
|
||||
ssdp.ATTR_UPNP_MANUFACTURER_URL: config_flow.DECONZ_MANUFACTURERURL,
|
||||
ssdp.ATTR_UPNP_SERIAL: BRIDGEID,
|
||||
},
|
||||
|
@ -271,96 +383,79 @@ async def test_bridge_discovery_update_existing_entry(hass):
|
|||
|
||||
assert result["type"] == "abort"
|
||||
assert result["reason"] == "updated_instance"
|
||||
assert entry.data[config_flow.CONF_HOST] == "mock-deconz"
|
||||
assert gateway.config_entry.data[config_flow.CONF_HOST] == "2.3.4.5"
|
||||
|
||||
|
||||
async def test_bridge_discovery_dont_update_existing_hassio_entry(hass):
|
||||
"""Test to ensure the SSDP discovery does not update an Hass.io entry."""
|
||||
entry = MockConfigEntry(
|
||||
domain=config_flow.DOMAIN,
|
||||
source="hassio",
|
||||
data={
|
||||
config_flow.CONF_HOST: "core-deconz",
|
||||
config_flow.CONF_BRIDGEID: "123ABC",
|
||||
},
|
||||
unique_id="123ABC",
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
gateway = Mock()
|
||||
gateway.config_entry = entry
|
||||
hass.data[config_flow.DOMAIN] = {"123ABC": gateway}
|
||||
async def test_ssdp_discovery_dont_update_configuration(hass):
|
||||
"""Test if a discovered bridge has already been configured."""
|
||||
gateway = await setup_deconz_integration(hass)
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
config_flow.DOMAIN,
|
||||
data={
|
||||
ssdp.ATTR_SSDP_LOCATION: "http://mock-deconz/",
|
||||
ssdp.ATTR_SSDP_LOCATION: "http://1.2.3.4:80/",
|
||||
ssdp.ATTR_UPNP_MANUFACTURER_URL: config_flow.DECONZ_MANUFACTURERURL,
|
||||
ssdp.ATTR_UPNP_SERIAL: "123ABC",
|
||||
ssdp.ATTR_UPNP_SERIAL: BRIDGEID,
|
||||
},
|
||||
context={"source": "ssdp"},
|
||||
)
|
||||
|
||||
assert result["type"] == "abort"
|
||||
assert result["reason"] == "already_configured"
|
||||
assert entry.data[config_flow.CONF_HOST] == "core-deconz"
|
||||
assert gateway.config_entry.data[config_flow.CONF_HOST] == "1.2.3.4"
|
||||
|
||||
|
||||
async def test_create_entry(hass, aioclient_mock):
|
||||
"""Test that _create_entry work and that bridgeid can be requested."""
|
||||
aioclient_mock.get(
|
||||
"http://1.2.3.4:80/api/1234567890ABCDEF/config",
|
||||
json={"bridgeid": BRIDGEID, "uuid": "456DEF"},
|
||||
headers={"content-type": "application/json"},
|
||||
async def test_ssdp_discovery_dont_update_existing_hassio_configuration(hass):
|
||||
"""Test to ensure the SSDP discovery does not update an Hass.io entry."""
|
||||
gateway = await setup_deconz_integration(hass, source="hassio")
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
config_flow.DOMAIN,
|
||||
data={
|
||||
ssdp.ATTR_SSDP_LOCATION: "http://1.2.3.4:80/",
|
||||
ssdp.ATTR_UPNP_MANUFACTURER_URL: config_flow.DECONZ_MANUFACTURERURL,
|
||||
ssdp.ATTR_UPNP_SERIAL: BRIDGEID,
|
||||
},
|
||||
context={"source": "ssdp"},
|
||||
)
|
||||
|
||||
flow = config_flow.DeconzFlowHandler()
|
||||
flow.context = {}
|
||||
flow.hass = hass
|
||||
flow.deconz_config = {
|
||||
config_flow.CONF_HOST: "1.2.3.4",
|
||||
config_flow.CONF_PORT: 80,
|
||||
config_flow.CONF_API_KEY: "1234567890ABCDEF",
|
||||
}
|
||||
|
||||
result = await flow._create_entry()
|
||||
|
||||
assert result["type"] == "create_entry"
|
||||
assert result["title"] == BRIDGEID
|
||||
assert result["data"] == {
|
||||
config_flow.CONF_HOST: "1.2.3.4",
|
||||
config_flow.CONF_PORT: 80,
|
||||
config_flow.CONF_API_KEY: "1234567890ABCDEF",
|
||||
}
|
||||
|
||||
|
||||
async def test_create_entry_timeout(hass, aioclient_mock):
|
||||
"""Test that _create_entry handles a timeout."""
|
||||
flow = config_flow.DeconzFlowHandler()
|
||||
flow.hass = hass
|
||||
flow.deconz_config = {
|
||||
config_flow.CONF_HOST: "1.2.3.4",
|
||||
config_flow.CONF_PORT: 80,
|
||||
config_flow.CONF_API_KEY: "1234567890ABCDEF",
|
||||
}
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.deconz.config_flow.async_get_bridge_id",
|
||||
side_effect=asyncio.TimeoutError,
|
||||
):
|
||||
result = await flow._create_entry()
|
||||
|
||||
assert result["type"] == "abort"
|
||||
assert result["reason"] == "no_bridges"
|
||||
assert result["reason"] == "already_configured"
|
||||
assert gateway.config_entry.data[config_flow.CONF_HOST] == "1.2.3.4"
|
||||
|
||||
|
||||
async def test_hassio_update_instance(hass):
|
||||
"""Test we can update an existing config entry."""
|
||||
data = deepcopy(DECONZ_WEB_REQUEST)
|
||||
entry_config = deepcopy(ENTRY_CONFIG)
|
||||
gateway = await setup_deconz_integration(
|
||||
hass, entry_config, options={}, get_state_response=data
|
||||
async def test_flow_hassio_discovery(hass):
|
||||
"""Test hassio discovery flow works."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
config_flow.DOMAIN,
|
||||
data={
|
||||
"addon": "Mock Addon",
|
||||
config_flow.CONF_HOST: "mock-deconz",
|
||||
config_flow.CONF_PORT: 80,
|
||||
config_flow.CONF_SERIAL: BRIDGEID,
|
||||
config_flow.CONF_API_KEY: API_KEY,
|
||||
},
|
||||
context={"source": "hassio"},
|
||||
)
|
||||
assert result["type"] == "form"
|
||||
assert result["step_id"] == "hassio_confirm"
|
||||
assert result["description_placeholders"] == {"addon": "Mock Addon"}
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={}
|
||||
)
|
||||
|
||||
assert result["type"] == "create_entry"
|
||||
assert result["result"].data == {
|
||||
config_flow.CONF_HOST: "mock-deconz",
|
||||
config_flow.CONF_PORT: 80,
|
||||
config_flow.CONF_API_KEY: API_KEY,
|
||||
}
|
||||
|
||||
|
||||
async def test_hassio_discovery_update_configuration(hass):
|
||||
"""Test we can update an existing config entry."""
|
||||
gateway = await setup_deconz_integration(hass)
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
config_flow.DOMAIN,
|
||||
|
@ -380,19 +475,16 @@ async def test_hassio_update_instance(hass):
|
|||
assert gateway.config_entry.data[config_flow.CONF_API_KEY] == "updated"
|
||||
|
||||
|
||||
async def test_hassio_dont_update_instance(hass):
|
||||
async def test_hassio_discovery_dont_update_configuration(hass):
|
||||
"""Test we can update an existing config entry."""
|
||||
data = deepcopy(DECONZ_WEB_REQUEST)
|
||||
await setup_deconz_integration(
|
||||
hass, ENTRY_CONFIG, options={}, get_state_response=data
|
||||
)
|
||||
await setup_deconz_integration(hass)
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
config_flow.DOMAIN,
|
||||
data={
|
||||
config_flow.CONF_HOST: "1.2.3.4",
|
||||
config_flow.CONF_PORT: 80,
|
||||
config_flow.CONF_API_KEY: "ABCDEF",
|
||||
config_flow.CONF_API_KEY: API_KEY,
|
||||
config_flow.CONF_SERIAL: BRIDGEID,
|
||||
},
|
||||
context={"source": "hassio"},
|
||||
|
@ -402,35 +494,6 @@ async def test_hassio_dont_update_instance(hass):
|
|||
assert result["reason"] == "already_configured"
|
||||
|
||||
|
||||
async def test_hassio_confirm(hass):
|
||||
"""Test we can finish a config flow."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
config_flow.DOMAIN,
|
||||
data={
|
||||
"addon": "Mock Addon",
|
||||
config_flow.CONF_HOST: "mock-deconz",
|
||||
config_flow.CONF_PORT: 80,
|
||||
config_flow.CONF_SERIAL: BRIDGEID,
|
||||
config_flow.CONF_API_KEY: "1234567890ABCDEF",
|
||||
},
|
||||
context={"source": "hassio"},
|
||||
)
|
||||
assert result["type"] == "form"
|
||||
assert result["step_id"] == "hassio_confirm"
|
||||
assert result["description_placeholders"] == {"addon": "Mock Addon"}
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={}
|
||||
)
|
||||
|
||||
assert result["type"] == "create_entry"
|
||||
assert result["result"].data == {
|
||||
config_flow.CONF_HOST: "mock-deconz",
|
||||
config_flow.CONF_PORT: 80,
|
||||
config_flow.CONF_API_KEY: "1234567890ABCDEF",
|
||||
}
|
||||
|
||||
|
||||
async def test_option_flow(hass):
|
||||
"""Test config flow options."""
|
||||
entry = MockConfigEntry(domain=config_flow.DOMAIN, data={}, options=None)
|
||||
|
|
|
@ -11,10 +11,11 @@ from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
|||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
API_KEY = "1234567890ABCDEF"
|
||||
BRIDGEID = "01234E56789A"
|
||||
|
||||
ENTRY_CONFIG = {
|
||||
deconz.config_flow.CONF_API_KEY: "ABCDEF",
|
||||
deconz.config_flow.CONF_API_KEY: API_KEY,
|
||||
deconz.config_flow.CONF_HOST: "1.2.3.4",
|
||||
deconz.config_flow.CONF_PORT: 80,
|
||||
}
|
||||
|
@ -46,10 +47,12 @@ async def setup_deconz_integration(
|
|||
options=ENTRY_OPTIONS,
|
||||
get_state_response=DECONZ_WEB_REQUEST,
|
||||
entry_id="1",
|
||||
source="user",
|
||||
):
|
||||
"""Create the deCONZ gateway."""
|
||||
config_entry = MockConfigEntry(
|
||||
domain=deconz.DOMAIN,
|
||||
source=source,
|
||||
data=deepcopy(config),
|
||||
connection_class=config_entries.CONN_CLASS_LOCAL_PUSH,
|
||||
options=deepcopy(options),
|
||||
|
|
Loading…
Reference in New Issue