mirror of
https://github.com/home-assistant/core.git
synced 2025-12-25 05:26:47 +00:00
KNX Config/OptionsFlow: minimize wait time for interface discovery (#81982)
* Minimize wait time for interface discovery * fix OptionsFlow when connection failed there is no `self.hass.data["KNX"]` when we are in retry mode after failed integration setup * review changes * fix new tests
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
"""Test the KNX config flow."""
|
||||
from unittest.mock import patch
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
import pytest
|
||||
from xknx.exceptions.exception import InvalidSecureConfiguration
|
||||
@@ -67,6 +67,24 @@ def _gateway_descriptor(
|
||||
return descriptor
|
||||
|
||||
|
||||
class GatewayScannerMock:
|
||||
"""Mock GatewayScanner."""
|
||||
|
||||
def __init__(self, gateways=None):
|
||||
"""Initialize GatewayScannerMock."""
|
||||
# Key is a HPAI instance in xknx, but not used in HA anyway.
|
||||
self.found_gateways = (
|
||||
{f"{gateway.ip_addr}:{gateway.port}": gateway for gateway in gateways}
|
||||
if gateways
|
||||
else {}
|
||||
)
|
||||
|
||||
async def async_scan(self):
|
||||
"""Mock async generator."""
|
||||
for gateway in self.found_gateways:
|
||||
yield gateway
|
||||
|
||||
|
||||
async def test_user_single_instance(hass):
|
||||
"""Test we only allow a single config flow."""
|
||||
MockConfigEntry(domain=DOMAIN).add_to_hass(hass)
|
||||
@@ -78,15 +96,17 @@ async def test_user_single_instance(hass):
|
||||
assert result["reason"] == "single_instance_allowed"
|
||||
|
||||
|
||||
async def test_routing_setup(hass: HomeAssistant) -> None:
|
||||
@patch(
|
||||
"homeassistant.components.knx.config_flow.GatewayScanner",
|
||||
return_value=GatewayScannerMock(),
|
||||
)
|
||||
async def test_routing_setup(gateway_scanner_mock, hass: HomeAssistant) -> None:
|
||||
"""Test routing setup."""
|
||||
with patch("xknx.io.gateway_scanner.GatewayScanner.scan") as gateways:
|
||||
gateways.return_value = []
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
assert result["type"] == FlowResultType.FORM
|
||||
assert not result["errors"]
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
assert result["type"] == FlowResultType.FORM
|
||||
assert not result["errors"]
|
||||
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
@@ -126,19 +146,23 @@ async def test_routing_setup(hass: HomeAssistant) -> None:
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_routing_setup_advanced(hass: HomeAssistant) -> None:
|
||||
@patch(
|
||||
"homeassistant.components.knx.config_flow.GatewayScanner",
|
||||
return_value=GatewayScannerMock(),
|
||||
)
|
||||
async def test_routing_setup_advanced(
|
||||
gateway_scanner_mock, hass: HomeAssistant
|
||||
) -> None:
|
||||
"""Test routing setup with advanced options."""
|
||||
with patch("xknx.io.gateway_scanner.GatewayScanner.scan") as gateways:
|
||||
gateways.return_value = []
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={
|
||||
"source": config_entries.SOURCE_USER,
|
||||
"show_advanced_options": True,
|
||||
},
|
||||
)
|
||||
assert result["type"] == FlowResultType.FORM
|
||||
assert not result["errors"]
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={
|
||||
"source": config_entries.SOURCE_USER,
|
||||
"show_advanced_options": True,
|
||||
},
|
||||
)
|
||||
assert result["type"] == FlowResultType.FORM
|
||||
assert not result["errors"]
|
||||
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
@@ -200,15 +224,19 @@ async def test_routing_setup_advanced(hass: HomeAssistant) -> None:
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_routing_secure_manual_setup(hass: HomeAssistant) -> None:
|
||||
@patch(
|
||||
"homeassistant.components.knx.config_flow.GatewayScanner",
|
||||
return_value=GatewayScannerMock(),
|
||||
)
|
||||
async def test_routing_secure_manual_setup(
|
||||
gateway_scanner_mock, hass: HomeAssistant
|
||||
) -> None:
|
||||
"""Test routing secure setup with manual key config."""
|
||||
with patch("xknx.io.gateway_scanner.GatewayScanner.scan") as gateways:
|
||||
gateways.return_value = []
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
assert result["type"] == FlowResultType.FORM
|
||||
assert not result["errors"]
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
assert result["type"] == FlowResultType.FORM
|
||||
assert not result["errors"]
|
||||
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
@@ -287,15 +315,19 @@ async def test_routing_secure_manual_setup(hass: HomeAssistant) -> None:
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_routing_secure_keyfile(hass: HomeAssistant) -> None:
|
||||
@patch(
|
||||
"homeassistant.components.knx.config_flow.GatewayScanner",
|
||||
return_value=GatewayScannerMock(),
|
||||
)
|
||||
async def test_routing_secure_keyfile(
|
||||
gateway_scanner_mock, hass: HomeAssistant
|
||||
) -> None:
|
||||
"""Test routing secure setup with keyfile."""
|
||||
with patch("xknx.io.gateway_scanner.GatewayScanner.scan") as gateways:
|
||||
gateways.return_value = []
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
assert result["type"] == FlowResultType.FORM
|
||||
assert not result["errors"]
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
assert result["type"] == FlowResultType.FORM
|
||||
assert not result["errors"]
|
||||
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
@@ -412,17 +444,19 @@ async def test_routing_secure_keyfile(hass: HomeAssistant) -> None:
|
||||
),
|
||||
],
|
||||
)
|
||||
@patch(
|
||||
"homeassistant.components.knx.config_flow.GatewayScanner",
|
||||
return_value=GatewayScannerMock(),
|
||||
)
|
||||
async def test_tunneling_setup_manual(
|
||||
hass: HomeAssistant, user_input, config_entry_data
|
||||
gateway_scanner_mock, hass: HomeAssistant, user_input, config_entry_data
|
||||
) -> None:
|
||||
"""Test tunneling if no gateway was found found (or `manual` option was chosen)."""
|
||||
with patch("xknx.io.gateway_scanner.GatewayScanner.scan") as gateways:
|
||||
gateways.return_value = []
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
assert result["type"] == FlowResultType.FORM
|
||||
assert not result["errors"]
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
assert result["type"] == FlowResultType.FORM
|
||||
assert not result["errors"]
|
||||
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
@@ -451,19 +485,23 @@ async def test_tunneling_setup_manual(
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_tunneling_setup_for_local_ip(hass: HomeAssistant) -> None:
|
||||
@patch(
|
||||
"homeassistant.components.knx.config_flow.GatewayScanner",
|
||||
return_value=GatewayScannerMock(),
|
||||
)
|
||||
async def test_tunneling_setup_for_local_ip(
|
||||
gateway_scanner_mock, hass: HomeAssistant
|
||||
) -> None:
|
||||
"""Test tunneling if only one gateway is found."""
|
||||
with patch("xknx.io.gateway_scanner.GatewayScanner.scan") as gateways:
|
||||
gateways.return_value = []
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={
|
||||
"source": config_entries.SOURCE_USER,
|
||||
"show_advanced_options": True,
|
||||
},
|
||||
)
|
||||
assert result["type"] == FlowResultType.FORM
|
||||
assert not result["errors"]
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={
|
||||
"source": config_entries.SOURCE_USER,
|
||||
"show_advanced_options": True,
|
||||
},
|
||||
)
|
||||
assert result["type"] == FlowResultType.FORM
|
||||
assert not result["errors"]
|
||||
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
@@ -542,11 +580,13 @@ async def test_tunneling_setup_for_local_ip(hass: HomeAssistant) -> None:
|
||||
|
||||
|
||||
async def test_tunneling_setup_for_multiple_found_gateways(hass: HomeAssistant) -> None:
|
||||
"""Test tunneling if only one gateway is found."""
|
||||
"""Test tunneling if multiple gateways are found."""
|
||||
gateway = _gateway_descriptor("192.168.0.1", 3675)
|
||||
gateway2 = _gateway_descriptor("192.168.1.100", 3675)
|
||||
with patch("xknx.io.gateway_scanner.GatewayScanner.scan") as gateways:
|
||||
gateways.return_value = [gateway, gateway2]
|
||||
with patch(
|
||||
"homeassistant.components.knx.config_flow.GatewayScanner"
|
||||
) as gateway_scanner_mock:
|
||||
gateway_scanner_mock.return_value = GatewayScannerMock([gateway, gateway2])
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
@@ -601,8 +641,10 @@ async def test_manual_tunnel_step_with_found_gateway(
|
||||
hass: HomeAssistant, gateway
|
||||
) -> None:
|
||||
"""Test manual tunnel if gateway was found and tunneling is selected."""
|
||||
with patch("xknx.io.gateway_scanner.GatewayScanner.scan") as gateways:
|
||||
gateways.return_value = [gateway]
|
||||
with patch(
|
||||
"homeassistant.components.knx.config_flow.GatewayScanner"
|
||||
) as gateway_scanner_mock:
|
||||
gateway_scanner_mock.return_value = GatewayScannerMock([gateway])
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
@@ -634,8 +676,12 @@ async def test_manual_tunnel_step_with_found_gateway(
|
||||
|
||||
async def test_form_with_automatic_connection_handling(hass: HomeAssistant) -> None:
|
||||
"""Test we get the form."""
|
||||
with patch("xknx.io.gateway_scanner.GatewayScanner.scan") as gateways:
|
||||
gateways.return_value = [_gateway_descriptor("192.168.0.1", 3675)]
|
||||
with patch(
|
||||
"homeassistant.components.knx.config_flow.GatewayScanner"
|
||||
) as gateway_scanner_mock:
|
||||
gateway_scanner_mock.return_value = GatewayScannerMock(
|
||||
[_gateway_descriptor("192.168.0.1", 3675)]
|
||||
)
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
@@ -672,8 +718,10 @@ async def _get_menu_step(hass: HomeAssistant) -> FlowResult:
|
||||
supports_tunnelling_tcp=True,
|
||||
requires_secure=True,
|
||||
)
|
||||
with patch("xknx.io.gateway_scanner.GatewayScanner.scan") as gateways:
|
||||
gateways.return_value = [gateway]
|
||||
with patch(
|
||||
"homeassistant.components.knx.config_flow.GatewayScanner"
|
||||
) as gateway_scanner_mock:
|
||||
gateway_scanner_mock.return_value = GatewayScannerMock([gateway])
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
@@ -711,8 +759,10 @@ async def test_get_secure_menu_step_manual_tunnelling(
|
||||
supports_tunnelling_tcp=True,
|
||||
requires_secure=True,
|
||||
)
|
||||
with patch("xknx.io.gateway_scanner.GatewayScanner.scan") as gateways:
|
||||
gateways.return_value = [gateway]
|
||||
with patch(
|
||||
"homeassistant.components.knx.config_flow.GatewayScanner"
|
||||
) as gateway_scanner_mock:
|
||||
gateway_scanner_mock.return_value = GatewayScannerMock([gateway])
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
@@ -899,12 +949,15 @@ async def test_options_flow_connection_type(
|
||||
) -> None:
|
||||
"""Test options flow changing interface."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
hass.data[DOMAIN] = Mock() # GatewayScanner uses running XKNX() instance
|
||||
gateway = _gateway_descriptor("192.168.0.1", 3675)
|
||||
|
||||
menu_step = await hass.config_entries.options.async_init(mock_config_entry.entry_id)
|
||||
|
||||
with patch("xknx.io.gateway_scanner.GatewayScanner.scan") as gateways:
|
||||
gateways.return_value = [gateway]
|
||||
with patch(
|
||||
"homeassistant.components.knx.config_flow.GatewayScanner"
|
||||
) as gateway_scanner_mock:
|
||||
gateway_scanner_mock.return_value = GatewayScannerMock([gateway])
|
||||
result = await hass.config_entries.options.async_configure(
|
||||
menu_step["flow_id"],
|
||||
{"next_step_id": "connection_type"},
|
||||
|
||||
Reference in New Issue
Block a user