Prevent duplicate WMS WebControl pro config entry creation (#128315)

This commit is contained in:
Marc Hörsken 2024-10-25 11:02:13 +02:00 committed by GitHub
parent 8665f4a251
commit 0acb95bbd5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 84 additions and 6 deletions

View File

@ -84,6 +84,15 @@ class WebControlProConfigFlow(ConfigFlow, domain=DOMAIN):
if not pong: if not pong:
errors["base"] = "cannot_connect" errors["base"] = "cannot_connect"
else: else:
await hub.refresh()
rooms = set(hub.rooms.keys())
for entry in self.hass.config_entries.async_loaded_entries(DOMAIN):
if (
entry.runtime_data
and entry.runtime_data.rooms
and set(entry.runtime_data.rooms.keys()) == rooms
):
return self.async_abort(reason="already_configured")
return self.async_create_entry(title=host, data=user_input) return self.async_create_entry(title=host, data=user_input)
if self.source == dhcp.DOMAIN: if self.source == dhcp.DOMAIN:

View File

@ -6,13 +6,19 @@ import aiohttp
from homeassistant.components.dhcp import DhcpServiceInfo from homeassistant.components.dhcp import DhcpServiceInfo
from homeassistant.components.wmspro.const import DOMAIN from homeassistant.components.wmspro.const import DOMAIN
from homeassistant.config_entries import SOURCE_DHCP, SOURCE_USER from homeassistant.config_entries import SOURCE_DHCP, SOURCE_USER, ConfigEntryState
from homeassistant.const import CONF_HOST from homeassistant.const import CONF_HOST
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType from homeassistant.data_entry_flow import FlowResultType
from . import setup_config_entry
async def test_config_flow(hass: HomeAssistant, mock_setup_entry: AsyncMock) -> None: from tests.common import MockConfigEntry
async def test_config_flow(
hass: HomeAssistant, mock_setup_entry: AsyncMock, mock_hub_refresh: AsyncMock
) -> None:
"""Test we can handle user-input to create a config entry.""" """Test we can handle user-input to create a config entry."""
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER} DOMAIN, context={"source": SOURCE_USER}
@ -40,7 +46,7 @@ async def test_config_flow(hass: HomeAssistant, mock_setup_entry: AsyncMock) ->
async def test_config_flow_from_dhcp( async def test_config_flow_from_dhcp(
hass: HomeAssistant, mock_setup_entry: AsyncMock hass: HomeAssistant, mock_setup_entry: AsyncMock, mock_hub_refresh: AsyncMock
) -> None: ) -> None:
"""Test we can handle DHCP discovery to create a config entry.""" """Test we can handle DHCP discovery to create a config entry."""
info = DhcpServiceInfo( info = DhcpServiceInfo(
@ -74,6 +80,7 @@ async def test_config_flow_from_dhcp(
async def test_config_flow_from_dhcp_add_mac( async def test_config_flow_from_dhcp_add_mac(
hass: HomeAssistant, hass: HomeAssistant,
mock_setup_entry: AsyncMock, mock_setup_entry: AsyncMock,
mock_hub_refresh: AsyncMock,
) -> None: ) -> None:
"""Test we can use DHCP discovery to add MAC address to a config entry.""" """Test we can use DHCP discovery to add MAC address to a config entry."""
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
@ -115,6 +122,7 @@ async def test_config_flow_from_dhcp_add_mac(
async def test_config_flow_from_dhcp_ip_update( async def test_config_flow_from_dhcp_ip_update(
hass: HomeAssistant, hass: HomeAssistant,
mock_setup_entry: AsyncMock, mock_setup_entry: AsyncMock,
mock_hub_refresh: AsyncMock,
) -> None: ) -> None:
"""Test we can use DHCP discovery to update IP in a config entry.""" """Test we can use DHCP discovery to update IP in a config entry."""
info = DhcpServiceInfo( info = DhcpServiceInfo(
@ -160,6 +168,7 @@ async def test_config_flow_from_dhcp_ip_update(
async def test_config_flow_from_dhcp_no_update( async def test_config_flow_from_dhcp_no_update(
hass: HomeAssistant, hass: HomeAssistant,
mock_setup_entry: AsyncMock, mock_setup_entry: AsyncMock,
mock_hub_refresh: AsyncMock,
) -> None: ) -> None:
"""Test we do not use DHCP discovery to overwrite hostname with IP in config entry.""" """Test we do not use DHCP discovery to overwrite hostname with IP in config entry."""
info = DhcpServiceInfo( info = DhcpServiceInfo(
@ -203,7 +212,7 @@ async def test_config_flow_from_dhcp_no_update(
async def test_config_flow_ping_failed( async def test_config_flow_ping_failed(
hass: HomeAssistant, mock_setup_entry: AsyncMock hass: HomeAssistant, mock_setup_entry: AsyncMock, mock_hub_refresh: AsyncMock
) -> None: ) -> None:
"""Test we handle ping failed error.""" """Test we handle ping failed error."""
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
@ -244,7 +253,7 @@ async def test_config_flow_ping_failed(
async def test_config_flow_cannot_connect( async def test_config_flow_cannot_connect(
hass: HomeAssistant, mock_setup_entry: AsyncMock hass: HomeAssistant, mock_setup_entry: AsyncMock, mock_hub_refresh: AsyncMock
) -> None: ) -> None:
"""Test we handle cannot connect error.""" """Test we handle cannot connect error."""
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
@ -285,7 +294,7 @@ async def test_config_flow_cannot_connect(
async def test_config_flow_unknown_error( async def test_config_flow_unknown_error(
hass: HomeAssistant, mock_setup_entry: AsyncMock hass: HomeAssistant, mock_setup_entry: AsyncMock, mock_hub_refresh: AsyncMock
) -> None: ) -> None:
"""Test we handle an unknown error.""" """Test we handle an unknown error."""
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
@ -323,3 +332,63 @@ async def test_config_flow_unknown_error(
CONF_HOST: "1.2.3.4", CONF_HOST: "1.2.3.4",
} }
assert len(mock_setup_entry.mock_calls) == 1 assert len(mock_setup_entry.mock_calls) == 1
async def test_config_flow_duplicate_entries(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_hub_ping: AsyncMock,
mock_dest_refresh: AsyncMock,
mock_hub_configuration_test: AsyncMock,
) -> None:
"""Test we prevent creation of duplicate config entries."""
await setup_config_entry(hass, mock_config_entry)
assert mock_config_entry.state is ConfigEntryState.LOADED
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{
CONF_HOST: "5.6.7.8",
},
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
assert len(hass.config_entries.async_entries(DOMAIN)) == 1
async def test_config_flow_multiple_entries(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_hub_ping: AsyncMock,
mock_dest_refresh: AsyncMock,
mock_hub_configuration_test: AsyncMock,
mock_hub_configuration_prod: AsyncMock,
) -> None:
"""Test we allow creation of different config entries."""
await setup_config_entry(hass, mock_config_entry)
assert mock_config_entry.state is ConfigEntryState.LOADED
mock_hub_configuration_prod.return_value = mock_hub_configuration_test.return_value
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{
CONF_HOST: "5.6.7.8",
},
)
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == "5.6.7.8"
assert result["data"] == {
CONF_HOST: "5.6.7.8",
}
assert len(hass.config_entries.async_entries(DOMAIN)) == 2