mirror of
https://github.com/home-assistant/core.git
synced 2025-07-20 19:57:07 +00:00
Improve config flow for GIOS (#139935)
* Initial commit * Use TYPE_CHECKING * Update strings * Remove default value * Improve tests
This commit is contained in:
parent
d3a96ba688
commit
98cf936ff5
@ -3,7 +3,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
from typing import Any
|
from typing import TYPE_CHECKING, Any
|
||||||
|
|
||||||
from aiohttp.client_exceptions import ClientConnectorError
|
from aiohttp.client_exceptions import ClientConnectorError
|
||||||
from gios import ApiError, Gios, InvalidSensorsDataError, NoStationError
|
from gios import ApiError, Gios, InvalidSensorsDataError, NoStationError
|
||||||
@ -12,6 +12,12 @@ import voluptuous as vol
|
|||||||
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
|
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
|
||||||
from homeassistant.const import CONF_NAME
|
from homeassistant.const import CONF_NAME
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
|
from homeassistant.helpers.selector import (
|
||||||
|
SelectOptionDict,
|
||||||
|
SelectSelector,
|
||||||
|
SelectSelectorConfig,
|
||||||
|
SelectSelectorMode,
|
||||||
|
)
|
||||||
|
|
||||||
from .const import API_TIMEOUT, CONF_STATION_ID, DOMAIN
|
from .const import API_TIMEOUT, CONF_STATION_ID, DOMAIN
|
||||||
|
|
||||||
@ -27,40 +33,59 @@ class GiosFlowHandler(ConfigFlow, domain=DOMAIN):
|
|||||||
"""Handle a flow initialized by the user."""
|
"""Handle a flow initialized by the user."""
|
||||||
errors = {}
|
errors = {}
|
||||||
|
|
||||||
if user_input is not None:
|
|
||||||
try:
|
|
||||||
await self.async_set_unique_id(
|
|
||||||
str(user_input[CONF_STATION_ID]), raise_on_progress=False
|
|
||||||
)
|
|
||||||
self._abort_if_unique_id_configured()
|
|
||||||
|
|
||||||
websession = async_get_clientsession(self.hass)
|
websession = async_get_clientsession(self.hass)
|
||||||
|
|
||||||
|
if user_input is not None:
|
||||||
|
station_id = user_input[CONF_STATION_ID]
|
||||||
|
|
||||||
|
try:
|
||||||
|
await self.async_set_unique_id(station_id, raise_on_progress=False)
|
||||||
|
self._abort_if_unique_id_configured()
|
||||||
|
|
||||||
async with asyncio.timeout(API_TIMEOUT):
|
async with asyncio.timeout(API_TIMEOUT):
|
||||||
gios = await Gios.create(websession, user_input[CONF_STATION_ID])
|
gios = await Gios.create(websession, int(station_id))
|
||||||
await gios.async_update()
|
await gios.async_update()
|
||||||
|
|
||||||
|
# GIOS treats station ID as int
|
||||||
|
user_input[CONF_STATION_ID] = int(station_id)
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
assert gios.station_name is not None
|
assert gios.station_name is not None
|
||||||
|
|
||||||
return self.async_create_entry(
|
return self.async_create_entry(
|
||||||
title=gios.station_name,
|
title=gios.station_name,
|
||||||
data=user_input,
|
data=user_input,
|
||||||
)
|
)
|
||||||
except (ApiError, ClientConnectorError, TimeoutError):
|
except (ApiError, ClientConnectorError, TimeoutError):
|
||||||
errors["base"] = "cannot_connect"
|
errors["base"] = "cannot_connect"
|
||||||
except NoStationError:
|
|
||||||
errors[CONF_STATION_ID] = "wrong_station_id"
|
|
||||||
except InvalidSensorsDataError:
|
except InvalidSensorsDataError:
|
||||||
errors[CONF_STATION_ID] = "invalid_sensors_data"
|
errors[CONF_STATION_ID] = "invalid_sensors_data"
|
||||||
|
|
||||||
|
try:
|
||||||
|
gios = await Gios.create(websession)
|
||||||
|
except (ApiError, ClientConnectorError, NoStationError):
|
||||||
|
return self.async_abort(reason="cannot_connect")
|
||||||
|
|
||||||
|
options: list[SelectOptionDict] = [
|
||||||
|
SelectOptionDict(value=str(station.id), label=station.name)
|
||||||
|
for station in gios.measurement_stations.values()
|
||||||
|
]
|
||||||
|
|
||||||
|
schema: vol.Schema = vol.Schema(
|
||||||
|
{
|
||||||
|
vol.Required(CONF_STATION_ID): SelectSelector(
|
||||||
|
SelectSelectorConfig(
|
||||||
|
options=options,
|
||||||
|
sort=True,
|
||||||
|
mode=SelectSelectorMode.DROPDOWN,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
vol.Optional(CONF_NAME, default=self.hass.config.location_name): str,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
return self.async_show_form(
|
return self.async_show_form(
|
||||||
step_id="user",
|
step_id="user",
|
||||||
data_schema=vol.Schema(
|
data_schema=schema,
|
||||||
{
|
|
||||||
vol.Required(CONF_STATION_ID): int,
|
|
||||||
vol.Optional(
|
|
||||||
CONF_NAME, default=self.hass.config.location_name
|
|
||||||
): str,
|
|
||||||
}
|
|
||||||
),
|
|
||||||
errors=errors,
|
errors=errors,
|
||||||
)
|
)
|
||||||
|
@ -5,17 +5,17 @@
|
|||||||
"title": "GIO\u015a (Polish Chief Inspectorate Of Environmental Protection)",
|
"title": "GIO\u015a (Polish Chief Inspectorate Of Environmental Protection)",
|
||||||
"data": {
|
"data": {
|
||||||
"name": "[%key:common::config_flow::data::name%]",
|
"name": "[%key:common::config_flow::data::name%]",
|
||||||
"station_id": "ID of the measuring station"
|
"station_id": "Measuring station"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"error": {
|
"error": {
|
||||||
"wrong_station_id": "ID of the measuring station is not correct.",
|
|
||||||
"invalid_sensors_data": "Invalid sensors' data for this measuring station.",
|
"invalid_sensors_data": "Invalid sensors' data for this measuring station.",
|
||||||
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]"
|
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]"
|
||||||
},
|
},
|
||||||
"abort": {
|
"abort": {
|
||||||
"already_configured": "[%key:common::config_flow::abort::already_configured_location%]"
|
"already_configured": "[%key:common::config_flow::abort::already_configured_location%]",
|
||||||
|
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system_health": {
|
"system_health": {
|
||||||
|
@ -6,7 +6,8 @@ from unittest.mock import patch
|
|||||||
from gios import ApiError
|
from gios import ApiError
|
||||||
|
|
||||||
from homeassistant.components.gios import config_flow
|
from homeassistant.components.gios import config_flow
|
||||||
from homeassistant.components.gios.const import CONF_STATION_ID
|
from homeassistant.components.gios.const import CONF_STATION_ID, DOMAIN
|
||||||
|
from homeassistant.config_entries import SOURCE_USER
|
||||||
from homeassistant.const import CONF_NAME
|
from homeassistant.const import CONF_NAME
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.data_entry_flow import FlowResultType
|
from homeassistant.data_entry_flow import FlowResultType
|
||||||
@ -17,36 +18,35 @@ from tests.common import load_fixture
|
|||||||
|
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
CONF_NAME: "Foo",
|
CONF_NAME: "Foo",
|
||||||
CONF_STATION_ID: 123,
|
CONF_STATION_ID: "123",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async def test_show_form(hass: HomeAssistant) -> None:
|
async def test_show_form(hass: HomeAssistant) -> None:
|
||||||
"""Test that the form is served with no input."""
|
"""Test that the form is served with no input."""
|
||||||
flow = config_flow.GiosFlowHandler()
|
with patch(
|
||||||
flow.hass = hass
|
"homeassistant.components.gios.coordinator.Gios._get_stations",
|
||||||
|
return_value=STATIONS,
|
||||||
result = await flow.async_step_user(user_input=None)
|
):
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": SOURCE_USER}
|
||||||
|
)
|
||||||
|
|
||||||
assert result["type"] is FlowResultType.FORM
|
assert result["type"] is FlowResultType.FORM
|
||||||
assert result["step_id"] == "user"
|
assert result["step_id"] == "user"
|
||||||
|
|
||||||
|
|
||||||
async def test_invalid_station_id(hass: HomeAssistant) -> None:
|
async def test_form_with_api_error(hass: HomeAssistant) -> None:
|
||||||
"""Test that errors are shown when measuring station ID is invalid."""
|
"""Test the form is aborted because of API error."""
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.gios.coordinator.Gios._get_stations",
|
"homeassistant.components.gios.coordinator.Gios._get_stations",
|
||||||
return_value=STATIONS,
|
side_effect=ApiError("error"),
|
||||||
):
|
):
|
||||||
flow = config_flow.GiosFlowHandler()
|
result = await hass.config_entries.flow.async_init(
|
||||||
flow.hass = hass
|
DOMAIN, context={"source": SOURCE_USER}
|
||||||
flow.context = {}
|
|
||||||
|
|
||||||
result = await flow.async_step_user(
|
|
||||||
user_input={CONF_NAME: "Foo", CONF_STATION_ID: 0}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
assert result["errors"] == {CONF_STATION_ID: "wrong_station_id"}
|
assert result["type"] is FlowResultType.ABORT
|
||||||
|
|
||||||
|
|
||||||
async def test_invalid_sensor_data(hass: HomeAssistant) -> None:
|
async def test_invalid_sensor_data(hass: HomeAssistant) -> None:
|
||||||
@ -76,15 +76,23 @@ async def test_invalid_sensor_data(hass: HomeAssistant) -> None:
|
|||||||
|
|
||||||
async def test_cannot_connect(hass: HomeAssistant) -> None:
|
async def test_cannot_connect(hass: HomeAssistant) -> None:
|
||||||
"""Test that errors are shown when cannot connect to GIOS server."""
|
"""Test that errors are shown when cannot connect to GIOS server."""
|
||||||
with patch(
|
with (
|
||||||
|
patch(
|
||||||
|
"homeassistant.components.gios.coordinator.Gios._get_stations",
|
||||||
|
return_value=STATIONS,
|
||||||
|
),
|
||||||
|
patch(
|
||||||
"homeassistant.components.gios.coordinator.Gios._async_get",
|
"homeassistant.components.gios.coordinator.Gios._async_get",
|
||||||
side_effect=ApiError("error"),
|
side_effect=ApiError("error"),
|
||||||
|
),
|
||||||
):
|
):
|
||||||
flow = config_flow.GiosFlowHandler()
|
result = await hass.config_entries.flow.async_init(
|
||||||
flow.hass = hass
|
DOMAIN, context={"source": SOURCE_USER}
|
||||||
flow.context = {}
|
)
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result = await flow.async_step_user(user_input=CONFIG)
|
result["flow_id"], CONFIG
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert result["errors"] == {"base": "cannot_connect"}
|
assert result["errors"] == {"base": "cannot_connect"}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user