Add already exists config flow tests for Ecovacs (#133572)

Co-authored-by: Michael <35783820+mib1185@users.noreply.github.com>
Co-authored-by: Franck Nijhof <git@frenck.dev>
pull/133826/head
Robert Resch 2024-12-22 20:23:55 +01:00 committed by GitHub
parent 07322c6992
commit 0ad9af0feb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 72 additions and 48 deletions

View File

@ -1,6 +1,7 @@
"""Test Ecovacs config flow.""" """Test Ecovacs config flow."""
from collections.abc import Awaitable, Callable from collections.abc import Awaitable, Callable
from dataclasses import dataclass, field
import ssl import ssl
from typing import Any from typing import Any
from unittest.mock import AsyncMock, Mock, patch from unittest.mock import AsyncMock, Mock, patch
@ -28,15 +29,20 @@ from .const import (
VALID_ENTRY_DATA_SELF_HOSTED_WITH_VALIDATE_CERT, VALID_ENTRY_DATA_SELF_HOSTED_WITH_VALIDATE_CERT,
) )
from tests.common import MockConfigEntry
_USER_STEP_SELF_HOSTED = {CONF_MODE: InstanceMode.SELF_HOSTED} _USER_STEP_SELF_HOSTED = {CONF_MODE: InstanceMode.SELF_HOSTED}
_TEST_FN_AUTH_ARG = "user_input_auth"
_TEST_FN_USER_ARG = "user_input_user" @dataclass
class _TestFnUserInput:
auth: dict[str, Any]
user: dict[str, Any] = field(default_factory=dict)
async def _test_user_flow( async def _test_user_flow(
hass: HomeAssistant, hass: HomeAssistant,
user_input_auth: dict[str, Any], user_input: _TestFnUserInput,
) -> dict[str, Any]: ) -> dict[str, Any]:
"""Test config flow.""" """Test config flow."""
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
@ -50,15 +56,13 @@ async def _test_user_flow(
return await hass.config_entries.flow.async_configure( return await hass.config_entries.flow.async_configure(
result["flow_id"], result["flow_id"],
user_input=user_input_auth, user_input=user_input.auth,
) )
async def _test_user_flow_show_advanced_options( async def _test_user_flow_show_advanced_options(
hass: HomeAssistant, hass: HomeAssistant,
*, user_input: _TestFnUserInput,
user_input_auth: dict[str, Any],
user_input_user: dict[str, Any] | None = None,
) -> dict[str, Any]: ) -> dict[str, Any]:
"""Test config flow.""" """Test config flow."""
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
@ -72,7 +76,7 @@ async def _test_user_flow_show_advanced_options(
result = await hass.config_entries.flow.async_configure( result = await hass.config_entries.flow.async_configure(
result["flow_id"], result["flow_id"],
user_input=user_input_user or {}, user_input=user_input.user,
) )
assert result["type"] is FlowResultType.FORM assert result["type"] is FlowResultType.FORM
@ -81,29 +85,26 @@ async def _test_user_flow_show_advanced_options(
return await hass.config_entries.flow.async_configure( return await hass.config_entries.flow.async_configure(
result["flow_id"], result["flow_id"],
user_input=user_input_auth, user_input=user_input.auth,
) )
@pytest.mark.parametrize( @pytest.mark.parametrize(
("test_fn", "test_fn_args", "entry_data"), ("test_fn", "test_fn_user_input", "entry_data"),
[ [
( (
_test_user_flow_show_advanced_options, _test_user_flow_show_advanced_options,
{_TEST_FN_AUTH_ARG: VALID_ENTRY_DATA_CLOUD}, _TestFnUserInput(VALID_ENTRY_DATA_CLOUD),
VALID_ENTRY_DATA_CLOUD, VALID_ENTRY_DATA_CLOUD,
), ),
( (
_test_user_flow_show_advanced_options, _test_user_flow_show_advanced_options,
{ _TestFnUserInput(VALID_ENTRY_DATA_SELF_HOSTED, _USER_STEP_SELF_HOSTED),
_TEST_FN_AUTH_ARG: VALID_ENTRY_DATA_SELF_HOSTED,
_TEST_FN_USER_ARG: _USER_STEP_SELF_HOSTED,
},
VALID_ENTRY_DATA_SELF_HOSTED, VALID_ENTRY_DATA_SELF_HOSTED,
), ),
( (
_test_user_flow, _test_user_flow,
{_TEST_FN_AUTH_ARG: VALID_ENTRY_DATA_CLOUD}, _TestFnUserInput(VALID_ENTRY_DATA_CLOUD),
VALID_ENTRY_DATA_CLOUD, VALID_ENTRY_DATA_CLOUD,
), ),
], ],
@ -114,18 +115,12 @@ async def test_user_flow(
mock_setup_entry: AsyncMock, mock_setup_entry: AsyncMock,
mock_authenticator_authenticate: AsyncMock, mock_authenticator_authenticate: AsyncMock,
mock_mqtt_client: Mock, mock_mqtt_client: Mock,
test_fn: Callable[[HomeAssistant, dict[str, Any]], Awaitable[dict[str, Any]]] test_fn: Callable[[HomeAssistant, _TestFnUserInput], Awaitable[dict[str, Any]]],
| Callable[ test_fn_user_input: _TestFnUserInput,
[HomeAssistant, dict[str, Any], dict[str, Any]], Awaitable[dict[str, Any]]
],
test_fn_args: dict[str, Any],
entry_data: dict[str, Any], entry_data: dict[str, Any],
) -> None: ) -> None:
"""Test the user config flow.""" """Test the user config flow."""
result = await test_fn( result = await test_fn(hass, test_fn_user_input)
hass,
**test_fn_args,
)
assert result["type"] is FlowResultType.CREATE_ENTRY assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == entry_data[CONF_USERNAME] assert result["title"] == entry_data[CONF_USERNAME]
assert result["data"] == entry_data assert result["data"] == entry_data
@ -161,24 +156,21 @@ def _cannot_connect_error(user_input: dict[str, Any]) -> str:
ids=["cannot_connect", "invalid_auth", "unknown"], ids=["cannot_connect", "invalid_auth", "unknown"],
) )
@pytest.mark.parametrize( @pytest.mark.parametrize(
("test_fn", "test_fn_args", "entry_data"), ("test_fn", "test_fn_user_input", "entry_data"),
[ [
( (
_test_user_flow_show_advanced_options, _test_user_flow_show_advanced_options,
{_TEST_FN_AUTH_ARG: VALID_ENTRY_DATA_CLOUD}, _TestFnUserInput(VALID_ENTRY_DATA_CLOUD),
VALID_ENTRY_DATA_CLOUD, VALID_ENTRY_DATA_CLOUD,
), ),
( (
_test_user_flow_show_advanced_options, _test_user_flow_show_advanced_options,
{ _TestFnUserInput(VALID_ENTRY_DATA_SELF_HOSTED, _USER_STEP_SELF_HOSTED),
_TEST_FN_AUTH_ARG: VALID_ENTRY_DATA_SELF_HOSTED,
_TEST_FN_USER_ARG: _USER_STEP_SELF_HOSTED,
},
VALID_ENTRY_DATA_SELF_HOSTED_WITH_VALIDATE_CERT, VALID_ENTRY_DATA_SELF_HOSTED_WITH_VALIDATE_CERT,
), ),
( (
_test_user_flow, _test_user_flow,
{_TEST_FN_AUTH_ARG: VALID_ENTRY_DATA_CLOUD}, _TestFnUserInput(VALID_ENTRY_DATA_CLOUD),
VALID_ENTRY_DATA_CLOUD, VALID_ENTRY_DATA_CLOUD,
), ),
], ],
@ -193,22 +185,16 @@ async def test_user_flow_raise_error(
reason_rest: str, reason_rest: str,
side_effect_mqtt: Exception, side_effect_mqtt: Exception,
errors_mqtt: Callable[[dict[str, Any]], str], errors_mqtt: Callable[[dict[str, Any]], str],
test_fn: Callable[[HomeAssistant, dict[str, Any]], Awaitable[dict[str, Any]]] test_fn: Callable[[HomeAssistant, _TestFnUserInput], Awaitable[dict[str, Any]]],
| Callable[ test_fn_user_input: _TestFnUserInput,
[HomeAssistant, dict[str, Any], dict[str, Any]], Awaitable[dict[str, Any]]
],
test_fn_args: dict[str, Any],
entry_data: dict[str, Any], entry_data: dict[str, Any],
) -> None: ) -> None:
"""Test handling error on library calls.""" """Test handling error on library calls."""
user_input_auth = test_fn_args[_TEST_FN_AUTH_ARG] user_input_auth = test_fn_user_input.auth
# Authenticator raises error # Authenticator raises error
mock_authenticator_authenticate.side_effect = side_effect_rest mock_authenticator_authenticate.side_effect = side_effect_rest
result = await test_fn( result = await test_fn(hass, test_fn_user_input)
hass,
**test_fn_args,
)
assert result["type"] is FlowResultType.FORM assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "auth" assert result["step_id"] == "auth"
assert result["errors"] == {"base": reason_rest} assert result["errors"] == {"base": reason_rest}
@ -256,12 +242,14 @@ async def test_user_flow_self_hosted_error(
result = await _test_user_flow_show_advanced_options( result = await _test_user_flow_show_advanced_options(
hass, hass,
user_input_auth=VALID_ENTRY_DATA_SELF_HOSTED _TestFnUserInput(
VALID_ENTRY_DATA_SELF_HOSTED
| { | {
CONF_OVERRIDE_REST_URL: "bla://localhost:8000", CONF_OVERRIDE_REST_URL: "bla://localhost:8000",
CONF_OVERRIDE_MQTT_URL: "mqtt://", CONF_OVERRIDE_MQTT_URL: "mqtt://",
}, },
user_input_user=_USER_STEP_SELF_HOSTED, _USER_STEP_SELF_HOSTED,
),
) )
assert result["type"] is FlowResultType.FORM assert result["type"] is FlowResultType.FORM
@ -298,3 +286,39 @@ async def test_user_flow_self_hosted_error(
mock_setup_entry.assert_called() mock_setup_entry.assert_called()
mock_authenticator_authenticate.assert_called() mock_authenticator_authenticate.assert_called()
mock_mqtt_client.verify_config.assert_called() mock_mqtt_client.verify_config.assert_called()
@pytest.mark.parametrize(
("test_fn", "test_fn_user_input"),
[
(
_test_user_flow_show_advanced_options,
_TestFnUserInput(VALID_ENTRY_DATA_CLOUD),
),
(
_test_user_flow_show_advanced_options,
_TestFnUserInput(VALID_ENTRY_DATA_SELF_HOSTED, _USER_STEP_SELF_HOSTED),
),
(
_test_user_flow,
_TestFnUserInput(VALID_ENTRY_DATA_CLOUD),
),
],
ids=["advanced_cloud", "advanced_self_hosted", "cloud"],
)
async def test_already_exists(
hass: HomeAssistant,
test_fn: Callable[[HomeAssistant, _TestFnUserInput], Awaitable[dict[str, Any]]],
test_fn_user_input: _TestFnUserInput,
) -> None:
"""Test we don't allow duplicated config entries."""
MockConfigEntry(domain=DOMAIN, data=test_fn_user_input.auth).add_to_hass(hass)
result = await test_fn(
hass,
test_fn_user_input,
)
assert result
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"