Add unique ID to WLED config entries (#30480)

* Add unique ID to WLED config entries

* Improve robustness of the tests
This commit is contained in:
Franck Nijhof 2020-01-04 22:48:31 +01:00 committed by Paulus Schoutsen
parent bf9418e51a
commit 51db9bdfce
4 changed files with 56 additions and 40 deletions

View File

@ -61,6 +61,12 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
hass.data.setdefault(DOMAIN, {}) hass.data.setdefault(DOMAIN, {})
hass.data[DOMAIN][entry.entry_id] = {DATA_WLED_CLIENT: wled} hass.data[DOMAIN][entry.entry_id] = {DATA_WLED_CLIENT: wled}
# For backwards compat, set unique ID
if entry.unique_id is None:
hass.config_entries.async_update_entry(
entry, unique_id=wled.device.info.mac_address
)
# Set up all platforms for this device/entry. # Set up all platforms for this device/entry.
for component in WLED_COMPONENTS: for component in WLED_COMPONENTS:
hass.async_create_task( hass.async_create_task(

View File

@ -87,10 +87,8 @@ class WLEDFlowHandler(ConfigFlow, domain=DOMAIN):
# Check if already configured # Check if already configured
mac_address = device.info.mac_address mac_address = device.info.mac_address
for entry in self._async_current_entries(): await self.async_set_unique_id(device.info.mac_address)
if entry.data[CONF_MAC] == mac_address: self._abort_if_unique_id_configured()
# This mac address is already configured
return self.async_abort(reason="already_configured")
title = user_input[CONF_HOST] title = user_input[CONF_HOST]
if source == SOURCE_ZEROCONF: if source == SOURCE_ZEROCONF:

View File

@ -15,10 +15,9 @@ from tests.test_util.aiohttp import AiohttpClientMocker
async def test_show_user_form(hass: HomeAssistant) -> None: async def test_show_user_form(hass: HomeAssistant) -> None:
"""Test that the user set up form is served.""" """Test that the user set up form is served."""
flow = config_flow.WLEDFlowHandler() result = await hass.config_entries.flow.async_init(
flow.hass = hass config_flow.DOMAIN, context={"source": SOURCE_USER},
flow.context = {"source": SOURCE_USER} )
result = await flow.async_step_user(user_input=None)
assert result["step_id"] == "user" assert result["step_id"] == "user"
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
@ -64,10 +63,11 @@ async def test_connection_error(
"""Test we show user form on WLED connection error.""" """Test we show user form on WLED connection error."""
aioclient_mock.get("http://example.com/json/", exc=aiohttp.ClientError) aioclient_mock.get("http://example.com/json/", exc=aiohttp.ClientError)
flow = config_flow.WLEDFlowHandler() result = await hass.config_entries.flow.async_init(
flow.hass = hass config_flow.DOMAIN,
flow.context = {"source": SOURCE_USER} context={"source": SOURCE_USER},
result = await flow.async_step_user(user_input={CONF_HOST: "example.com"}) data={CONF_HOST: "example.com"},
)
assert result["errors"] == {"base": "connection_error"} assert result["errors"] == {"base": "connection_error"}
assert result["step_id"] == "user" assert result["step_id"] == "user"
@ -80,10 +80,11 @@ async def test_zeroconf_connection_error(
"""Test we abort zeroconf flow on WLED connection error.""" """Test we abort zeroconf flow on WLED connection error."""
aioclient_mock.get("http://example.local/json/", exc=aiohttp.ClientError) aioclient_mock.get("http://example.local/json/", exc=aiohttp.ClientError)
flow = config_flow.WLEDFlowHandler() result = await hass.config_entries.flow.async_init(
flow.hass = hass config_flow.DOMAIN,
flow.context = {"source": SOURCE_ZEROCONF} context={"source": SOURCE_ZEROCONF},
result = await flow.async_step_zeroconf(user_input={"hostname": "example.local."}) data={"hostname": "example.local."},
)
assert result["reason"] == "connection_error" assert result["reason"] == "connection_error"
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
@ -95,15 +96,14 @@ async def test_zeroconf_confirm_connection_error(
"""Test we abort zeroconf flow on WLED connection error.""" """Test we abort zeroconf flow on WLED connection error."""
aioclient_mock.get("http://example.com/json/", exc=aiohttp.ClientError) aioclient_mock.get("http://example.com/json/", exc=aiohttp.ClientError)
flow = config_flow.WLEDFlowHandler() result = await hass.config_entries.flow.async_init(
flow.hass = hass config_flow.DOMAIN,
flow.context = { context={
"source": SOURCE_ZEROCONF, "source": SOURCE_ZEROCONF,
CONF_HOST: "example.com", CONF_HOST: "example.com",
CONF_NAME: "test", CONF_NAME: "test",
} },
result = await flow.async_step_zeroconf_confirm( data={"hostname": "example.com."},
user_input={CONF_HOST: "example.com"}
) )
assert result["reason"] == "connection_error" assert result["reason"] == "connection_error"
@ -128,13 +128,14 @@ async def test_user_device_exists_abort(
"""Test we abort zeroconf flow if WLED device already configured.""" """Test we abort zeroconf flow if WLED device already configured."""
await init_integration(hass, aioclient_mock) await init_integration(hass, aioclient_mock)
flow = config_flow.WLEDFlowHandler() result = await hass.config_entries.flow.async_init(
flow.hass = hass config_flow.DOMAIN,
flow.context = {"source": SOURCE_USER} context={"source": SOURCE_USER},
result = await flow.async_step_user({CONF_HOST: "example.local"}) data={CONF_HOST: "example.local"},
)
assert result["reason"] == "already_configured"
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
assert result["reason"] == "already_configured"
async def test_zeroconf_device_exists_abort( async def test_zeroconf_device_exists_abort(
@ -143,13 +144,14 @@ async def test_zeroconf_device_exists_abort(
"""Test we abort zeroconf flow if WLED device already configured.""" """Test we abort zeroconf flow if WLED device already configured."""
await init_integration(hass, aioclient_mock) await init_integration(hass, aioclient_mock)
flow = config_flow.WLEDFlowHandler() result = await hass.config_entries.flow.async_init(
flow.hass = hass config_flow.DOMAIN,
flow.context = {"source": SOURCE_ZEROCONF} context={"source": SOURCE_ZEROCONF},
result = await flow.async_step_zeroconf({"hostname": "example.local."}) data={"hostname": "example.local."},
)
assert result["reason"] == "already_configured"
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
assert result["reason"] == "already_configured"
async def test_full_user_flow_implementation( async def test_full_user_flow_implementation(
@ -162,15 +164,17 @@ async def test_full_user_flow_implementation(
headers={"Content-Type": "application/json"}, headers={"Content-Type": "application/json"},
) )
flow = config_flow.WLEDFlowHandler() result = await hass.config_entries.flow.async_init(
flow.hass = hass config_flow.DOMAIN, context={"source": SOURCE_USER},
flow.context = {"source": SOURCE_USER} )
result = await flow.async_step_user(user_input=None)
assert result["step_id"] == "user" assert result["step_id"] == "user"
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
result = await flow.async_step_user(user_input={CONF_HOST: "example.local"}) result = await hass.config_entries.flow.async_configure(
result["flow_id"], user_input={CONF_HOST: "example.local"}
)
assert result["data"][CONF_HOST] == "example.local" assert result["data"][CONF_HOST] == "example.local"
assert result["data"][CONF_MAC] == "aabbccddeeff" assert result["data"][CONF_MAC] == "aabbccddeeff"
assert result["title"] == "example.local" assert result["title"] == "example.local"

View File

@ -33,6 +33,14 @@ async def test_unload_config_entry(
assert not hass.data.get(DOMAIN) assert not hass.data.get(DOMAIN)
async def test_setting_unique_id(hass, aioclient_mock):
"""Test we set unique ID if not set yet."""
entry = await init_integration(hass, aioclient_mock)
assert hass.data[DOMAIN]
assert entry.unique_id == "aabbccddeeff"
async def test_interval_update( async def test_interval_update(
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
) -> None: ) -> None: