mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 20:57:21 +00:00
Add Aussie Broadband integration (#53552)
This commit is contained in:
parent
1f00ded33a
commit
3dd7ec6856
@ -91,6 +91,8 @@ homeassistant/components/aurora/* @djtimca
|
|||||||
tests/components/aurora/* @djtimca
|
tests/components/aurora/* @djtimca
|
||||||
homeassistant/components/aurora_abb_powerone/* @davet2001
|
homeassistant/components/aurora_abb_powerone/* @davet2001
|
||||||
tests/components/aurora_abb_powerone/* @davet2001
|
tests/components/aurora_abb_powerone/* @davet2001
|
||||||
|
homeassistant/components/aussie_broadband/* @nickw444 @Bre77
|
||||||
|
tests/components/aussie_broadband/* @nickw444 @Bre77
|
||||||
homeassistant/components/auth/* @home-assistant/core
|
homeassistant/components/auth/* @home-assistant/core
|
||||||
tests/components/auth/* @home-assistant/core
|
tests/components/auth/* @home-assistant/core
|
||||||
homeassistant/components/automation/* @home-assistant/core
|
homeassistant/components/automation/* @home-assistant/core
|
||||||
|
84
homeassistant/components/aussie_broadband/__init__.py
Normal file
84
homeassistant/components/aussie_broadband/__init__.py
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
"""The Aussie Broadband integration."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from datetime import timedelta
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from aiohttp import ClientError
|
||||||
|
from aussiebb.asyncio import AussieBB, AuthenticationException
|
||||||
|
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME, Platform
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
|
||||||
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||||
|
|
||||||
|
from .const import CONF_SERVICES, DEFAULT_UPDATE_INTERVAL, DOMAIN, SERVICE_ID
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
PLATFORMS = [Platform.SENSOR]
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
|
"""Set up Aussie Broadband from a config entry."""
|
||||||
|
# Login to the Aussie Broadband API and retrieve the current service list
|
||||||
|
client = AussieBB(
|
||||||
|
entry.data[CONF_USERNAME],
|
||||||
|
entry.data[CONF_PASSWORD],
|
||||||
|
async_get_clientsession(hass),
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
await client.login()
|
||||||
|
all_services = await client.get_services()
|
||||||
|
except AuthenticationException as exc:
|
||||||
|
raise ConfigEntryAuthFailed() from exc
|
||||||
|
except ClientError as exc:
|
||||||
|
raise ConfigEntryNotReady() from exc
|
||||||
|
|
||||||
|
# Filter the service list to those that are enabled in options
|
||||||
|
services = [
|
||||||
|
s for s in all_services if str(s["service_id"]) in entry.options[CONF_SERVICES]
|
||||||
|
]
|
||||||
|
|
||||||
|
# Create an appropriate refresh function
|
||||||
|
def update_data_factory(service_id):
|
||||||
|
async def async_update_data():
|
||||||
|
return await client.get_usage(service_id)
|
||||||
|
|
||||||
|
return async_update_data
|
||||||
|
|
||||||
|
# Initiate a Data Update Coordinator for each service
|
||||||
|
for service in services:
|
||||||
|
service["coordinator"] = DataUpdateCoordinator(
|
||||||
|
hass,
|
||||||
|
_LOGGER,
|
||||||
|
name=service["service_id"],
|
||||||
|
update_interval=timedelta(minutes=DEFAULT_UPDATE_INTERVAL),
|
||||||
|
update_method=update_data_factory(service[SERVICE_ID]),
|
||||||
|
)
|
||||||
|
await service["coordinator"].async_config_entry_first_refresh()
|
||||||
|
|
||||||
|
# Setup the integration
|
||||||
|
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = {
|
||||||
|
"client": client,
|
||||||
|
"services": services,
|
||||||
|
}
|
||||||
|
hass.config_entries.async_setup_platforms(entry, PLATFORMS)
|
||||||
|
entry.async_on_unload(entry.add_update_listener(update_listener))
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
async def update_listener(hass: HomeAssistant, entry: ConfigEntry):
|
||||||
|
"""Reload to update options."""
|
||||||
|
await hass.config_entries.async_reload(entry.entry_id)
|
||||||
|
|
||||||
|
|
||||||
|
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
|
"""Unload the config entry."""
|
||||||
|
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
||||||
|
if unload_ok:
|
||||||
|
hass.data[DOMAIN].pop(entry.entry_id)
|
||||||
|
|
||||||
|
return unload_ok
|
184
homeassistant/components/aussie_broadband/config_flow.py
Normal file
184
homeassistant/components/aussie_broadband/config_flow.py
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
"""Config flow for Aussie Broadband integration."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from aiohttp import ClientError
|
||||||
|
from aussiebb.asyncio import AussieBB, AuthenticationException
|
||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
from homeassistant import config_entries
|
||||||
|
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
|
||||||
|
from homeassistant.core import callback
|
||||||
|
from homeassistant.data_entry_flow import FlowResult
|
||||||
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
|
||||||
|
from .const import CONF_SERVICES, DOMAIN, SERVICE_ID
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
|
"""Handle a config flow for Aussie Broadband."""
|
||||||
|
|
||||||
|
VERSION = 1
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
"""Initialize the config flow."""
|
||||||
|
self.data: dict = {}
|
||||||
|
self.options: dict = {CONF_SERVICES: []}
|
||||||
|
self.services: list[dict[str]] = []
|
||||||
|
self.client: AussieBB | None = None
|
||||||
|
self._reauth_username: str | None = None
|
||||||
|
|
||||||
|
async def async_auth(self, user_input: dict[str, str]) -> dict[str, str] | None:
|
||||||
|
"""Reusable Auth Helper."""
|
||||||
|
self.client = AussieBB(
|
||||||
|
user_input[CONF_USERNAME],
|
||||||
|
user_input[CONF_PASSWORD],
|
||||||
|
async_get_clientsession(self.hass),
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
await self.client.login()
|
||||||
|
return None
|
||||||
|
except AuthenticationException:
|
||||||
|
return {"base": "invalid_auth"}
|
||||||
|
except ClientError:
|
||||||
|
return {"base": "cannot_connect"}
|
||||||
|
|
||||||
|
async def async_step_user(
|
||||||
|
self, user_input: dict[str, Any] | None = None
|
||||||
|
) -> FlowResult:
|
||||||
|
"""Handle the initial step."""
|
||||||
|
errors: dict[str, str] | None = None
|
||||||
|
if user_input is not None:
|
||||||
|
if not (errors := await self.async_auth(user_input)):
|
||||||
|
await self.async_set_unique_id(user_input[CONF_USERNAME].lower())
|
||||||
|
self._abort_if_unique_id_configured()
|
||||||
|
|
||||||
|
self.data = user_input
|
||||||
|
self.services = await self.client.get_services() # type: ignore[union-attr]
|
||||||
|
|
||||||
|
if not self.services:
|
||||||
|
return self.async_abort(reason="no_services_found")
|
||||||
|
|
||||||
|
if len(self.services) == 1:
|
||||||
|
return self.async_create_entry(
|
||||||
|
title=self.data[CONF_USERNAME],
|
||||||
|
data=self.data,
|
||||||
|
options={CONF_SERVICES: [str(self.services[0][SERVICE_ID])]},
|
||||||
|
)
|
||||||
|
|
||||||
|
# Account has more than one service, select service to add
|
||||||
|
return await self.async_step_service()
|
||||||
|
|
||||||
|
return self.async_show_form(
|
||||||
|
step_id="user",
|
||||||
|
data_schema=vol.Schema(
|
||||||
|
{
|
||||||
|
vol.Required(CONF_USERNAME): str,
|
||||||
|
vol.Required(CONF_PASSWORD): str,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
errors=errors,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def async_step_service(
|
||||||
|
self, user_input: dict[str, Any] | None = None
|
||||||
|
) -> FlowResult:
|
||||||
|
"""Handle the optional service selection step."""
|
||||||
|
if user_input is not None:
|
||||||
|
return self.async_create_entry(
|
||||||
|
title=self.data[CONF_USERNAME], data=self.data, options=user_input
|
||||||
|
)
|
||||||
|
|
||||||
|
service_options = {str(s[SERVICE_ID]): s["description"] for s in self.services}
|
||||||
|
return self.async_show_form(
|
||||||
|
step_id="service",
|
||||||
|
data_schema=vol.Schema(
|
||||||
|
{
|
||||||
|
vol.Required(
|
||||||
|
CONF_SERVICES, default=list(service_options.keys())
|
||||||
|
): cv.multi_select(service_options)
|
||||||
|
}
|
||||||
|
),
|
||||||
|
errors=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def async_step_reauth(
|
||||||
|
self, user_input: dict[str, Any] | None = None
|
||||||
|
) -> FlowResult:
|
||||||
|
"""Handle reauth."""
|
||||||
|
errors: dict[str, str] | None = None
|
||||||
|
if user_input and user_input.get(CONF_USERNAME):
|
||||||
|
self._reauth_username = user_input[CONF_USERNAME]
|
||||||
|
|
||||||
|
elif self._reauth_username and user_input and user_input.get(CONF_PASSWORD):
|
||||||
|
data = {
|
||||||
|
CONF_USERNAME: self._reauth_username,
|
||||||
|
CONF_PASSWORD: user_input[CONF_PASSWORD],
|
||||||
|
}
|
||||||
|
|
||||||
|
if not (errors := await self.async_auth(data)):
|
||||||
|
entry = await self.async_set_unique_id(self._reauth_username.lower())
|
||||||
|
if entry:
|
||||||
|
self.hass.config_entries.async_update_entry(
|
||||||
|
entry,
|
||||||
|
data=data,
|
||||||
|
)
|
||||||
|
await self.hass.config_entries.async_reload(entry.entry_id)
|
||||||
|
return self.async_abort(reason="reauth_successful")
|
||||||
|
return self.async_create_entry(title=self._reauth_username, data=data)
|
||||||
|
|
||||||
|
return self.async_show_form(
|
||||||
|
step_id="reauth",
|
||||||
|
description_placeholders={"username": self._reauth_username},
|
||||||
|
data_schema=vol.Schema(
|
||||||
|
{
|
||||||
|
vol.Required(CONF_PASSWORD): str,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
errors=errors,
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
@callback
|
||||||
|
def async_get_options_flow(
|
||||||
|
config_entry: config_entries.ConfigEntry,
|
||||||
|
) -> config_entries.OptionsFlow:
|
||||||
|
"""Get the options flow for this handler."""
|
||||||
|
return OptionsFlowHandler(config_entry)
|
||||||
|
|
||||||
|
|
||||||
|
class OptionsFlowHandler(config_entries.OptionsFlow):
|
||||||
|
"""Options flow for picking services."""
|
||||||
|
|
||||||
|
def __init__(self, config_entry: config_entries.ConfigEntry) -> None:
|
||||||
|
"""Initialize options flow."""
|
||||||
|
self.config_entry = config_entry
|
||||||
|
|
||||||
|
async def async_step_init(self, user_input=None):
|
||||||
|
"""Manage the options."""
|
||||||
|
if user_input is not None:
|
||||||
|
return self.async_create_entry(title="", data=user_input)
|
||||||
|
|
||||||
|
if self.config_entry.state != config_entries.ConfigEntryState.LOADED:
|
||||||
|
return self.async_abort(reason="unknown")
|
||||||
|
data = self.hass.data[DOMAIN][self.config_entry.entry_id]
|
||||||
|
try:
|
||||||
|
services = await data["client"].get_services()
|
||||||
|
except AuthenticationException:
|
||||||
|
return self.async_abort(reason="invalid_auth")
|
||||||
|
except ClientError:
|
||||||
|
return self.async_abort(reason="cannot_connect")
|
||||||
|
service_options = {str(s[SERVICE_ID]): s["description"] for s in services}
|
||||||
|
return self.async_show_form(
|
||||||
|
step_id="init",
|
||||||
|
data_schema=vol.Schema(
|
||||||
|
{
|
||||||
|
vol.Required(
|
||||||
|
CONF_SERVICES,
|
||||||
|
default=self.config_entry.options.get(CONF_SERVICES),
|
||||||
|
): cv.multi_select(service_options),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
)
|
5
homeassistant/components/aussie_broadband/const.py
Normal file
5
homeassistant/components/aussie_broadband/const.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
"""Constants for the Aussie Broadband integration."""
|
||||||
|
DEFAULT_UPDATE_INTERVAL = 30
|
||||||
|
DOMAIN = "aussie_broadband"
|
||||||
|
SERVICE_ID = "service_id"
|
||||||
|
CONF_SERVICES = "services"
|
14
homeassistant/components/aussie_broadband/manifest.json
Normal file
14
homeassistant/components/aussie_broadband/manifest.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"domain": "aussie_broadband",
|
||||||
|
"name": "Aussie Broadband",
|
||||||
|
"config_flow": true,
|
||||||
|
"documentation": "https://www.home-assistant.io/integrations/aussie_broadband",
|
||||||
|
"requirements": [
|
||||||
|
"pyaussiebb==0.0.9"
|
||||||
|
],
|
||||||
|
"codeowners": [
|
||||||
|
"@nickw444",
|
||||||
|
"@Bre77"
|
||||||
|
],
|
||||||
|
"iot_class": "cloud_polling"
|
||||||
|
}
|
140
homeassistant/components/aussie_broadband/sensor.py
Normal file
140
homeassistant/components/aussie_broadband/sensor.py
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
"""Support for Aussie Broadband metric sensors."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from homeassistant.components.sensor import (
|
||||||
|
SensorEntity,
|
||||||
|
SensorEntityDescription,
|
||||||
|
SensorStateClass,
|
||||||
|
)
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.const import DATA_KILOBYTES, DATA_MEGABYTES, TIME_DAYS
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||||
|
|
||||||
|
from .const import DOMAIN, SERVICE_ID
|
||||||
|
|
||||||
|
SENSOR_DESCRIPTIONS: tuple[SensorEntityDescription, ...] = (
|
||||||
|
# Internet Services sensors
|
||||||
|
SensorEntityDescription(
|
||||||
|
key="usedMb",
|
||||||
|
name="Data Used",
|
||||||
|
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||||
|
native_unit_of_measurement=DATA_MEGABYTES,
|
||||||
|
icon="mdi:network",
|
||||||
|
),
|
||||||
|
SensorEntityDescription(
|
||||||
|
key="downloadedMb",
|
||||||
|
name="Downloaded",
|
||||||
|
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||||
|
native_unit_of_measurement=DATA_MEGABYTES,
|
||||||
|
icon="mdi:download-network",
|
||||||
|
),
|
||||||
|
SensorEntityDescription(
|
||||||
|
key="uploadedMb",
|
||||||
|
name="Uploaded",
|
||||||
|
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||||
|
native_unit_of_measurement=DATA_MEGABYTES,
|
||||||
|
icon="mdi:upload-network",
|
||||||
|
),
|
||||||
|
# Mobile Phone Services sensors
|
||||||
|
SensorEntityDescription(
|
||||||
|
key="national",
|
||||||
|
name="National Calls",
|
||||||
|
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||||
|
icon="mdi:phone",
|
||||||
|
),
|
||||||
|
SensorEntityDescription(
|
||||||
|
key="mobile",
|
||||||
|
name="Mobile Calls",
|
||||||
|
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||||
|
icon="mdi:phone",
|
||||||
|
),
|
||||||
|
SensorEntityDescription(
|
||||||
|
key="international",
|
||||||
|
name="International Calls",
|
||||||
|
entity_registry_enabled_default=False,
|
||||||
|
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||||
|
icon="mdi:phone-plus",
|
||||||
|
),
|
||||||
|
SensorEntityDescription(
|
||||||
|
key="sms",
|
||||||
|
name="SMS Sent",
|
||||||
|
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||||
|
icon="mdi:message-processing",
|
||||||
|
),
|
||||||
|
SensorEntityDescription(
|
||||||
|
key="internet",
|
||||||
|
name="Data Used",
|
||||||
|
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||||
|
native_unit_of_measurement=DATA_KILOBYTES,
|
||||||
|
icon="mdi:network",
|
||||||
|
),
|
||||||
|
SensorEntityDescription(
|
||||||
|
key="voicemail",
|
||||||
|
name="Voicemail Calls",
|
||||||
|
entity_registry_enabled_default=False,
|
||||||
|
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||||
|
icon="mdi:phone",
|
||||||
|
),
|
||||||
|
SensorEntityDescription(
|
||||||
|
key="other",
|
||||||
|
name="Other Calls",
|
||||||
|
entity_registry_enabled_default=False,
|
||||||
|
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||||
|
icon="mdi:phone",
|
||||||
|
),
|
||||||
|
# Generic sensors
|
||||||
|
SensorEntityDescription(
|
||||||
|
key="daysTotal",
|
||||||
|
name="Billing Cycle Length",
|
||||||
|
native_unit_of_measurement=TIME_DAYS,
|
||||||
|
icon="mdi:calendar-range",
|
||||||
|
),
|
||||||
|
SensorEntityDescription(
|
||||||
|
key="daysRemaining",
|
||||||
|
name="Billing Cycle Remaining",
|
||||||
|
native_unit_of_measurement=TIME_DAYS,
|
||||||
|
icon="mdi:calendar-clock",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(
|
||||||
|
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
|
||||||
|
):
|
||||||
|
"""Set up the Aussie Broadband sensor platform from a config entry."""
|
||||||
|
|
||||||
|
async_add_entities(
|
||||||
|
[
|
||||||
|
AussieBroadandSensorEntity(service, description)
|
||||||
|
for service in hass.data[DOMAIN][entry.entry_id]["services"]
|
||||||
|
for description in SENSOR_DESCRIPTIONS
|
||||||
|
if description.key in service["coordinator"].data
|
||||||
|
]
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
class AussieBroadandSensorEntity(CoordinatorEntity, SensorEntity):
|
||||||
|
"""Base class for Aussie Broadband metric sensors."""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self, service: dict[str, Any], description: SensorEntityDescription
|
||||||
|
) -> None:
|
||||||
|
"""Initialize the sensor."""
|
||||||
|
super().__init__(service["coordinator"])
|
||||||
|
self.entity_description = description
|
||||||
|
self._attr_unique_id = f"{service[SERVICE_ID]}:{description.key}"
|
||||||
|
self._attr_name = f"{service['name']} {description.name}"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def native_value(self):
|
||||||
|
"""Return the state of the sensor."""
|
||||||
|
if self.entity_description.key == "internet":
|
||||||
|
return self.coordinator.data[self.entity_description.key]["kbytes"]
|
||||||
|
if self.entity_description.key in ("national", "mobile", "sms"):
|
||||||
|
return self.coordinator.data[self.entity_description.key]["calls"]
|
||||||
|
return self.coordinator.data[self.entity_description.key]
|
50
homeassistant/components/aussie_broadband/strings.json
Normal file
50
homeassistant/components/aussie_broadband/strings.json
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"step": {
|
||||||
|
"user": {
|
||||||
|
"data": {
|
||||||
|
"username": "[%key:common::config_flow::data::username%]",
|
||||||
|
"password": "[%key:common::config_flow::data::password%]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"service": {
|
||||||
|
"title": "Select Services",
|
||||||
|
"data": {
|
||||||
|
"services": "Services"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"reauth": {
|
||||||
|
"title": "[%key:common::config_flow::title::reauth%]",
|
||||||
|
"description": "Update password for {username}",
|
||||||
|
"data": {
|
||||||
|
"password": "[%key:common::config_flow::data::password%]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"invalid_auth": "[%key:common::config_flow::error::invalid_auth%]",
|
||||||
|
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
|
||||||
|
"unknown": "[%key:common::config_flow::error::unknown%]"
|
||||||
|
},
|
||||||
|
"abort": {
|
||||||
|
"already_configured": "[%key:common::config_flow::abort::already_configured_account%]",
|
||||||
|
"no_services_found": "No services were found for this account",
|
||||||
|
"reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"step": {
|
||||||
|
"init": {
|
||||||
|
"title": "Select Services",
|
||||||
|
"data": {
|
||||||
|
"services": "Services"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"abort": {
|
||||||
|
"invalid_auth": "[%key:common::config_flow::error::invalid_auth%]",
|
||||||
|
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
|
||||||
|
"unknown": "[%key:common::config_flow::error::unknown%]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -34,6 +34,7 @@ FLOWS = [
|
|||||||
"august",
|
"august",
|
||||||
"aurora",
|
"aurora",
|
||||||
"aurora_abb_powerone",
|
"aurora_abb_powerone",
|
||||||
|
"aussie_broadband",
|
||||||
"awair",
|
"awair",
|
||||||
"axis",
|
"axis",
|
||||||
"azure_devops",
|
"azure_devops",
|
||||||
|
@ -1403,6 +1403,9 @@ pyatome==0.1.1
|
|||||||
# homeassistant.components.apple_tv
|
# homeassistant.components.apple_tv
|
||||||
pyatv==0.9.8
|
pyatv==0.9.8
|
||||||
|
|
||||||
|
# homeassistant.components.aussie_broadband
|
||||||
|
pyaussiebb==0.0.9
|
||||||
|
|
||||||
# homeassistant.components.balboa
|
# homeassistant.components.balboa
|
||||||
pybalboa==0.13
|
pybalboa==0.13
|
||||||
|
|
||||||
|
@ -877,6 +877,9 @@ pyatmo==6.2.2
|
|||||||
# homeassistant.components.apple_tv
|
# homeassistant.components.apple_tv
|
||||||
pyatv==0.9.8
|
pyatv==0.9.8
|
||||||
|
|
||||||
|
# homeassistant.components.aussie_broadband
|
||||||
|
pyaussiebb==0.0.9
|
||||||
|
|
||||||
# homeassistant.components.balboa
|
# homeassistant.components.balboa
|
||||||
pybalboa==0.13
|
pybalboa==0.13
|
||||||
|
|
||||||
|
1
tests/components/aussie_broadband/__init__.py
Normal file
1
tests/components/aussie_broadband/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
"""Tests for the Aussie Broadband integration."""
|
58
tests/components/aussie_broadband/common.py
Normal file
58
tests/components/aussie_broadband/common.py
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
"""Aussie Broadband common helpers for tests."""
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from homeassistant.components.aussie_broadband.const import (
|
||||||
|
CONF_SERVICES,
|
||||||
|
DOMAIN as AUSSIE_BROADBAND_DOMAIN,
|
||||||
|
)
|
||||||
|
from homeassistant.const import CONF_PASSWORD, CONF_SCAN_INTERVAL, CONF_USERNAME
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
|
FAKE_SERVICES = [
|
||||||
|
{
|
||||||
|
"service_id": "12345678",
|
||||||
|
"description": "Fake ABB NBN Service",
|
||||||
|
"type": "NBN",
|
||||||
|
"name": "NBN",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"service_id": "87654321",
|
||||||
|
"description": "Fake ABB Mobile Service",
|
||||||
|
"type": "PhoneMobile",
|
||||||
|
"name": "Mobile",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
FAKE_DATA = {
|
||||||
|
CONF_USERNAME: "test-username",
|
||||||
|
CONF_PASSWORD: "test-password",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def setup_platform(hass, platforms=[], side_effect=None, usage={}):
|
||||||
|
"""Set up the Aussie Broadband platform."""
|
||||||
|
mock_entry = MockConfigEntry(
|
||||||
|
domain=AUSSIE_BROADBAND_DOMAIN,
|
||||||
|
data=FAKE_DATA,
|
||||||
|
options={CONF_SERVICES: ["12345678", "87654321"], CONF_SCAN_INTERVAL: 30},
|
||||||
|
)
|
||||||
|
mock_entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
with patch("homeassistant.components.aussie_broadband.PLATFORMS", platforms), patch(
|
||||||
|
"aussiebb.asyncio.AussieBB.__init__", return_value=None
|
||||||
|
), patch(
|
||||||
|
"aussiebb.asyncio.AussieBB.login",
|
||||||
|
return_value=True,
|
||||||
|
side_effect=side_effect,
|
||||||
|
), patch(
|
||||||
|
"aussiebb.asyncio.AussieBB.get_services",
|
||||||
|
return_value=FAKE_SERVICES,
|
||||||
|
side_effect=side_effect,
|
||||||
|
), patch(
|
||||||
|
"aussiebb.asyncio.AussieBB.get_usage", return_value=usage
|
||||||
|
):
|
||||||
|
await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
return mock_entry
|
322
tests/components/aussie_broadband/test_config_flow.py
Normal file
322
tests/components/aussie_broadband/test_config_flow.py
Normal file
@ -0,0 +1,322 @@
|
|||||||
|
"""Test the Aussie Broadband config flow."""
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from aiohttp import ClientConnectionError
|
||||||
|
from aussiebb.asyncio import AuthenticationException
|
||||||
|
|
||||||
|
from homeassistant import config_entries, setup
|
||||||
|
from homeassistant.components.aussie_broadband.const import CONF_SERVICES, DOMAIN
|
||||||
|
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.data_entry_flow import (
|
||||||
|
RESULT_TYPE_ABORT,
|
||||||
|
RESULT_TYPE_CREATE_ENTRY,
|
||||||
|
RESULT_TYPE_FORM,
|
||||||
|
)
|
||||||
|
|
||||||
|
from .common import FAKE_DATA, FAKE_SERVICES, setup_platform
|
||||||
|
|
||||||
|
TEST_USERNAME = FAKE_DATA[CONF_USERNAME]
|
||||||
|
TEST_PASSWORD = FAKE_DATA[CONF_PASSWORD]
|
||||||
|
|
||||||
|
|
||||||
|
async def test_form(hass: HomeAssistant) -> None:
|
||||||
|
"""Test we get the form."""
|
||||||
|
result1 = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||||
|
)
|
||||||
|
assert result1["type"] == RESULT_TYPE_FORM
|
||||||
|
assert result1["errors"] is None
|
||||||
|
|
||||||
|
with patch("aussiebb.asyncio.AussieBB.__init__", return_value=None), patch(
|
||||||
|
"aussiebb.asyncio.AussieBB.login", return_value=True
|
||||||
|
), patch(
|
||||||
|
"aussiebb.asyncio.AussieBB.get_services", return_value=[FAKE_SERVICES[0]]
|
||||||
|
), patch(
|
||||||
|
"homeassistant.components.aussie_broadband.async_setup_entry",
|
||||||
|
return_value=True,
|
||||||
|
) as mock_setup_entry:
|
||||||
|
result2 = await hass.config_entries.flow.async_configure(
|
||||||
|
result1["flow_id"],
|
||||||
|
FAKE_DATA,
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert result2["type"] == RESULT_TYPE_CREATE_ENTRY
|
||||||
|
assert result2["title"] == TEST_USERNAME
|
||||||
|
assert result2["data"] == FAKE_DATA
|
||||||
|
assert result2["options"] == {CONF_SERVICES: ["12345678"]}
|
||||||
|
assert len(mock_setup_entry.mock_calls) == 1
|
||||||
|
|
||||||
|
|
||||||
|
async def test_already_configured(hass: HomeAssistant) -> None:
|
||||||
|
"""Test already configured."""
|
||||||
|
# Setup an entry
|
||||||
|
result1 = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||||
|
)
|
||||||
|
|
||||||
|
with patch("aussiebb.asyncio.AussieBB.__init__", return_value=None), patch(
|
||||||
|
"aussiebb.asyncio.AussieBB.login", return_value=True
|
||||||
|
), patch(
|
||||||
|
"aussiebb.asyncio.AussieBB.get_services", return_value=[FAKE_SERVICES[0]]
|
||||||
|
), patch(
|
||||||
|
"homeassistant.components.aussie_broadband.async_setup_entry",
|
||||||
|
return_value=True,
|
||||||
|
) as mock_setup_entry:
|
||||||
|
await hass.config_entries.flow.async_configure(
|
||||||
|
result1["flow_id"],
|
||||||
|
FAKE_DATA,
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
# Test Already configured
|
||||||
|
result3 = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||||
|
)
|
||||||
|
with patch("aussiebb.asyncio.AussieBB.__init__", return_value=None), patch(
|
||||||
|
"aussiebb.asyncio.AussieBB.login", return_value=True
|
||||||
|
), patch(
|
||||||
|
"aussiebb.asyncio.AussieBB.get_services", return_value=[FAKE_SERVICES[0]]
|
||||||
|
), patch(
|
||||||
|
"homeassistant.components.aussie_broadband.async_setup_entry",
|
||||||
|
return_value=True,
|
||||||
|
) as mock_setup_entry:
|
||||||
|
result4 = await hass.config_entries.flow.async_configure(
|
||||||
|
result3["flow_id"],
|
||||||
|
FAKE_DATA,
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert result4["type"] == RESULT_TYPE_ABORT
|
||||||
|
assert len(mock_setup_entry.mock_calls) == 0
|
||||||
|
|
||||||
|
|
||||||
|
async def test_no_services(hass: HomeAssistant) -> None:
|
||||||
|
"""Test when there are no services."""
|
||||||
|
result1 = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||||
|
)
|
||||||
|
assert result1["type"] == RESULT_TYPE_FORM
|
||||||
|
assert result1["errors"] is None
|
||||||
|
|
||||||
|
with patch("aussiebb.asyncio.AussieBB.__init__", return_value=None), patch(
|
||||||
|
"aussiebb.asyncio.AussieBB.login", return_value=True
|
||||||
|
), patch("aussiebb.asyncio.AussieBB.get_services", return_value=[]), patch(
|
||||||
|
"homeassistant.components.aussie_broadband.async_setup_entry",
|
||||||
|
return_value=True,
|
||||||
|
) as mock_setup_entry:
|
||||||
|
result2 = await hass.config_entries.flow.async_configure(
|
||||||
|
result1["flow_id"],
|
||||||
|
FAKE_DATA,
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert result2["type"] == RESULT_TYPE_ABORT
|
||||||
|
assert result2["reason"] == "no_services_found"
|
||||||
|
assert len(mock_setup_entry.mock_calls) == 0
|
||||||
|
|
||||||
|
|
||||||
|
async def test_form_multiple_services(hass: HomeAssistant) -> None:
|
||||||
|
"""Test the config flow with multiple services."""
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||||
|
)
|
||||||
|
assert result["type"] == RESULT_TYPE_FORM
|
||||||
|
assert result["errors"] is None
|
||||||
|
|
||||||
|
with patch("aussiebb.asyncio.AussieBB.__init__", return_value=None), patch(
|
||||||
|
"aussiebb.asyncio.AussieBB.login", return_value=True
|
||||||
|
), patch("aussiebb.asyncio.AussieBB.get_services", return_value=FAKE_SERVICES):
|
||||||
|
result2 = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
FAKE_DATA,
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert result2["type"] == RESULT_TYPE_FORM
|
||||||
|
assert result2["step_id"] == "service"
|
||||||
|
assert result2["errors"] is None
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.aussie_broadband.async_setup_entry",
|
||||||
|
return_value=True,
|
||||||
|
) as mock_setup_entry:
|
||||||
|
result3 = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
{CONF_SERVICES: [FAKE_SERVICES[1]["service_id"]]},
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert result3["type"] == RESULT_TYPE_CREATE_ENTRY
|
||||||
|
assert result3["title"] == TEST_USERNAME
|
||||||
|
assert result3["data"] == FAKE_DATA
|
||||||
|
assert result3["options"] == {
|
||||||
|
CONF_SERVICES: [FAKE_SERVICES[1]["service_id"]],
|
||||||
|
}
|
||||||
|
assert len(mock_setup_entry.mock_calls) == 1
|
||||||
|
|
||||||
|
|
||||||
|
async def test_form_invalid_auth(hass: HomeAssistant) -> None:
|
||||||
|
"""Test invalid auth is handled."""
|
||||||
|
result1 = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||||
|
)
|
||||||
|
|
||||||
|
with patch("aussiebb.asyncio.AussieBB.__init__", return_value=None), patch(
|
||||||
|
"aussiebb.asyncio.AussieBB.login", side_effect=AuthenticationException()
|
||||||
|
):
|
||||||
|
result2 = await hass.config_entries.flow.async_configure(
|
||||||
|
result1["flow_id"],
|
||||||
|
FAKE_DATA,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result2["type"] == RESULT_TYPE_FORM
|
||||||
|
assert result2["errors"] == {"base": "invalid_auth"}
|
||||||
|
|
||||||
|
|
||||||
|
async def test_form_network_issue(hass: HomeAssistant) -> None:
|
||||||
|
"""Test network issues are handled."""
|
||||||
|
result1 = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||||
|
)
|
||||||
|
|
||||||
|
with patch("aussiebb.asyncio.AussieBB.__init__", return_value=None), patch(
|
||||||
|
"aussiebb.asyncio.AussieBB.login", side_effect=ClientConnectionError()
|
||||||
|
):
|
||||||
|
result2 = await hass.config_entries.flow.async_configure(
|
||||||
|
result1["flow_id"],
|
||||||
|
FAKE_DATA,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result2["type"] == RESULT_TYPE_FORM
|
||||||
|
assert result2["errors"] == {"base": "cannot_connect"}
|
||||||
|
|
||||||
|
|
||||||
|
async def test_reauth(hass: HomeAssistant) -> None:
|
||||||
|
"""Test reauth flow."""
|
||||||
|
|
||||||
|
await setup.async_setup_component(hass, "persistent_notification", {})
|
||||||
|
|
||||||
|
# Test reauth but the entry doesn't exist
|
||||||
|
result1 = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": config_entries.SOURCE_REAUTH}, data=FAKE_DATA
|
||||||
|
)
|
||||||
|
|
||||||
|
with patch("aussiebb.asyncio.AussieBB.__init__", return_value=None), patch(
|
||||||
|
"aussiebb.asyncio.AussieBB.login", return_value=True
|
||||||
|
), patch(
|
||||||
|
"aussiebb.asyncio.AussieBB.get_services", return_value=[FAKE_SERVICES[0]]
|
||||||
|
), patch(
|
||||||
|
"homeassistant.components.aussie_broadband.async_setup_entry",
|
||||||
|
return_value=True,
|
||||||
|
):
|
||||||
|
result2 = await hass.config_entries.flow.async_configure(
|
||||||
|
result1["flow_id"],
|
||||||
|
{
|
||||||
|
CONF_PASSWORD: TEST_PASSWORD,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert result2["type"] == RESULT_TYPE_CREATE_ENTRY
|
||||||
|
assert result2["title"] == TEST_USERNAME
|
||||||
|
assert result2["data"] == FAKE_DATA
|
||||||
|
|
||||||
|
# Test failed reauth
|
||||||
|
result5 = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN,
|
||||||
|
context={"source": config_entries.SOURCE_REAUTH},
|
||||||
|
data=FAKE_DATA,
|
||||||
|
)
|
||||||
|
assert result5["step_id"] == "reauth"
|
||||||
|
|
||||||
|
with patch("aussiebb.asyncio.AussieBB.__init__", return_value=None), patch(
|
||||||
|
"aussiebb.asyncio.AussieBB.login", side_effect=AuthenticationException()
|
||||||
|
), patch("aussiebb.asyncio.AussieBB.get_services", return_value=[FAKE_SERVICES[0]]):
|
||||||
|
|
||||||
|
result6 = await hass.config_entries.flow.async_configure(
|
||||||
|
result5["flow_id"],
|
||||||
|
{
|
||||||
|
CONF_PASSWORD: "test-wrongpassword",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert result6["step_id"] == "reauth"
|
||||||
|
|
||||||
|
# Test successful reauth
|
||||||
|
with patch("aussiebb.asyncio.AussieBB.__init__", return_value=None), patch(
|
||||||
|
"aussiebb.asyncio.AussieBB.login", return_value=True
|
||||||
|
), patch("aussiebb.asyncio.AussieBB.get_services", return_value=[FAKE_SERVICES[0]]):
|
||||||
|
|
||||||
|
result7 = await hass.config_entries.flow.async_configure(
|
||||||
|
result6["flow_id"],
|
||||||
|
{
|
||||||
|
CONF_PASSWORD: "test-newpassword",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert result7["type"] == "abort"
|
||||||
|
assert result7["reason"] == "reauth_successful"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_options_flow(hass):
|
||||||
|
"""Test options flow."""
|
||||||
|
entry = await setup_platform(hass)
|
||||||
|
|
||||||
|
with patch("aussiebb.asyncio.AussieBB.get_services", return_value=FAKE_SERVICES):
|
||||||
|
|
||||||
|
result1 = await hass.config_entries.options.async_init(entry.entry_id)
|
||||||
|
assert result1["type"] == RESULT_TYPE_FORM
|
||||||
|
assert result1["step_id"] == "init"
|
||||||
|
|
||||||
|
result2 = await hass.config_entries.options.async_configure(
|
||||||
|
result1["flow_id"],
|
||||||
|
user_input={CONF_SERVICES: []},
|
||||||
|
)
|
||||||
|
assert result2["type"] == RESULT_TYPE_CREATE_ENTRY
|
||||||
|
assert entry.options == {CONF_SERVICES: []}
|
||||||
|
|
||||||
|
|
||||||
|
async def test_options_flow_auth_failure(hass):
|
||||||
|
"""Test options flow with auth failure."""
|
||||||
|
|
||||||
|
entry = await setup_platform(hass)
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"aussiebb.asyncio.AussieBB.get_services", side_effect=AuthenticationException()
|
||||||
|
):
|
||||||
|
|
||||||
|
result1 = await hass.config_entries.options.async_init(entry.entry_id)
|
||||||
|
assert result1["type"] == RESULT_TYPE_ABORT
|
||||||
|
assert result1["reason"] == "invalid_auth"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_options_flow_network_failure(hass):
|
||||||
|
"""Test options flow with connectivity failure."""
|
||||||
|
|
||||||
|
entry = await setup_platform(hass)
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"aussiebb.asyncio.AussieBB.get_services", side_effect=ClientConnectionError()
|
||||||
|
):
|
||||||
|
|
||||||
|
result1 = await hass.config_entries.options.async_init(entry.entry_id)
|
||||||
|
assert result1["type"] == RESULT_TYPE_ABORT
|
||||||
|
assert result1["reason"] == "cannot_connect"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_options_flow_not_loaded(hass):
|
||||||
|
"""Test the options flow aborts when the entry has unloaded due to a reauth."""
|
||||||
|
|
||||||
|
entry = await setup_platform(hass)
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"aussiebb.asyncio.AussieBB.get_services", side_effect=AuthenticationException()
|
||||||
|
):
|
||||||
|
entry.state = config_entries.ConfigEntryState.NOT_LOADED
|
||||||
|
result1 = await hass.config_entries.options.async_init(entry.entry_id)
|
||||||
|
assert result1["type"] == RESULT_TYPE_ABORT
|
||||||
|
assert result1["reason"] == "unknown"
|
35
tests/components/aussie_broadband/test_init.py
Normal file
35
tests/components/aussie_broadband/test_init.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
"""Test the Aussie Broadband init."""
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from aiohttp import ClientConnectionError
|
||||||
|
from aussiebb.asyncio import AuthenticationException
|
||||||
|
|
||||||
|
from homeassistant import data_entry_flow
|
||||||
|
from homeassistant.config_entries import ConfigEntryState
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
|
from .common import setup_platform
|
||||||
|
|
||||||
|
|
||||||
|
async def test_unload(hass: HomeAssistant) -> None:
|
||||||
|
"""Test unload."""
|
||||||
|
entry = await setup_platform(hass)
|
||||||
|
assert await hass.config_entries.async_unload(entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert entry.state is ConfigEntryState.NOT_LOADED
|
||||||
|
|
||||||
|
|
||||||
|
async def test_auth_failure(hass: HomeAssistant) -> None:
|
||||||
|
"""Test init with an authentication failure."""
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.aussie_broadband.config_flow.ConfigFlow.async_step_reauth",
|
||||||
|
return_value={"type": data_entry_flow.RESULT_TYPE_FORM},
|
||||||
|
) as mock_async_step_reauth:
|
||||||
|
await setup_platform(hass, side_effect=AuthenticationException())
|
||||||
|
mock_async_step_reauth.assert_called_once()
|
||||||
|
|
||||||
|
|
||||||
|
async def test_net_failure(hass: HomeAssistant) -> None:
|
||||||
|
"""Test init with a network failure."""
|
||||||
|
entry = await setup_platform(hass, side_effect=ClientConnectionError())
|
||||||
|
assert entry.state is ConfigEntryState.SETUP_RETRY
|
50
tests/components/aussie_broadband/test_sensor.py
Normal file
50
tests/components/aussie_broadband/test_sensor.py
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
"""Aussie Broadband sensor platform tests."""
|
||||||
|
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
|
||||||
|
|
||||||
|
from .common import setup_platform
|
||||||
|
|
||||||
|
MOCK_NBN_USAGE = {
|
||||||
|
"usedMb": 54321,
|
||||||
|
"downloadedMb": 50000,
|
||||||
|
"uploadedMb": 4321,
|
||||||
|
"daysTotal": 28,
|
||||||
|
"daysRemaining": 25,
|
||||||
|
}
|
||||||
|
|
||||||
|
MOCK_MOBILE_USAGE = {
|
||||||
|
"national": {"calls": 1, "cost": 0},
|
||||||
|
"mobile": {"calls": 2, "cost": 0},
|
||||||
|
"international": {"calls": 3, "cost": 0},
|
||||||
|
"sms": {"calls": 4, "cost": 0},
|
||||||
|
"internet": {"kbytes": 512, "cost": 0},
|
||||||
|
"voicemail": {"calls": 6, "cost": 0},
|
||||||
|
"other": {"calls": 7, "cost": 0},
|
||||||
|
"daysTotal": 31,
|
||||||
|
"daysRemaining": 30,
|
||||||
|
"historical": [],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def test_nbn_sensor_states(hass):
|
||||||
|
"""Tests that the sensors are correct."""
|
||||||
|
|
||||||
|
await setup_platform(hass, [SENSOR_DOMAIN], usage=MOCK_NBN_USAGE)
|
||||||
|
|
||||||
|
assert hass.states.get("sensor.nbn_data_used").state == "54321"
|
||||||
|
assert hass.states.get("sensor.nbn_downloaded").state == "50000"
|
||||||
|
assert hass.states.get("sensor.nbn_uploaded").state == "4321"
|
||||||
|
assert hass.states.get("sensor.nbn_billing_cycle_length").state == "28"
|
||||||
|
assert hass.states.get("sensor.nbn_billing_cycle_remaining").state == "25"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_phone_sensor_states(hass):
|
||||||
|
"""Tests that the sensors are correct."""
|
||||||
|
|
||||||
|
await setup_platform(hass, [SENSOR_DOMAIN], usage=MOCK_MOBILE_USAGE)
|
||||||
|
|
||||||
|
assert hass.states.get("sensor.mobile_national_calls").state == "1"
|
||||||
|
assert hass.states.get("sensor.mobile_mobile_calls").state == "2"
|
||||||
|
assert hass.states.get("sensor.mobile_sms_sent").state == "4"
|
||||||
|
assert hass.states.get("sensor.mobile_data_used").state == "512"
|
||||||
|
assert hass.states.get("sensor.mobile_billing_cycle_length").state == "31"
|
||||||
|
assert hass.states.get("sensor.mobile_billing_cycle_remaining").state == "30"
|
Loading…
x
Reference in New Issue
Block a user