From 31e9ca009991bdde292971356a194a1fe54f536a Mon Sep 17 00:00:00 2001 From: Rami Mosleh Date: Tue, 26 Sep 2023 15:51:04 +0300 Subject: [PATCH] Handle authorization error in glances config flow (#100866) * Handle authroization error in glances config flow * Remove validate_input method and expections * update tests --- .../components/glances/config_flow.py | 31 +++++++------------ homeassistant/components/glances/strings.json | 3 +- tests/components/glances/test_config_flow.py | 30 ++++++++++++++---- 3 files changed, 38 insertions(+), 26 deletions(-) diff --git a/homeassistant/components/glances/config_flow.py b/homeassistant/components/glances/config_flow.py index 58b81bc088e..e61761b26c6 100644 --- a/homeassistant/components/glances/config_flow.py +++ b/homeassistant/components/glances/config_flow.py @@ -3,10 +3,13 @@ from __future__ import annotations from typing import Any -from glances_api.exceptions import GlancesApiError +from glances_api.exceptions import ( + GlancesApiAuthorizationError, + GlancesApiConnectionError, +) import voluptuous as vol -from homeassistant import config_entries, exceptions +from homeassistant import config_entries from homeassistant.const import ( CONF_HOST, CONF_PASSWORD, @@ -15,7 +18,6 @@ from homeassistant.const import ( CONF_USERNAME, CONF_VERIFY_SSL, ) -from homeassistant.core import HomeAssistant from homeassistant.data_entry_flow import FlowResult from . import get_api @@ -41,15 +43,6 @@ DATA_SCHEMA = vol.Schema( ) -async def validate_input(hass: HomeAssistant, data: dict[str, Any]) -> None: - """Validate the user input allows us to connect.""" - api = get_api(hass, data) - try: - await api.get_ha_sensor_data() - except GlancesApiError as err: - raise CannotConnect from err - - class GlancesFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): """Handle a Glances config flow.""" @@ -64,19 +57,19 @@ class GlancesFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): self._async_abort_entries_match( {CONF_HOST: user_input[CONF_HOST], CONF_PORT: user_input[CONF_PORT]} ) + api = get_api(self.hass, user_input) try: - await validate_input(self.hass, user_input) + await api.get_ha_sensor_data() + except GlancesApiAuthorizationError: + errors["base"] = "invalid_auth" + except GlancesApiConnectionError: + errors["base"] = "cannot_connect" + if not errors: return self.async_create_entry( title=f"{user_input[CONF_HOST]}:{user_input[CONF_PORT]}", data=user_input, ) - except CannotConnect: - errors["base"] = "cannot_connect" return self.async_show_form( step_id="user", data_schema=DATA_SCHEMA, errors=errors ) - - -class CannotConnect(exceptions.HomeAssistantError): - """Error to indicate we cannot connect.""" diff --git a/homeassistant/components/glances/strings.json b/homeassistant/components/glances/strings.json index b46716b43c0..684eb05d1d6 100644 --- a/homeassistant/components/glances/strings.json +++ b/homeassistant/components/glances/strings.json @@ -14,7 +14,8 @@ } }, "error": { - "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]" + "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", + "invalid_auth": "[%key:common::config_flow::error::invalid_auth%]" }, "abort": { "already_configured": "[%key:common::config_flow::abort::already_configured_device%]" diff --git a/tests/components/glances/test_config_flow.py b/tests/components/glances/test_config_flow.py index d4d25d8b86f..b8ab7742088 100644 --- a/tests/components/glances/test_config_flow.py +++ b/tests/components/glances/test_config_flow.py @@ -1,7 +1,10 @@ """Tests for Glances config flow.""" from unittest.mock import MagicMock -from glances_api.exceptions import GlancesApiConnectionError +from glances_api.exceptions import ( + GlancesApiAuthorizationError, + GlancesApiConnectionError, +) import pytest from homeassistant import config_entries @@ -9,7 +12,7 @@ from homeassistant.components import glances from homeassistant.core import HomeAssistant from homeassistant.data_entry_flow import FlowResultType -from . import MOCK_USER_INPUT +from . import HA_SENSOR_DATA, MOCK_USER_INPUT from tests.common import MockConfigEntry, patch @@ -39,10 +42,19 @@ async def test_form(hass: HomeAssistant) -> None: assert result["data"] == MOCK_USER_INPUT -async def test_form_cannot_connect(hass: HomeAssistant, mock_api: MagicMock) -> None: - """Test to return error if we cannot connect.""" +@pytest.mark.parametrize( + ("error", "message"), + [ + (GlancesApiAuthorizationError, "invalid_auth"), + (GlancesApiConnectionError, "cannot_connect"), + ], +) +async def test_form_fails( + hass: HomeAssistant, error: Exception, message: str, mock_api: MagicMock +) -> None: + """Test flow fails when api exception is raised.""" - mock_api.return_value.get_ha_sensor_data.side_effect = GlancesApiConnectionError + mock_api.return_value.get_ha_sensor_data.side_effect = [error, HA_SENSOR_DATA] result = await hass.config_entries.flow.async_init( glances.DOMAIN, context={"source": config_entries.SOURCE_USER} ) @@ -51,7 +63,13 @@ async def test_form_cannot_connect(hass: HomeAssistant, mock_api: MagicMock) -> ) assert result["type"] == FlowResultType.FORM - assert result["errors"] == {"base": "cannot_connect"} + assert result["errors"] == {"base": message} + + result = await hass.config_entries.flow.async_configure( + result["flow_id"], user_input=MOCK_USER_INPUT + ) + + assert result["type"] == FlowResultType.CREATE_ENTRY async def test_form_already_configured(hass: HomeAssistant) -> None: