From ebee1a3feba5a38f74425cbc1a3c9891c82810ef Mon Sep 17 00:00:00 2001 From: Manu Date: Sun, 4 Oct 2026 18:01:05 +0200 Subject: [PATCH] Split user flow init and data submission in tomorrowio config flow tests (#184176) --- tests/components/tomorrowio/conftest.py | 7 +- .../components/tomorrowio/test_config_flow.py | 109 ++++++++---------- 2 files changed, 54 insertions(+), 62 deletions(-) diff --git a/tests/components/tomorrowio/conftest.py b/tests/components/tomorrowio/conftest.py index 05f788d614f1..6d3b8b10ef2d 100644 --- a/tests/components/tomorrowio/conftest.py +++ b/tests/components/tomorrowio/conftest.py @@ -1,6 +1,7 @@ """Configure py.test.""" -from unittest.mock import PropertyMock, patch +from collections.abc import Generator +from unittest.mock import AsyncMock, PropertyMock, patch import pytest @@ -8,7 +9,7 @@ from tests.common import load_json_object_fixture @pytest.fixture(name="tomorrowio_config_flow_connect", autouse=True) -def tomorrowio_config_flow_connect(): +def tomorrowio_config_flow_connect() -> Generator[None]: """Mock valid tomorrowio config flow setup.""" with patch( "homeassistant.components.tomorrowio.config_flow.TomorrowioV4.realtime", @@ -18,7 +19,7 @@ def tomorrowio_config_flow_connect(): @pytest.fixture(name="tomorrowio_config_entry_update", autouse=True) -def tomorrowio_config_entry_update_fixture(): +def tomorrowio_config_entry_update_fixture() -> Generator[AsyncMock]: """Mock valid tomorrowio config entry setup.""" with ( patch( diff --git a/tests/components/tomorrowio/test_config_flow.py b/tests/components/tomorrowio/test_config_flow.py index d280e8a51825..4044117e918b 100644 --- a/tests/components/tomorrowio/test_config_flow.py +++ b/tests/components/tomorrowio/test_config_flow.py @@ -2,6 +2,7 @@ from unittest.mock import patch +import pytest from pytomorrowio.exceptions import ( CantConnectException, InvalidAPIKeyException, @@ -102,79 +103,69 @@ async def test_user_flow_same_unique_ids(hass: HomeAssistant) -> None: unique_id=_get_unique_id(hass, user_input), version=2, ).add_to_hass(hass) - result = await hass.config_entries.flow.async_init( - DOMAIN, - context={"source": SOURCE_USER}, - data=user_input, + DOMAIN, context={"source": SOURCE_USER} + ) + assert result["type"] is FlowResultType.FORM + assert result["step_id"] == "user" + assert result["errors"] == {} + + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + user_input=user_input, ) assert result["type"] is FlowResultType.ABORT assert result["reason"] == "already_configured" -async def test_user_flow_cannot_connect(hass: HomeAssistant) -> None: - """Test user config flow when Tomorrow.io can't connect.""" +@pytest.mark.parametrize( + ("side_effect", "errors"), + [ + (CantConnectException, {"base": "cannot_connect"}), + (InvalidAPIKeyException, {CONF_API_KEY: "invalid_api_key"}), + (RateLimitedException, {CONF_API_KEY: "rate_limited"}), + (UnknownException, {"base": "unknown"}), + ], +) +async def test_user_flow_errors( + hass: HomeAssistant, side_effect: type[Exception], errors: dict[str, str] +) -> None: + """Test user config flow errors and recovery.""" + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": SOURCE_USER} + ) + assert result["type"] is FlowResultType.FORM + assert result["step_id"] == "user" + assert result["errors"] == {} + with patch( "homeassistant.components.tomorrowio.config_flow.TomorrowioV4.realtime", - side_effect=CantConnectException, + side_effect=side_effect, ): - result = await hass.config_entries.flow.async_init( - DOMAIN, - context={"source": SOURCE_USER}, - data=_get_config_schema(hass, SOURCE_USER, MIN_CONFIG)(MIN_CONFIG), + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + user_input=_get_config_schema(hass, SOURCE_USER, MIN_CONFIG)(MIN_CONFIG), ) - assert result["type"] is FlowResultType.FORM - assert result["errors"] == {"base": "cannot_connect"} + assert result["type"] is FlowResultType.FORM + assert result["errors"] == errors + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + user_input=_get_config_schema(hass, SOURCE_USER, MIN_CONFIG)(MIN_CONFIG), + ) -async def test_user_flow_invalid_api(hass: HomeAssistant) -> None: - """Test user config flow when API key is invalid.""" - with patch( - "homeassistant.components.tomorrowio.config_flow.TomorrowioV4.realtime", - side_effect=InvalidAPIKeyException, - ): - result = await hass.config_entries.flow.async_init( - DOMAIN, - context={"source": SOURCE_USER}, - data=_get_config_schema(hass, SOURCE_USER, MIN_CONFIG)(MIN_CONFIG), - ) - - assert result["type"] is FlowResultType.FORM - assert result["errors"] == {CONF_API_KEY: "invalid_api_key"} - - -async def test_user_flow_rate_limited(hass: HomeAssistant) -> None: - """Test user config flow when API key is rate limited.""" - with patch( - "homeassistant.components.tomorrowio.config_flow.TomorrowioV4.realtime", - side_effect=RateLimitedException, - ): - result = await hass.config_entries.flow.async_init( - DOMAIN, - context={"source": SOURCE_USER}, - data=_get_config_schema(hass, SOURCE_USER, MIN_CONFIG)(MIN_CONFIG), - ) - - assert result["type"] is FlowResultType.FORM - assert result["errors"] == {CONF_API_KEY: "rate_limited"} - - -async def test_user_flow_unknown_exception(hass: HomeAssistant) -> None: - """Test user config flow when unknown error occurs.""" - with patch( - "homeassistant.components.tomorrowio.config_flow.TomorrowioV4.realtime", - side_effect=UnknownException, - ): - result = await hass.config_entries.flow.async_init( - DOMAIN, - context={"source": SOURCE_USER}, - data=_get_config_schema(hass, SOURCE_USER, MIN_CONFIG)(MIN_CONFIG), - ) - - assert result["type"] is FlowResultType.FORM - assert result["errors"] == {"base": "unknown"} + assert result["type"] is FlowResultType.CREATE_ENTRY + assert result["title"] == DEFAULT_NAME + assert result["data"] == { + CONF_NAME: DEFAULT_NAME, + CONF_API_KEY: API_KEY, + CONF_LOCATION: { + CONF_LATITUDE: hass.config.latitude, + CONF_LONGITUDE: hass.config.longitude, + }, + } async def test_options_flow(hass: HomeAssistant) -> None: