mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 05:07:41 +00:00
Add FAA Delays Integration (#41347)
Co-authored-by: Franck Nijhof <frenck@frenck.nl> Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
parent
ba51ada494
commit
8d2606134d
@ -272,6 +272,8 @@ omit =
|
|||||||
homeassistant/components/evohome/*
|
homeassistant/components/evohome/*
|
||||||
homeassistant/components/ezviz/*
|
homeassistant/components/ezviz/*
|
||||||
homeassistant/components/familyhub/camera.py
|
homeassistant/components/familyhub/camera.py
|
||||||
|
homeassistant/components/faa_delays/__init__.py
|
||||||
|
homeassistant/components/faa_delays/binary_sensor.py
|
||||||
homeassistant/components/fastdotcom/*
|
homeassistant/components/fastdotcom/*
|
||||||
homeassistant/components/ffmpeg/camera.py
|
homeassistant/components/ffmpeg/camera.py
|
||||||
homeassistant/components/fibaro/*
|
homeassistant/components/fibaro/*
|
||||||
|
@ -146,6 +146,7 @@ homeassistant/components/esphome/* @OttoWinter
|
|||||||
homeassistant/components/essent/* @TheLastProject
|
homeassistant/components/essent/* @TheLastProject
|
||||||
homeassistant/components/evohome/* @zxdavb
|
homeassistant/components/evohome/* @zxdavb
|
||||||
homeassistant/components/ezviz/* @baqs
|
homeassistant/components/ezviz/* @baqs
|
||||||
|
homeassistant/components/faa_delays/* @ntilley905
|
||||||
homeassistant/components/fastdotcom/* @rohankapoorcom
|
homeassistant/components/fastdotcom/* @rohankapoorcom
|
||||||
homeassistant/components/file/* @fabaff
|
homeassistant/components/file/* @fabaff
|
||||||
homeassistant/components/filter/* @dgomes
|
homeassistant/components/filter/* @dgomes
|
||||||
|
84
homeassistant/components/faa_delays/__init__.py
Normal file
84
homeassistant/components/faa_delays/__init__.py
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
"""The FAA Delays integration."""
|
||||||
|
import asyncio
|
||||||
|
from datetime import timedelta
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from aiohttp import ClientConnectionError
|
||||||
|
from async_timeout import timeout
|
||||||
|
from faadelays import Airport
|
||||||
|
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.const import CONF_ID
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.exceptions import ConfigEntryNotReady
|
||||||
|
from homeassistant.helpers import aiohttp_client
|
||||||
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||||
|
|
||||||
|
from .const import DOMAIN
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
PLATFORMS = ["binary_sensor"]
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup(hass: HomeAssistant, config: dict):
|
||||||
|
"""Set up the FAA Delays component."""
|
||||||
|
hass.data[DOMAIN] = {}
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
||||||
|
"""Set up FAA Delays from a config entry."""
|
||||||
|
code = entry.data[CONF_ID]
|
||||||
|
|
||||||
|
coordinator = FAADataUpdateCoordinator(hass, code)
|
||||||
|
await coordinator.async_refresh()
|
||||||
|
|
||||||
|
if not coordinator.last_update_success:
|
||||||
|
raise ConfigEntryNotReady
|
||||||
|
|
||||||
|
hass.data[DOMAIN][entry.entry_id] = coordinator
|
||||||
|
|
||||||
|
for component in PLATFORMS:
|
||||||
|
hass.async_create_task(
|
||||||
|
hass.config_entries.async_forward_entry_setup(entry, component)
|
||||||
|
)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
|
||||||
|
"""Unload a config entry."""
|
||||||
|
unload_ok = all(
|
||||||
|
await asyncio.gather(
|
||||||
|
*[
|
||||||
|
hass.config_entries.async_forward_entry_unload(entry, component)
|
||||||
|
for component in PLATFORMS
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if unload_ok:
|
||||||
|
hass.data[DOMAIN].pop(entry.entry_id)
|
||||||
|
|
||||||
|
return unload_ok
|
||||||
|
|
||||||
|
|
||||||
|
class FAADataUpdateCoordinator(DataUpdateCoordinator):
|
||||||
|
"""Class to manage fetching FAA API data from a single endpoint."""
|
||||||
|
|
||||||
|
def __init__(self, hass, code):
|
||||||
|
"""Initialize the coordinator."""
|
||||||
|
super().__init__(
|
||||||
|
hass, _LOGGER, name=DOMAIN, update_interval=timedelta(minutes=1)
|
||||||
|
)
|
||||||
|
self.session = aiohttp_client.async_get_clientsession(hass)
|
||||||
|
self.data = Airport(code, self.session)
|
||||||
|
self.code = code
|
||||||
|
|
||||||
|
async def _async_update_data(self):
|
||||||
|
try:
|
||||||
|
with timeout(10):
|
||||||
|
await self.data.update()
|
||||||
|
except ClientConnectionError as err:
|
||||||
|
raise UpdateFailed(err) from err
|
||||||
|
return self.data
|
93
homeassistant/components/faa_delays/binary_sensor.py
Normal file
93
homeassistant/components/faa_delays/binary_sensor.py
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
"""Platform for FAA Delays sensor component."""
|
||||||
|
from homeassistant.components.binary_sensor import BinarySensorEntity
|
||||||
|
from homeassistant.const import ATTR_ICON, ATTR_NAME
|
||||||
|
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||||
|
|
||||||
|
from .const import DOMAIN, FAA_BINARY_SENSORS
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(hass, entry, async_add_entities):
|
||||||
|
"""Set up a FAA sensor based on a config entry."""
|
||||||
|
coordinator = hass.data[DOMAIN][entry.entry_id]
|
||||||
|
|
||||||
|
binary_sensors = []
|
||||||
|
for kind, attrs in FAA_BINARY_SENSORS.items():
|
||||||
|
name = attrs[ATTR_NAME]
|
||||||
|
icon = attrs[ATTR_ICON]
|
||||||
|
|
||||||
|
binary_sensors.append(
|
||||||
|
FAABinarySensor(coordinator, kind, name, icon, entry.entry_id)
|
||||||
|
)
|
||||||
|
|
||||||
|
async_add_entities(binary_sensors)
|
||||||
|
|
||||||
|
|
||||||
|
class FAABinarySensor(CoordinatorEntity, BinarySensorEntity):
|
||||||
|
"""Define a binary sensor for FAA Delays."""
|
||||||
|
|
||||||
|
def __init__(self, coordinator, sensor_type, name, icon, entry_id):
|
||||||
|
"""Initialize the sensor."""
|
||||||
|
super().__init__(coordinator)
|
||||||
|
|
||||||
|
self.coordinator = coordinator
|
||||||
|
self._entry_id = entry_id
|
||||||
|
self._icon = icon
|
||||||
|
self._name = name
|
||||||
|
self._sensor_type = sensor_type
|
||||||
|
self._id = self.coordinator.data.iata
|
||||||
|
self._attrs = {}
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
"""Return the name of the sensor."""
|
||||||
|
return f"{self._id} {self._name}"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def icon(self):
|
||||||
|
"""Return the icon."""
|
||||||
|
return self._icon
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_on(self):
|
||||||
|
"""Return the status of the sensor."""
|
||||||
|
if self._sensor_type == "GROUND_DELAY":
|
||||||
|
return self.coordinator.data.ground_delay.status
|
||||||
|
if self._sensor_type == "GROUND_STOP":
|
||||||
|
return self.coordinator.data.ground_stop.status
|
||||||
|
if self._sensor_type == "DEPART_DELAY":
|
||||||
|
return self.coordinator.data.depart_delay.status
|
||||||
|
if self._sensor_type == "ARRIVE_DELAY":
|
||||||
|
return self.coordinator.data.arrive_delay.status
|
||||||
|
if self._sensor_type == "CLOSURE":
|
||||||
|
return self.coordinator.data.closure.status
|
||||||
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def unique_id(self):
|
||||||
|
"""Return a unique, Home Assistant friendly identifier for this entity."""
|
||||||
|
return f"{self._id}_{self._sensor_type}"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def device_state_attributes(self):
|
||||||
|
"""Return attributes for sensor."""
|
||||||
|
if self._sensor_type == "GROUND_DELAY":
|
||||||
|
self._attrs["average"] = self.coordinator.data.ground_delay.average
|
||||||
|
self._attrs["reason"] = self.coordinator.data.ground_delay.reason
|
||||||
|
elif self._sensor_type == "GROUND_STOP":
|
||||||
|
self._attrs["endtime"] = self.coordinator.data.ground_stop.endtime
|
||||||
|
self._attrs["reason"] = self.coordinator.data.ground_stop.reason
|
||||||
|
elif self._sensor_type == "DEPART_DELAY":
|
||||||
|
self._attrs["minimum"] = self.coordinator.data.depart_delay.minimum
|
||||||
|
self._attrs["maximum"] = self.coordinator.data.depart_delay.maximum
|
||||||
|
self._attrs["trend"] = self.coordinator.data.depart_delay.trend
|
||||||
|
self._attrs["reason"] = self.coordinator.data.depart_delay.reason
|
||||||
|
elif self._sensor_type == "ARRIVE_DELAY":
|
||||||
|
self._attrs["minimum"] = self.coordinator.data.arrive_delay.minimum
|
||||||
|
self._attrs["maximum"] = self.coordinator.data.arrive_delay.maximum
|
||||||
|
self._attrs["trend"] = self.coordinator.data.arrive_delay.trend
|
||||||
|
self._attrs["reason"] = self.coordinator.data.arrive_delay.reason
|
||||||
|
elif self._sensor_type == "CLOSURE":
|
||||||
|
self._attrs["begin"] = self.coordinator.data.closure.begin
|
||||||
|
self._attrs["end"] = self.coordinator.data.closure.end
|
||||||
|
self._attrs["reason"] = self.coordinator.data.closure.reason
|
||||||
|
return self._attrs
|
62
homeassistant/components/faa_delays/config_flow.py
Normal file
62
homeassistant/components/faa_delays/config_flow.py
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
"""Config flow for FAA Delays integration."""
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from aiohttp import ClientConnectionError
|
||||||
|
import faadelays
|
||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
from homeassistant import config_entries
|
||||||
|
from homeassistant.const import CONF_ID
|
||||||
|
from homeassistant.helpers import aiohttp_client
|
||||||
|
|
||||||
|
from .const import DOMAIN # pylint:disable=unused-import
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
DATA_SCHEMA = vol.Schema({vol.Required(CONF_ID): str})
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
|
"""Handle a config flow for FAA Delays."""
|
||||||
|
|
||||||
|
VERSION = 1
|
||||||
|
CONNECTION_CLASS = config_entries.CONN_CLASS_CLOUD_POLL
|
||||||
|
|
||||||
|
async def async_step_user(self, user_input=None):
|
||||||
|
"""Handle the initial step."""
|
||||||
|
errors = {}
|
||||||
|
if user_input is not None:
|
||||||
|
|
||||||
|
await self.async_set_unique_id(user_input[CONF_ID])
|
||||||
|
self._abort_if_unique_id_configured()
|
||||||
|
|
||||||
|
websession = aiohttp_client.async_get_clientsession(self.hass)
|
||||||
|
|
||||||
|
data = faadelays.Airport(user_input[CONF_ID], websession)
|
||||||
|
|
||||||
|
try:
|
||||||
|
await data.update()
|
||||||
|
|
||||||
|
except faadelays.InvalidAirport:
|
||||||
|
_LOGGER.error("Airport code %s is invalid", user_input[CONF_ID])
|
||||||
|
errors[CONF_ID] = "invalid_airport"
|
||||||
|
|
||||||
|
except ClientConnectionError:
|
||||||
|
_LOGGER.error("Error connecting to FAA API")
|
||||||
|
errors["base"] = "cannot_connect"
|
||||||
|
|
||||||
|
except Exception as error: # pylint: disable=broad-except
|
||||||
|
_LOGGER.exception("Unexpected exception: %s", error)
|
||||||
|
errors["base"] = "unknown"
|
||||||
|
|
||||||
|
if not errors:
|
||||||
|
_LOGGER.debug(
|
||||||
|
"Creating entry with id: %s, name: %s",
|
||||||
|
user_input[CONF_ID],
|
||||||
|
data.name,
|
||||||
|
)
|
||||||
|
return self.async_create_entry(title=data.name, data=user_input)
|
||||||
|
|
||||||
|
return self.async_show_form(
|
||||||
|
step_id="user", data_schema=DATA_SCHEMA, errors=errors
|
||||||
|
)
|
28
homeassistant/components/faa_delays/const.py
Normal file
28
homeassistant/components/faa_delays/const.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
"""Constants for the FAA Delays integration."""
|
||||||
|
|
||||||
|
from homeassistant.const import ATTR_ICON, ATTR_NAME
|
||||||
|
|
||||||
|
DOMAIN = "faa_delays"
|
||||||
|
|
||||||
|
FAA_BINARY_SENSORS = {
|
||||||
|
"GROUND_DELAY": {
|
||||||
|
ATTR_NAME: "Ground Delay",
|
||||||
|
ATTR_ICON: "mdi:airport",
|
||||||
|
},
|
||||||
|
"GROUND_STOP": {
|
||||||
|
ATTR_NAME: "Ground Stop",
|
||||||
|
ATTR_ICON: "mdi:airport",
|
||||||
|
},
|
||||||
|
"DEPART_DELAY": {
|
||||||
|
ATTR_NAME: "Departure Delay",
|
||||||
|
ATTR_ICON: "mdi:airplane-takeoff",
|
||||||
|
},
|
||||||
|
"ARRIVE_DELAY": {
|
||||||
|
ATTR_NAME: "Arrival Delay",
|
||||||
|
ATTR_ICON: "mdi:airplane-landing",
|
||||||
|
},
|
||||||
|
"CLOSURE": {
|
||||||
|
ATTR_NAME: "Closure",
|
||||||
|
ATTR_ICON: "mdi:airplane:off",
|
||||||
|
},
|
||||||
|
}
|
8
homeassistant/components/faa_delays/manifest.json
Normal file
8
homeassistant/components/faa_delays/manifest.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"domain": "faa_delays",
|
||||||
|
"name": "FAA Delays",
|
||||||
|
"config_flow": true,
|
||||||
|
"documentation": "https://www.home-assistant.io/integrations/faadelays",
|
||||||
|
"requirements": ["faadelays==0.0.6"],
|
||||||
|
"codeowners": ["@ntilley905"]
|
||||||
|
}
|
21
homeassistant/components/faa_delays/strings.json
Normal file
21
homeassistant/components/faa_delays/strings.json
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"step": {
|
||||||
|
"user": {
|
||||||
|
"title": "FAA Delays",
|
||||||
|
"description": "Enter a US Airport Code in IATA Format",
|
||||||
|
"data": {
|
||||||
|
"id": "Airport"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"invalid_airport": "Airport code is not valid",
|
||||||
|
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
|
||||||
|
"unknown": "[%key:common::config_flow::error::unknown%]"
|
||||||
|
},
|
||||||
|
"abort": {
|
||||||
|
"already_configured": "This airport is already configured."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
homeassistant/components/faa_delays/translations/en.json
Normal file
19
homeassistant/components/faa_delays/translations/en.json
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"abort": {
|
||||||
|
"already_configured": "This airport is already configured."
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"invalid_airport": "Airport code is not valid"
|
||||||
|
},
|
||||||
|
"step": {
|
||||||
|
"user": {
|
||||||
|
"title": "FAA Delays",
|
||||||
|
"description": "Enter a US Airport Code in IATA Format",
|
||||||
|
"data": {
|
||||||
|
"id": "Airport"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -64,6 +64,7 @@ FLOWS = [
|
|||||||
"enocean",
|
"enocean",
|
||||||
"epson",
|
"epson",
|
||||||
"esphome",
|
"esphome",
|
||||||
|
"faa_delays",
|
||||||
"fireservicerota",
|
"fireservicerota",
|
||||||
"flick_electric",
|
"flick_electric",
|
||||||
"flo",
|
"flo",
|
||||||
|
@ -574,6 +574,9 @@ eternalegypt==0.0.12
|
|||||||
# homeassistant.components.evohome
|
# homeassistant.components.evohome
|
||||||
evohome-async==0.3.5.post1
|
evohome-async==0.3.5.post1
|
||||||
|
|
||||||
|
# homeassistant.components.faa_delays
|
||||||
|
faadelays==0.0.6
|
||||||
|
|
||||||
# homeassistant.components.dlib_face_detect
|
# homeassistant.components.dlib_face_detect
|
||||||
# homeassistant.components.dlib_face_identify
|
# homeassistant.components.dlib_face_identify
|
||||||
# face_recognition==1.2.3
|
# face_recognition==1.2.3
|
||||||
|
@ -302,6 +302,9 @@ ephem==3.7.7.0
|
|||||||
# homeassistant.components.epson
|
# homeassistant.components.epson
|
||||||
epson-projector==0.2.3
|
epson-projector==0.2.3
|
||||||
|
|
||||||
|
# homeassistant.components.faa_delays
|
||||||
|
faadelays==0.0.6
|
||||||
|
|
||||||
# homeassistant.components.feedreader
|
# homeassistant.components.feedreader
|
||||||
feedparser==6.0.2
|
feedparser==6.0.2
|
||||||
|
|
||||||
|
1
tests/components/faa_delays/__init__.py
Normal file
1
tests/components/faa_delays/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
"""Tests for the FAA Delays integration."""
|
120
tests/components/faa_delays/test_config_flow.py
Normal file
120
tests/components/faa_delays/test_config_flow.py
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
"""Test the FAA Delays config flow."""
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from aiohttp import ClientConnectionError
|
||||||
|
import faadelays
|
||||||
|
|
||||||
|
from homeassistant import config_entries, data_entry_flow, setup
|
||||||
|
from homeassistant.components.faa_delays.const import DOMAIN
|
||||||
|
from homeassistant.const import CONF_ID
|
||||||
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
|
|
||||||
|
async def mock_valid_airport(self, *args, **kwargs):
|
||||||
|
"""Return a valid airport."""
|
||||||
|
self.name = "Test airport"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_form(hass):
|
||||||
|
"""Test we get the form."""
|
||||||
|
await setup.async_setup_component(hass, "persistent_notification", {})
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||||
|
)
|
||||||
|
assert result["type"] == "form"
|
||||||
|
assert result["errors"] == {}
|
||||||
|
|
||||||
|
with patch.object(faadelays.Airport, "update", new=mock_valid_airport), patch(
|
||||||
|
"homeassistant.components.faa_delays.async_setup", return_value=True
|
||||||
|
) as mock_setup, patch(
|
||||||
|
"homeassistant.components.faa_delays.async_setup_entry",
|
||||||
|
return_value=True,
|
||||||
|
) as mock_setup_entry:
|
||||||
|
result2 = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
{
|
||||||
|
"id": "test",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result2["type"] == "create_entry"
|
||||||
|
assert result2["title"] == "Test airport"
|
||||||
|
assert result2["data"] == {
|
||||||
|
"id": "test",
|
||||||
|
}
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert len(mock_setup.mock_calls) == 1
|
||||||
|
assert len(mock_setup_entry.mock_calls) == 1
|
||||||
|
|
||||||
|
|
||||||
|
async def test_duplicate_error(hass):
|
||||||
|
"""Test that we handle a duplicate configuration."""
|
||||||
|
conf = {CONF_ID: "test"}
|
||||||
|
|
||||||
|
MockConfigEntry(domain=DOMAIN, unique_id="test", data=conf).add_to_hass(hass)
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": config_entries.SOURCE_USER}, data=conf
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
||||||
|
assert result["reason"] == "already_configured"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_form_invalid_airport(hass):
|
||||||
|
"""Test we handle invalid airport."""
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||||
|
)
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"faadelays.Airport.update",
|
||||||
|
side_effect=faadelays.InvalidAirport,
|
||||||
|
):
|
||||||
|
result2 = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
{
|
||||||
|
"id": "test",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result2["type"] == "form"
|
||||||
|
assert result2["errors"] == {CONF_ID: "invalid_airport"}
|
||||||
|
|
||||||
|
|
||||||
|
async def test_form_cannot_connect(hass):
|
||||||
|
"""Test we handle a connection error."""
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||||
|
)
|
||||||
|
|
||||||
|
with patch("faadelays.Airport.update", side_effect=ClientConnectionError):
|
||||||
|
result2 = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
{
|
||||||
|
"id": "test",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result2["type"] == "form"
|
||||||
|
assert result2["errors"] == {"base": "cannot_connect"}
|
||||||
|
|
||||||
|
|
||||||
|
async def test_form_unexpected_exception(hass):
|
||||||
|
"""Test we handle an unexpected exception."""
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||||
|
)
|
||||||
|
|
||||||
|
with patch("faadelays.Airport.update", side_effect=HomeAssistantError):
|
||||||
|
result2 = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
{
|
||||||
|
"id": "test",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result2["type"] == "form"
|
||||||
|
assert result2["errors"] == {"base": "unknown"}
|
Loading…
x
Reference in New Issue
Block a user