Add Avri config flow (#34288)
* Add config flow to Avri integration * Add config flow validation * Update .coveragerc * Start adding config flow tests * Fix failing test * Fix pylint * Update homeassistant/components/avri/config_flow.py Co-authored-by: J. Nick Koston <nick@koston.org> * Update homeassistant/components/avri/config_flow.py Co-authored-by: J. Nick Koston <nick@koston.org> * Fix import order * Code review comments * Update homeassistant/components/avri/sensor.py Co-authored-by: J. Nick Koston <nick@koston.org> * Remove device information Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
parent
14f5cab71d
commit
d73a4e1ed5
15 changed files with 344 additions and 47 deletions
|
@ -68,6 +68,7 @@ omit =
|
||||||
homeassistant/components/aurora_abb_powerone/sensor.py
|
homeassistant/components/aurora_abb_powerone/sensor.py
|
||||||
homeassistant/components/avea/light.py
|
homeassistant/components/avea/light.py
|
||||||
homeassistant/components/avion/light.py
|
homeassistant/components/avion/light.py
|
||||||
|
homeassistant/components/avri/const.py
|
||||||
homeassistant/components/avri/sensor.py
|
homeassistant/components/avri/sensor.py
|
||||||
homeassistant/components/azure_event_hub/*
|
homeassistant/components/azure_event_hub/*
|
||||||
homeassistant/components/azure_service_bus/*
|
homeassistant/components/azure_service_bus/*
|
||||||
|
|
24
homeassistant/components/avri/.translations/en.json
Normal file
24
homeassistant/components/avri/.translations/en.json
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"abort": {
|
||||||
|
"already_configured": "This address is already configured."
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"invalid_country_code": "Unknown 2 letter country code.",
|
||||||
|
"invalid_house_number": "Invalid house number."
|
||||||
|
},
|
||||||
|
"step": {
|
||||||
|
"user": {
|
||||||
|
"data": {
|
||||||
|
"country_code": "2 Letter country code",
|
||||||
|
"house_number": "House number",
|
||||||
|
"house_number_extension": "House number extension",
|
||||||
|
"zip_code": "Zip code"
|
||||||
|
},
|
||||||
|
"description": "Enter your address",
|
||||||
|
"title": "Avri"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"title": "Avri"
|
||||||
|
}
|
24
homeassistant/components/avri/.translations/nl.json
Normal file
24
homeassistant/components/avri/.translations/nl.json
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"abort": {
|
||||||
|
"already_configured": "Dit adres is reeds geconfigureerd."
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"invalid_country_code": "Onbekende landcode",
|
||||||
|
"invalid_house_number": "Ongeldig huisnummer."
|
||||||
|
},
|
||||||
|
"step": {
|
||||||
|
"user": {
|
||||||
|
"data": {
|
||||||
|
"country_code": "2 Letter landcode",
|
||||||
|
"house_number": "Huisnummer",
|
||||||
|
"house_number_extension": "Huisnummer toevoeging",
|
||||||
|
"zip_code": "Postcode"
|
||||||
|
},
|
||||||
|
"description": "Vul je adres in.",
|
||||||
|
"title": "Avri"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"title": "Avri"
|
||||||
|
}
|
|
@ -1 +1,63 @@
|
||||||
"""The avri component."""
|
"""The avri component."""
|
||||||
|
import asyncio
|
||||||
|
from datetime import timedelta
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from avri.api import Avri
|
||||||
|
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
|
from .const import (
|
||||||
|
CONF_COUNTRY_CODE,
|
||||||
|
CONF_HOUSE_NUMBER,
|
||||||
|
CONF_HOUSE_NUMBER_EXTENSION,
|
||||||
|
CONF_ZIP_CODE,
|
||||||
|
DOMAIN,
|
||||||
|
)
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
PLATFORMS = ["sensor"]
|
||||||
|
SCAN_INTERVAL = timedelta(hours=4)
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup(hass: HomeAssistant, config: dict):
|
||||||
|
"""Set up the Avri component."""
|
||||||
|
hass.data[DOMAIN] = {}
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
||||||
|
"""Set up Avri from a config entry."""
|
||||||
|
client = Avri(
|
||||||
|
postal_code=entry.data[CONF_ZIP_CODE],
|
||||||
|
house_nr=entry.data[CONF_HOUSE_NUMBER],
|
||||||
|
house_nr_extension=entry.data.get(CONF_HOUSE_NUMBER_EXTENSION),
|
||||||
|
country_code=entry.data[CONF_COUNTRY_CODE],
|
||||||
|
)
|
||||||
|
|
||||||
|
hass.data[DOMAIN][entry.entry_id] = client
|
||||||
|
|
||||||
|
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
|
||||||
|
|
74
homeassistant/components/avri/config_flow.py
Normal file
74
homeassistant/components/avri/config_flow.py
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
"""Config flow for Avri component."""
|
||||||
|
import pycountry
|
||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
from homeassistant import config_entries
|
||||||
|
from homeassistant.const import CONF_ID
|
||||||
|
|
||||||
|
from .const import (
|
||||||
|
CONF_COUNTRY_CODE,
|
||||||
|
CONF_HOUSE_NUMBER,
|
||||||
|
CONF_HOUSE_NUMBER_EXTENSION,
|
||||||
|
CONF_ZIP_CODE,
|
||||||
|
DEFAULT_COUNTRY_CODE,
|
||||||
|
)
|
||||||
|
from .const import DOMAIN # pylint:disable=unused-import
|
||||||
|
|
||||||
|
DATA_SCHEMA = vol.Schema(
|
||||||
|
{
|
||||||
|
vol.Required(CONF_ZIP_CODE): str,
|
||||||
|
vol.Required(CONF_HOUSE_NUMBER): int,
|
||||||
|
vol.Optional(CONF_HOUSE_NUMBER_EXTENSION): str,
|
||||||
|
vol.Optional(CONF_COUNTRY_CODE, default=DEFAULT_COUNTRY_CODE): str,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class AvriConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
|
"""Avri config flow."""
|
||||||
|
|
||||||
|
VERSION = 1
|
||||||
|
|
||||||
|
async def _show_setup_form(self, errors=None):
|
||||||
|
"""Show the setup form to the user."""
|
||||||
|
return self.async_show_form(
|
||||||
|
step_id="user", data_schema=DATA_SCHEMA, errors=errors or {},
|
||||||
|
)
|
||||||
|
|
||||||
|
async def async_step_user(self, user_input=None):
|
||||||
|
"""Handle the initial step."""
|
||||||
|
if user_input is None:
|
||||||
|
return await self._show_setup_form()
|
||||||
|
|
||||||
|
zip_code = user_input[CONF_ZIP_CODE].replace(" ", "").upper()
|
||||||
|
|
||||||
|
errors = {}
|
||||||
|
if user_input[CONF_HOUSE_NUMBER] <= 0:
|
||||||
|
errors[CONF_HOUSE_NUMBER] = "invalid_house_number"
|
||||||
|
return await self._show_setup_form(errors)
|
||||||
|
if not pycountry.countries.get(alpha_2=user_input[CONF_COUNTRY_CODE]):
|
||||||
|
errors[CONF_COUNTRY_CODE] = "invalid_country_code"
|
||||||
|
return await self._show_setup_form(errors)
|
||||||
|
|
||||||
|
unique_id = (
|
||||||
|
f"{zip_code}"
|
||||||
|
f" "
|
||||||
|
f"{user_input[CONF_HOUSE_NUMBER]}"
|
||||||
|
f'{user_input.get(CONF_HOUSE_NUMBER_EXTENSION, "")}'
|
||||||
|
)
|
||||||
|
|
||||||
|
await self.async_set_unique_id(unique_id)
|
||||||
|
self._abort_if_unique_id_configured()
|
||||||
|
|
||||||
|
return self.async_create_entry(
|
||||||
|
title=unique_id,
|
||||||
|
data={
|
||||||
|
CONF_ID: unique_id,
|
||||||
|
CONF_ZIP_CODE: zip_code,
|
||||||
|
CONF_HOUSE_NUMBER: user_input[CONF_HOUSE_NUMBER],
|
||||||
|
CONF_HOUSE_NUMBER_EXTENSION: user_input.get(
|
||||||
|
CONF_HOUSE_NUMBER_EXTENSION, ""
|
||||||
|
),
|
||||||
|
CONF_COUNTRY_CODE: user_input[CONF_COUNTRY_CODE],
|
||||||
|
},
|
||||||
|
)
|
8
homeassistant/components/avri/const.py
Normal file
8
homeassistant/components/avri/const.py
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
"""Constants for the Avri integration."""
|
||||||
|
CONF_COUNTRY_CODE = "country_code"
|
||||||
|
CONF_ZIP_CODE = "zip_code"
|
||||||
|
CONF_HOUSE_NUMBER = "house_number"
|
||||||
|
CONF_HOUSE_NUMBER_EXTENSION = "house_number_extension"
|
||||||
|
DOMAIN = "avri"
|
||||||
|
ICON = "mdi:trash-can-outline"
|
||||||
|
DEFAULT_COUNTRY_CODE = "NL"
|
|
@ -2,6 +2,12 @@
|
||||||
"domain": "avri",
|
"domain": "avri",
|
||||||
"name": "Avri",
|
"name": "Avri",
|
||||||
"documentation": "https://www.home-assistant.io/integrations/avri",
|
"documentation": "https://www.home-assistant.io/integrations/avri",
|
||||||
"requirements": ["avri-api==0.1.7"],
|
"requirements": [
|
||||||
"codeowners": ["@timvancann"]
|
"avri-api==0.1.7",
|
||||||
}
|
"pycountry==19.8.18"
|
||||||
|
],
|
||||||
|
"codeowners": [
|
||||||
|
"@timvancann"
|
||||||
|
],
|
||||||
|
"config_flow": true
|
||||||
|
}
|
|
@ -1,45 +1,25 @@
|
||||||
"""Support for Avri waste curbside collection pickup."""
|
"""Support for Avri waste curbside collection pickup."""
|
||||||
from datetime import timedelta
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from avri.api import Avri, AvriException
|
from avri.api import Avri, AvriException
|
||||||
import voluptuous as vol
|
|
||||||
|
|
||||||
from homeassistant.components.sensor import PLATFORM_SCHEMA
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_NAME
|
from homeassistant.const import CONF_ID, DEVICE_CLASS_TIMESTAMP
|
||||||
from homeassistant.exceptions import PlatformNotReady
|
from homeassistant.exceptions import PlatformNotReady
|
||||||
import homeassistant.helpers.config_validation as cv
|
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
|
from homeassistant.helpers.typing import HomeAssistantType
|
||||||
|
|
||||||
|
from .const import DOMAIN, ICON
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
CONF_COUNTRY_CODE = "country_code"
|
|
||||||
CONF_ZIP_CODE = "zip_code"
|
|
||||||
CONF_HOUSE_NUMBER = "house_number"
|
|
||||||
CONF_HOUSE_NUMBER_EXTENSION = "house_number_extension"
|
|
||||||
DEFAULT_NAME = "avri"
|
|
||||||
ICON = "mdi:trash-can-outline"
|
|
||||||
SCAN_INTERVAL = timedelta(hours=4)
|
|
||||||
DEFAULT_COUNTRY_CODE = "NL"
|
|
||||||
|
|
||||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
|
||||||
{
|
|
||||||
vol.Required(CONF_ZIP_CODE): cv.string,
|
|
||||||
vol.Required(CONF_HOUSE_NUMBER): cv.positive_int,
|
|
||||||
vol.Optional(CONF_HOUSE_NUMBER_EXTENSION): cv.string,
|
|
||||||
vol.Optional(CONF_COUNTRY_CODE, default=DEFAULT_COUNTRY_CODE): cv.string,
|
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def setup_platform(hass, config, add_entities, discovery_info=None):
|
async def async_setup_entry(
|
||||||
|
hass: HomeAssistantType, entry: ConfigEntry, async_add_entities
|
||||||
|
) -> None:
|
||||||
"""Set up the Avri Waste platform."""
|
"""Set up the Avri Waste platform."""
|
||||||
client = Avri(
|
client = hass.data[DOMAIN][entry.entry_id]
|
||||||
postal_code=config[CONF_ZIP_CODE],
|
integration_id = entry.data[CONF_ID]
|
||||||
house_nr=config[CONF_HOUSE_NUMBER],
|
|
||||||
house_nr_extension=config.get(CONF_HOUSE_NUMBER_EXTENSION),
|
|
||||||
country_code=config[CONF_COUNTRY_CODE],
|
|
||||||
)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
each_upcoming = client.upcoming_of_each()
|
each_upcoming = client.upcoming_of_each()
|
||||||
|
@ -47,22 +27,23 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
raise PlatformNotReady from ex
|
raise PlatformNotReady from ex
|
||||||
else:
|
else:
|
||||||
entities = [
|
entities = [
|
||||||
AvriWasteUpcoming(config[CONF_NAME], client, upcoming.name)
|
AvriWasteUpcoming(client, upcoming.name, integration_id)
|
||||||
for upcoming in each_upcoming
|
for upcoming in each_upcoming
|
||||||
]
|
]
|
||||||
add_entities(entities, True)
|
async_add_entities(entities, True)
|
||||||
|
|
||||||
|
|
||||||
class AvriWasteUpcoming(Entity):
|
class AvriWasteUpcoming(Entity):
|
||||||
"""Avri Waste Sensor."""
|
"""Avri Waste Sensor."""
|
||||||
|
|
||||||
def __init__(self, name: str, client: Avri, waste_type: str):
|
def __init__(self, client: Avri, waste_type: str, integration_id: str):
|
||||||
"""Initialize the sensor."""
|
"""Initialize the sensor."""
|
||||||
self._waste_type = waste_type
|
self._waste_type = waste_type
|
||||||
self._name = f"{name}_{self._waste_type}"
|
self._name = f"{self._waste_type}".title()
|
||||||
self._state = None
|
self._state = None
|
||||||
self._client = client
|
self._client = client
|
||||||
self._state_available = False
|
self._state_available = False
|
||||||
|
self._integration_id = integration_id
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
|
@ -72,13 +53,7 @@ class AvriWasteUpcoming(Entity):
|
||||||
@property
|
@property
|
||||||
def unique_id(self) -> str:
|
def unique_id(self) -> str:
|
||||||
"""Return a unique ID."""
|
"""Return a unique ID."""
|
||||||
return (
|
return (f"{self._integration_id}" f"-{self._waste_type}").replace(" ", "")
|
||||||
f"{self._waste_type}"
|
|
||||||
f"-{self._client.country_code}"
|
|
||||||
f"-{self._client.postal_code}"
|
|
||||||
f"-{self._client.house_nr}"
|
|
||||||
f"-{self._client.house_nr_extension}"
|
|
||||||
)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def state(self):
|
def state(self):
|
||||||
|
@ -90,13 +65,21 @@ class AvriWasteUpcoming(Entity):
|
||||||
"""Return True if entity is available."""
|
"""Return True if entity is available."""
|
||||||
return self._state_available
|
return self._state_available
|
||||||
|
|
||||||
|
@property
|
||||||
|
def device_class(self):
|
||||||
|
"""Return the device class of the sensor."""
|
||||||
|
return DEVICE_CLASS_TIMESTAMP
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def icon(self):
|
def icon(self):
|
||||||
"""Icon to use in the frontend."""
|
"""Icon to use in the frontend."""
|
||||||
return ICON
|
return ICON
|
||||||
|
|
||||||
def update(self):
|
async def async_update(self):
|
||||||
"""Update device state."""
|
"""Update the data."""
|
||||||
|
if not self.enabled:
|
||||||
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
pickup_events = self._client.upcoming_of_each()
|
pickup_events = self._client.upcoming_of_each()
|
||||||
except AvriException as ex:
|
except AvriException as ex:
|
||||||
|
|
24
homeassistant/components/avri/strings.json
Normal file
24
homeassistant/components/avri/strings.json
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"title": "Avri",
|
||||||
|
"config": {
|
||||||
|
"abort": {
|
||||||
|
"already_configured": "This address is already configured."
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"invalid_house_number": "Invalid house number.",
|
||||||
|
"invalid_country_code": "Unknown 2 letter country code."
|
||||||
|
},
|
||||||
|
"step": {
|
||||||
|
"user": {
|
||||||
|
"data": {
|
||||||
|
"zip_code": "Zip code",
|
||||||
|
"house_number": "House number",
|
||||||
|
"house_number_extension": "House number extension",
|
||||||
|
"country_code": "2 Letter country code"
|
||||||
|
},
|
||||||
|
"description": "Enter your address",
|
||||||
|
"title": "Avri"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,6 +17,7 @@ FLOWS = [
|
||||||
"ambient_station",
|
"ambient_station",
|
||||||
"atag",
|
"atag",
|
||||||
"august",
|
"august",
|
||||||
|
"avri",
|
||||||
"axis",
|
"axis",
|
||||||
"blebox",
|
"blebox",
|
||||||
"blink",
|
"blink",
|
||||||
|
|
|
@ -1259,6 +1259,9 @@ pycomfoconnect==0.3
|
||||||
# homeassistant.components.coolmaster
|
# homeassistant.components.coolmaster
|
||||||
pycoolmasternet==0.0.4
|
pycoolmasternet==0.0.4
|
||||||
|
|
||||||
|
# homeassistant.components.avri
|
||||||
|
pycountry==19.8.18
|
||||||
|
|
||||||
# homeassistant.components.microsoft
|
# homeassistant.components.microsoft
|
||||||
pycsspeechtts==1.0.3
|
pycsspeechtts==1.0.3
|
||||||
|
|
||||||
|
|
|
@ -146,6 +146,9 @@ async-upnp-client==0.14.13
|
||||||
# homeassistant.components.stream
|
# homeassistant.components.stream
|
||||||
av==8.0.2
|
av==8.0.2
|
||||||
|
|
||||||
|
# homeassistant.components.avri
|
||||||
|
avri-api==0.1.7
|
||||||
|
|
||||||
# homeassistant.components.axis
|
# homeassistant.components.axis
|
||||||
axis==29
|
axis==29
|
||||||
|
|
||||||
|
@ -544,6 +547,9 @@ pychromecast==6.0.0
|
||||||
# homeassistant.components.coolmaster
|
# homeassistant.components.coolmaster
|
||||||
pycoolmasternet==0.0.4
|
pycoolmasternet==0.0.4
|
||||||
|
|
||||||
|
# homeassistant.components.avri
|
||||||
|
pycountry==19.8.18
|
||||||
|
|
||||||
# homeassistant.components.daikin
|
# homeassistant.components.daikin
|
||||||
pydaikin==2.1.1
|
pydaikin==2.1.1
|
||||||
|
|
||||||
|
|
|
@ -8,4 +8,4 @@ cd "$(dirname "$0")/.."
|
||||||
script/bootstrap
|
script/bootstrap
|
||||||
|
|
||||||
pre-commit install
|
pre-commit install
|
||||||
pip3 install -e .
|
pip install -e .
|
||||||
|
|
1
tests/components/avri/__init__.py
Normal file
1
tests/components/avri/__init__.py
Normal file
|
@ -0,0 +1 @@
|
||||||
|
"""Tests for the Avri integration."""
|
80
tests/components/avri/test_config_flow.py
Normal file
80
tests/components/avri/test_config_flow.py
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
"""Test the Avri config flow."""
|
||||||
|
from asynctest import patch
|
||||||
|
|
||||||
|
from homeassistant import config_entries, setup
|
||||||
|
from homeassistant.components.avri.const import DOMAIN
|
||||||
|
|
||||||
|
|
||||||
|
async def test_form(hass):
|
||||||
|
"""Test we get the form."""
|
||||||
|
await setup.async_setup_component(hass, "avri", {})
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||||
|
)
|
||||||
|
assert result["type"] == "form"
|
||||||
|
assert result["errors"] == {}
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.avri.async_setup_entry", return_value=True,
|
||||||
|
) as mock_setup_entry:
|
||||||
|
result2 = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
{
|
||||||
|
"zip_code": "1234AB",
|
||||||
|
"house_number": 42,
|
||||||
|
"house_number_extension": "",
|
||||||
|
"country_code": "NL",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result2["type"] == "create_entry"
|
||||||
|
assert result2["title"] == "1234AB 42"
|
||||||
|
assert result2["data"] == {
|
||||||
|
"id": "1234AB 42",
|
||||||
|
"zip_code": "1234AB",
|
||||||
|
"house_number": 42,
|
||||||
|
"house_number_extension": "",
|
||||||
|
"country_code": "NL",
|
||||||
|
}
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert len(mock_setup_entry.mock_calls) == 1
|
||||||
|
|
||||||
|
|
||||||
|
async def test_form_invalid_house_number(hass):
|
||||||
|
"""Test we handle invalid house number."""
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||||
|
)
|
||||||
|
|
||||||
|
result2 = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
{
|
||||||
|
"zip_code": "1234AB",
|
||||||
|
"house_number": -1,
|
||||||
|
"house_number_extension": "",
|
||||||
|
"country_code": "NL",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result2["type"] == "form"
|
||||||
|
assert result2["errors"] == {"house_number": "invalid_house_number"}
|
||||||
|
|
||||||
|
|
||||||
|
async def test_form_invalid_country_code(hass):
|
||||||
|
"""Test we handle invalid county code."""
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||||
|
)
|
||||||
|
|
||||||
|
result2 = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
{
|
||||||
|
"zip_code": "1234AB",
|
||||||
|
"house_number": 42,
|
||||||
|
"house_number_extension": "",
|
||||||
|
"country_code": "foo",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result2["type"] == "form"
|
||||||
|
assert result2["errors"] == {"country_code": "invalid_country_code"}
|
Loading…
Add table
Add a link
Reference in a new issue