1
0
mirror of https://github.com/home-assistant/core.git synced 2026-04-19 00:10:21 +01:00
Files
core/tests/components/solarman/test_config_flow.py
SOLARMAN f3cea5160b Add solarman integration (#152525)
Co-authored-by: xiaozhouhhh <13588112144@163.com>
Co-authored-by: Joostlek <joostlek@outlook.com>
2026-03-24 16:09:14 +01:00

253 lines
7.8 KiB
Python

"""Test the Solarman config flow."""
from ipaddress import ip_address
from unittest.mock import AsyncMock
import pytest
from homeassistant.components.solarman.const import CONF_SN, DOMAIN, MODEL_NAME_MAP
from homeassistant.config_entries import SOURCE_USER, SOURCE_ZEROCONF
from homeassistant.const import CONF_HOST, CONF_MODEL
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType
from homeassistant.helpers.service_info.zeroconf import ZeroconfServiceInfo
from tests.common import MockConfigEntry
# Configure test constants
TEST_HOST = "192.168.1.100"
TEST_DEVICE_SN = "SN1234567890"
TEST_MODEL = "SP-2W-EU"
@pytest.mark.parametrize("device_fixture", ["P1-2W"], indirect=True)
async def test_flow_success(hass: HomeAssistant, mock_solarman: AsyncMock) -> None:
"""Test successful configuration flow."""
# Initiate config flow
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
# Verify initial form
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "user"
# Submit valid data
result = await hass.config_entries.flow.async_configure(
result["flow_id"], {CONF_HOST: TEST_HOST}
)
# Verify entry creation
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == f"P1 Meter Reader ({TEST_HOST})"
assert result["context"]["unique_id"] == "SN2345678901"
# Verify configuration data.
data = result["data"]
assert data[CONF_HOST] == TEST_HOST
assert data[CONF_SN] == "SN2345678901"
assert data[CONF_MODEL] == "P1-2W"
@pytest.mark.parametrize("device_fixture", ["SP-2W-EU"], indirect=True)
@pytest.mark.parametrize(
("exception", "expected_error"),
[
(TimeoutError, "timeout"),
(ConnectionError, "cannot_connect"),
(Exception("Some unknown error"), "unknown"),
],
)
async def test_flow_error(
hass: HomeAssistant,
mock_solarman: AsyncMock,
exception: Exception,
expected_error: str,
) -> None:
"""Test connection error handling."""
# Initiate and submit config flow
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
mock_solarman.get_config.side_effect = exception
# Submit config flow
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_HOST: TEST_HOST},
)
# Verify error form display.
assert result["type"] is FlowResultType.FORM
assert result["errors"]["base"] == expected_error
mock_solarman.get_config.side_effect = None
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_HOST: TEST_HOST},
)
assert result["type"] is FlowResultType.CREATE_ENTRY
@pytest.mark.parametrize("device_fixture", ["SP-2W-EU"], indirect=True)
async def test_flow_duplicate_entry(
hass: HomeAssistant, mock_config_entry: MockConfigEntry, mock_solarman: AsyncMock
) -> None:
"""Test duplicate entry handling."""
# Create existing config entry.
mock_config_entry.add_to_hass(hass)
# Initiate and submit config flow
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: TEST_HOST}
)
# Verify flow abort
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
@pytest.mark.parametrize("device_fixture", ["SP-2W-EU"], indirect=True)
async def test_zeroconf(hass: HomeAssistant, mock_solarman: AsyncMock) -> None:
"""Test zeroconf discovery flow."""
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_ZEROCONF},
data=ZeroconfServiceInfo(
ip_address=ip_address(TEST_HOST),
ip_addresses=[ip_address(TEST_HOST)],
name="mock_name",
port=8080,
hostname="mock_hostname",
type="_solarman._tcp.local.",
properties={
"product_type": "SP-2W-EU",
"serial": TEST_DEVICE_SN,
},
),
)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "discovery_confirm"
result = await hass.config_entries.flow.async_configure(result["flow_id"], {})
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == f"{MODEL_NAME_MAP[TEST_MODEL]} ({TEST_HOST})"
data = result["data"]
assert data[CONF_HOST] == TEST_HOST
assert data[CONF_SN] == TEST_DEVICE_SN
assert data[CONF_MODEL] == TEST_MODEL
assert result["context"]["unique_id"] == TEST_DEVICE_SN
@pytest.mark.parametrize("device_fixture", ["SP-2W-EU"], indirect=True)
async def test_zeroconf_already_configured(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_solarman: AsyncMock,
) -> None:
"""Test zeroconf discovery when already configured."""
mock_config_entry.add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_ZEROCONF},
data=ZeroconfServiceInfo(
ip_address=ip_address(TEST_HOST),
ip_addresses=[ip_address(TEST_HOST)],
name="mock_name",
port=8080,
hostname="mock_hostname",
type="_solarman._tcp.local.",
properties={
"product_type": "SP-2W-EU",
"serial": TEST_DEVICE_SN,
},
),
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
@pytest.mark.parametrize("device_fixture", ["SP-2W-EU"], indirect=True)
async def test_zeroconf_ip_change(
hass: HomeAssistant, mock_config_entry: MockConfigEntry, mock_solarman: AsyncMock
) -> None:
"""Test discovery setup updates new config data."""
mock_config_entry.add_to_hass(hass)
# preflight check, see if the ip address is already in use
assert mock_config_entry.data[CONF_HOST] == TEST_HOST
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_ZEROCONF},
data=ZeroconfServiceInfo(
ip_address=ip_address("192.168.1.101"),
ip_addresses=[ip_address("192.168.1.101")],
name="mock_name",
port=8080,
hostname="mock_hostname",
type="_solarman._tcp.local.",
properties={
"product_type": "SP-2W-EU",
"serial": TEST_DEVICE_SN,
},
),
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
assert mock_config_entry.data[CONF_HOST] == "192.168.1.101"
@pytest.mark.parametrize(
("exception", "expected_error"),
[
(TimeoutError, "timeout"),
(ConnectionError, "cannot_connect"),
(Exception("Some unknown error"), "unknown"),
],
)
@pytest.mark.parametrize("device_fixture", ["SP-2W-EU"], indirect=True)
async def test_zeroconf_error(
hass: HomeAssistant,
mock_solarman: AsyncMock,
exception: Exception,
expected_error: str,
) -> None:
"""Test discovery setup."""
mock_solarman.get_config.side_effect = exception
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_ZEROCONF},
data=ZeroconfServiceInfo(
ip_address=ip_address(TEST_HOST),
ip_addresses=[ip_address(TEST_HOST)],
name="mock_name",
port=8080,
hostname="mock_hostname",
type="_solarman._tcp.local.",
properties={
"product_type": "SP-2W-EU",
"serial": TEST_DEVICE_SN,
},
),
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == expected_error