Test the connection in the Radio Browser config flow (#184069)

This commit is contained in:
Franck Nijhof
2026-10-02 19:33:44 +01:00
committed by GitHub
parent bdf6fa2d7a
commit 7060db318f
4 changed files with 62 additions and 4 deletions
@@ -2,7 +2,11 @@
from typing import Any, override
from radios import RadioBrowser, RadioBrowserError
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
from homeassistant.const import __version__
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from .const import DOMAIN
@@ -17,10 +21,20 @@ class RadioBrowserConfigFlow(ConfigFlow, domain=DOMAIN):
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Handle the initial step."""
errors: dict[str, str] = {}
if user_input is not None:
return self.async_create_entry(title="Radio Browser", data={})
radios = RadioBrowser(
session=async_get_clientsession(self.hass),
user_agent=f"HomeAssistant/{__version__}",
)
try:
await radios.stats()
except RadioBrowserError:
errors["base"] = "cannot_connect"
else:
return self.async_create_entry(title="Radio Browser", data={})
return self.async_show_form(step_id="user")
return self.async_show_form(step_id="user", errors=errors)
async def async_step_onboarding(
self, data: dict[str, Any] | None = None
@@ -1,5 +1,8 @@
{
"config": {
"error": {
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]"
},
"step": {
"user": {
"description": "Do you want to add Radio Browser to Home Assistant?"
@@ -31,6 +31,16 @@ def mock_setup_entry() -> Generator[AsyncMock]:
yield mock_setup
@pytest.fixture
def mock_radio_browser() -> Generator[MagicMock]:
"""Mock the Radio Browser client in the config flow."""
with patch(
"homeassistant.components.radio_browser.config_flow.RadioBrowser",
autospec=True,
) as radio_browser_mock:
yield radio_browser_mock.return_value
@pytest.fixture
async def init_integration(
hass: HomeAssistant,
@@ -1,8 +1,9 @@
"""Test the Radio Browser config flow."""
from unittest.mock import AsyncMock
from unittest.mock import AsyncMock, MagicMock
import pytest
from radios import RadioBrowserConnectionError
from homeassistant.components.radio_browser.const import DOMAIN
from homeassistant.config_entries import SOURCE_USER
@@ -12,13 +13,14 @@ from homeassistant.data_entry_flow import FlowResultType
from tests.common import MockConfigEntry
@pytest.mark.usefixtures("mock_radio_browser")
async def test_full_user_flow(hass: HomeAssistant, mock_setup_entry: AsyncMock) -> None:
"""Test the full user configuration flow."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
assert result.get("type") is FlowResultType.FORM
assert result.get("errors") is None
assert result.get("errors") == {}
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
@@ -32,6 +34,35 @@ async def test_full_user_flow(hass: HomeAssistant, mock_setup_entry: AsyncMock)
assert len(mock_setup_entry.mock_calls) == 1
async def test_user_flow_cannot_connect(
hass: HomeAssistant,
mock_radio_browser: MagicMock,
mock_setup_entry: AsyncMock,
) -> None:
"""Test the user flow when Radio Browser cannot be reached, and recovers."""
mock_radio_browser.stats.side_effect = RadioBrowserConnectionError
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={},
)
assert result.get("type") is FlowResultType.FORM
assert result.get("errors") == {"base": "cannot_connect"}
mock_radio_browser.stats.side_effect = None
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={},
)
assert result.get("type") is FlowResultType.CREATE_ENTRY
assert len(mock_setup_entry.mock_calls) == 1
@pytest.mark.usefixtures("mock_setup_entry")
async def test_already_configured(
hass: HomeAssistant, mock_config_entry: MockConfigEntry