mirror of
https://github.com/home-assistant/core.git
synced 2026-08-24 23:24:11 +01:00
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
201 lines
6.6 KiB
Python
201 lines
6.6 KiB
Python
"""Tests for the solax config flow."""
|
|
|
|
import asyncio
|
|
from unittest.mock import patch
|
|
|
|
import pytest
|
|
from solax.inverter import Inverter, InverterError, InverterResponse
|
|
from solax.inverters import X1Boost, X1MiniV34
|
|
|
|
from homeassistant import config_entries
|
|
from homeassistant.components.solax.const import DOMAIN
|
|
from homeassistant.const import CONF_IP_ADDRESS, CONF_MODEL, CONF_PASSWORD, CONF_PORT
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.data_entry_flow import FlowResultType
|
|
|
|
CONNECTION_INPUT: dict[str, str | int] = {
|
|
CONF_IP_ADDRESS: "192.168.1.87",
|
|
CONF_PORT: 80,
|
|
CONF_PASSWORD: "password",
|
|
}
|
|
|
|
|
|
def _build_inverter(inverter_cls: type[Inverter]) -> Inverter:
|
|
"""Build a real inverter instance to use as a discover() return value."""
|
|
return next(
|
|
iter(
|
|
inverter_cls.build_all_variants(
|
|
CONNECTION_INPUT[CONF_IP_ADDRESS],
|
|
CONNECTION_INPUT[CONF_PORT],
|
|
CONNECTION_INPUT[CONF_PASSWORD],
|
|
)
|
|
)
|
|
)
|
|
|
|
|
|
def __mock_get_data() -> InverterResponse:
|
|
return InverterResponse(
|
|
data=None,
|
|
dongle_serial_number="ABCDEFGHIJ",
|
|
version="2.034.06",
|
|
type=4,
|
|
inverter_serial_number="XXXXXXX",
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("discovered_inverter_classes", "steps", "expected_model"),
|
|
[
|
|
pytest.param({X1MiniV34}, [CONNECTION_INPUT], "x1_mini_v34", id="single_match"),
|
|
pytest.param(
|
|
{X1MiniV34, X1Boost},
|
|
[CONNECTION_INPUT, {CONF_MODEL: "x1_mini_v34"}],
|
|
"x1_mini_v34",
|
|
id="multiple_matches",
|
|
),
|
|
],
|
|
)
|
|
async def test_form_success(
|
|
hass: HomeAssistant,
|
|
discovered_inverter_classes: set[type[Inverter]],
|
|
steps: list[dict[str, str | int]],
|
|
expected_model: str,
|
|
) -> None:
|
|
"""Test successful discovery and entry creation, with/without a model choice."""
|
|
flow = await hass.config_entries.flow.async_init(
|
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
|
)
|
|
assert flow["type"] is FlowResultType.FORM
|
|
assert flow["errors"] is None
|
|
|
|
discovered = {_build_inverter(cls) for cls in discovered_inverter_classes}
|
|
|
|
with (
|
|
patch(
|
|
"homeassistant.components.solax.config_flow.discover",
|
|
return_value=discovered,
|
|
) as mock_discover,
|
|
patch("solax.RealTimeAPI.get_data", return_value=__mock_get_data()),
|
|
patch(
|
|
"homeassistant.components.solax.async_setup_entry",
|
|
return_value=True,
|
|
) as mock_setup_entry,
|
|
):
|
|
result = flow
|
|
for step_input in steps:
|
|
result = await hass.config_entries.flow.async_configure(
|
|
result["flow_id"], step_input
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert result["type"] is FlowResultType.CREATE_ENTRY
|
|
assert result["title"] == "ABCDEFGHIJ"
|
|
assert result["data"] == {**CONNECTION_INPUT, CONF_MODEL: expected_model}
|
|
assert len(mock_setup_entry.mock_calls) == 1
|
|
assert mock_discover.call_count == 1
|
|
assert mock_discover.call_args.kwargs == {"return_when": asyncio.ALL_COMPLETED}
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("side_effect", "expected_error"),
|
|
[
|
|
pytest.param(ConnectionError, "cannot_connect", id="cannot_connect"),
|
|
pytest.param(Exception, "unknown", id="unknown"),
|
|
],
|
|
)
|
|
async def test_form_discover_error(
|
|
hass: HomeAssistant, side_effect: type[Exception], expected_error: str
|
|
) -> None:
|
|
"""Test discovery failures redisplay the user step with an error."""
|
|
flow = await hass.config_entries.flow.async_init(
|
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
|
)
|
|
assert flow["type"] is FlowResultType.FORM
|
|
assert flow["errors"] is None
|
|
|
|
with patch(
|
|
"homeassistant.components.solax.config_flow.discover", side_effect=side_effect
|
|
):
|
|
result = await hass.config_entries.flow.async_configure(
|
|
flow["flow_id"], CONNECTION_INPUT
|
|
)
|
|
|
|
assert result["type"] is FlowResultType.FORM
|
|
assert result["step_id"] == "user"
|
|
assert result["errors"] == {"base": expected_error}
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("side_effect", "expected_error"),
|
|
[
|
|
pytest.param(ConnectionError, "cannot_connect", id="cannot_connect"),
|
|
pytest.param(InverterError, "cannot_connect", id="inverter_error"),
|
|
pytest.param(Exception, "unknown", id="unknown"),
|
|
],
|
|
)
|
|
@pytest.mark.parametrize(
|
|
("discovered_inverter_classes", "steps", "expected_step_id"),
|
|
[
|
|
pytest.param({X1MiniV34}, [CONNECTION_INPUT], "user", id="single_match"),
|
|
pytest.param(
|
|
{X1MiniV34, X1Boost},
|
|
[CONNECTION_INPUT, {CONF_MODEL: "x1_mini_v34"}],
|
|
"select_model",
|
|
id="multiple_matches",
|
|
),
|
|
],
|
|
)
|
|
async def test_form_finalize_error(
|
|
hass: HomeAssistant,
|
|
discovered_inverter_classes: set[type[Inverter]],
|
|
steps: list[dict[str, str | int]],
|
|
expected_step_id: str,
|
|
side_effect: type[Exception],
|
|
expected_error: str,
|
|
) -> None:
|
|
"""Test serial-number fetch failures redisplay the current step with an error."""
|
|
flow = await hass.config_entries.flow.async_init(
|
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
|
)
|
|
discovered = {_build_inverter(cls) for cls in discovered_inverter_classes}
|
|
|
|
with (
|
|
patch(
|
|
"homeassistant.components.solax.config_flow.discover",
|
|
return_value=discovered,
|
|
),
|
|
patch("solax.RealTimeAPI.get_data", side_effect=side_effect),
|
|
):
|
|
result = flow
|
|
for step_input in steps:
|
|
result = await hass.config_entries.flow.async_configure(
|
|
result["flow_id"], step_input
|
|
)
|
|
|
|
assert result["type"] is FlowResultType.FORM
|
|
assert result["step_id"] == expected_step_id
|
|
assert result["errors"] == {"base": expected_error}
|
|
|
|
|
|
async def test_form_select_model_step_options(hass: HomeAssistant) -> None:
|
|
"""Test the select_model step only lists the discovered inverter models."""
|
|
flow = await hass.config_entries.flow.async_init(
|
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
|
)
|
|
discovered = {_build_inverter(X1MiniV34), _build_inverter(X1Boost)}
|
|
|
|
with patch(
|
|
"homeassistant.components.solax.config_flow.discover",
|
|
return_value=discovered,
|
|
):
|
|
result = await hass.config_entries.flow.async_configure(
|
|
flow["flow_id"], CONNECTION_INPUT
|
|
)
|
|
|
|
assert result["type"] is FlowResultType.FORM
|
|
assert result["step_id"] == "select_model"
|
|
assert result["data_schema"].schema[CONF_MODEL].config["options"] == [
|
|
"x1_boost",
|
|
"x1_mini_v34",
|
|
]
|