Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 20 additions & 6 deletions homeassistant/components/keenetic_ndms2/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,17 +146,27 @@ async def async_step_init(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Manage the options."""
if (
not hasattr(self.config_entry, "runtime_data")
or not self.config_entry.runtime_data
):
return self.async_abort(reason="not_initialized")

router = self.config_entry.runtime_data

interfaces: list[InterfaceInfo] = await self.hass.async_add_executor_job(
router.client.get_interfaces
)
try:
interfaces: list[InterfaceInfo] = await self.hass.async_add_executor_job(
router.client.get_interfaces
)
except ConnectionException:
return self.async_abort(reason="cannot_connect")

self._interface_options = {
interface.name: (interface.description or interface.name)
for interface in interfaces
if interface.type.lower() == "bridge"
}

return await self.async_step_user()

async def async_step_user(
Expand All @@ -182,9 +192,13 @@ async def async_step_user(
): int,
vol.Required(
CONF_INTERFACES,
default=self.config_entry.options.get(
CONF_INTERFACES, [DEFAULT_INTERFACE]
),
default=[
item
for item in self.config_entry.options.get(
CONF_INTERFACES, [DEFAULT_INTERFACE]
)
if item in self._interface_options
],
): cv.multi_select(self._interface_options),
vol.Optional(
CONF_TRY_HOTSPOT,
Expand Down
4 changes: 4 additions & 0 deletions homeassistant/components/keenetic_ndms2/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@
"include_associated": "Use Wi-Fi AP associations data (ignored if hotspot data used)"
}
}
},
"abort": {
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
"not_initialized": "The integration is not initialized yet. Can't display available options."
}
}
}
67 changes: 66 additions & 1 deletion tests/components/keenetic_ndms2/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@
from ndms2_client import ConnectionException
from ndms2_client.client import InterfaceInfo, RouterInfo
import pytest
import voluptuous as vol

from homeassistant import config_entries
from homeassistant.components import keenetic_ndms2 as keenetic
from homeassistant.components.keenetic_ndms2 import const
from homeassistant.components.keenetic_ndms2 import CONF_INTERFACES, const
from homeassistant.const import CONF_HOST, CONF_SOURCE
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType
Expand Down Expand Up @@ -145,6 +146,70 @@ async def test_connection_error(hass: HomeAssistant, connect_error) -> None:
assert result["errors"] == {"base": "cannot_connect"}


async def test_options_not_initialized(hass: HomeAssistant) -> None:
"""Test the error when the integration is not initialized."""

entry = MockConfigEntry(domain=keenetic.DOMAIN, data=MOCK_DATA)
entry.add_to_hass(hass)

# not setting entry.runtime_data

result = await hass.config_entries.options.async_init(entry.entry_id)

assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "not_initialized"


async def test_options_connection_error(hass: HomeAssistant) -> None:
"""Test updating options."""

entry = MockConfigEntry(domain=keenetic.DOMAIN, data=MOCK_DATA)
entry.add_to_hass(hass)

def get_interfaces_error():
raise ConnectionException("Mocked failure")

# fake with connection error
entry.runtime_data = Mock(
client=Mock(get_interfaces=Mock(wraps=get_interfaces_error))
)

result = await hass.config_entries.options.async_init(entry.entry_id)

assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "cannot_connect"


async def test_options_interface_filter(hass: HomeAssistant) -> None:
"""Test the case when the default Home interface is missing on the router."""

entry = MockConfigEntry(domain=keenetic.DOMAIN, data=MOCK_DATA)
entry.add_to_hass(hass)

# fake interfaces
entry.runtime_data = Mock(
client=Mock(
get_interfaces=Mock(
return_value=[
InterfaceInfo.from_dict({"id": name, "type": "bridge"})
for name in ("not_a_home", "also_not_home")
]
)
)
)

result = await hass.config_entries.options.async_init(entry.entry_id)

assert result["type"] is FlowResultType.FORM
interfaces_schema = next(
i
for i, s in result["data_schema"].schema.items()
if i.schema == CONF_INTERFACES
)
assert isinstance(interfaces_schema, vol.Required)
assert interfaces_schema.default() == []


async def test_ssdp_works(hass: HomeAssistant, connect) -> None:
"""Test host already configured and discovered."""

Expand Down