mirror of
https://github.com/home-assistant/core.git
synced 2026-03-17 08:21:58 +01:00
Compare commits
7 Commits
edenhaus-r
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9bbd9d8bcd | ||
|
|
5ff2cac077 | ||
|
|
74b0d058ec | ||
|
|
29f96e3f9c | ||
|
|
39b44445ec | ||
|
|
589622c05a | ||
|
|
6abe576ec9 |
@@ -338,6 +338,7 @@ class Analytics:
|
||||
|
||||
hass = self._hass
|
||||
supervisor_info = None
|
||||
addons_info: dict[str, Any] | None = None
|
||||
operating_system_info: dict[str, Any] = {}
|
||||
|
||||
if self._data.uuid is None:
|
||||
@@ -347,6 +348,7 @@ class Analytics:
|
||||
if self.supervisor:
|
||||
supervisor_info = hassio.get_supervisor_info(hass)
|
||||
operating_system_info = hassio.get_os_info(hass) or {}
|
||||
addons_info = hassio.get_addons_info(hass) or {}
|
||||
|
||||
system_info = await async_get_system_info(hass)
|
||||
integrations = []
|
||||
@@ -419,13 +421,10 @@ class Analytics:
|
||||
|
||||
integrations.append(integration.domain)
|
||||
|
||||
if supervisor_info is not None:
|
||||
if addons_info is not None:
|
||||
supervisor_client = hassio.get_supervisor_client(hass)
|
||||
installed_addons = await asyncio.gather(
|
||||
*(
|
||||
supervisor_client.addons.addon_info(addon[ATTR_SLUG])
|
||||
for addon in supervisor_info[ATTR_ADDONS]
|
||||
)
|
||||
*(supervisor_client.addons.addon_info(slug) for slug in addons_info)
|
||||
)
|
||||
addons.extend(
|
||||
{
|
||||
|
||||
@@ -9,10 +9,21 @@ import logging
|
||||
import os
|
||||
import re
|
||||
import struct
|
||||
from typing import Any, NamedTuple
|
||||
from typing import Any, NamedTuple, cast
|
||||
|
||||
from aiohasupervisor import SupervisorError
|
||||
from aiohasupervisor.models import GreenOptions, YellowOptions # noqa: F401
|
||||
from aiohasupervisor.models import (
|
||||
GreenOptions,
|
||||
HomeAssistantInfo,
|
||||
HostInfo,
|
||||
InstalledAddon,
|
||||
NetworkInfo,
|
||||
OSInfo,
|
||||
RootInfo,
|
||||
StoreInfo,
|
||||
SupervisorInfo,
|
||||
YellowOptions,
|
||||
)
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.auth.const import GROUP_ID_ADMIN
|
||||
@@ -65,7 +76,7 @@ from . import ( # noqa: F401
|
||||
system_health,
|
||||
update,
|
||||
)
|
||||
from .addon_manager import AddonError, AddonInfo, AddonManager, AddonState # noqa: F401
|
||||
from .addon_manager import AddonError, AddonInfo, AddonManager, AddonState
|
||||
from .addon_panel import async_setup_addon_panel
|
||||
from .auth import async_setup_auth_view
|
||||
from .config import HassioConfig
|
||||
@@ -82,7 +93,9 @@ from .const import (
|
||||
ATTR_INPUT,
|
||||
ATTR_LOCATION,
|
||||
ATTR_PASSWORD,
|
||||
ATTR_REPOSITORIES,
|
||||
ATTR_SLUG,
|
||||
DATA_ADDONS_LIST,
|
||||
DATA_COMPONENT,
|
||||
DATA_CONFIG_STORE,
|
||||
DATA_CORE_INFO,
|
||||
@@ -100,18 +113,21 @@ from .const import (
|
||||
from .coordinator import (
|
||||
HassioDataUpdateCoordinator,
|
||||
get_addons_info,
|
||||
get_addons_stats, # noqa: F401
|
||||
get_core_info, # noqa: F401
|
||||
get_core_stats, # noqa: F401
|
||||
get_host_info, # noqa: F401
|
||||
get_addons_list,
|
||||
get_addons_stats,
|
||||
get_core_info,
|
||||
get_core_stats,
|
||||
get_host_info,
|
||||
get_info,
|
||||
get_issues_info, # noqa: F401
|
||||
get_issues_info,
|
||||
get_network_info,
|
||||
get_os_info,
|
||||
get_supervisor_info, # noqa: F401
|
||||
get_supervisor_stats, # noqa: F401
|
||||
get_store,
|
||||
get_supervisor_info,
|
||||
get_supervisor_stats,
|
||||
)
|
||||
from .discovery import async_setup_discovery_view
|
||||
from .handler import ( # noqa: F401
|
||||
from .handler import (
|
||||
HassIO,
|
||||
HassioAPIError,
|
||||
async_update_diagnostics,
|
||||
@@ -122,6 +138,35 @@ from .ingress import async_setup_ingress_view
|
||||
from .issues import SupervisorIssues
|
||||
from .websocket_api import async_load_websocket_api
|
||||
|
||||
# Expose the future safe name now so integrations can use it
|
||||
# All references to addons will eventually be refactored and deprecated
|
||||
get_apps_list = get_addons_list
|
||||
__all__ = [
|
||||
"AddonError",
|
||||
"AddonInfo",
|
||||
"AddonManager",
|
||||
"AddonState",
|
||||
"GreenOptions",
|
||||
"SupervisorError",
|
||||
"YellowOptions",
|
||||
"async_update_diagnostics",
|
||||
"get_addons_info",
|
||||
"get_addons_list",
|
||||
"get_addons_stats",
|
||||
"get_apps_list",
|
||||
"get_core_info",
|
||||
"get_core_stats",
|
||||
"get_host_info",
|
||||
"get_info",
|
||||
"get_issues_info",
|
||||
"get_network_info",
|
||||
"get_os_info",
|
||||
"get_store",
|
||||
"get_supervisor_client",
|
||||
"get_supervisor_info",
|
||||
"get_supervisor_stats",
|
||||
]
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -504,27 +549,55 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: # noqa:
|
||||
|
||||
try:
|
||||
(
|
||||
hass.data[DATA_INFO],
|
||||
hass.data[DATA_HOST_INFO],
|
||||
root_info,
|
||||
host_info,
|
||||
store_info,
|
||||
hass.data[DATA_CORE_INFO],
|
||||
hass.data[DATA_SUPERVISOR_INFO],
|
||||
hass.data[DATA_OS_INFO],
|
||||
hass.data[DATA_NETWORK_INFO],
|
||||
) = await asyncio.gather(
|
||||
create_eager_task(hassio.get_info()),
|
||||
create_eager_task(hassio.get_host_info()),
|
||||
create_eager_task(supervisor_client.store.info()),
|
||||
create_eager_task(hassio.get_core_info()),
|
||||
create_eager_task(hassio.get_supervisor_info()),
|
||||
create_eager_task(hassio.get_os_info()),
|
||||
create_eager_task(hassio.get_network_info()),
|
||||
homeassistant_info,
|
||||
supervisor_info,
|
||||
os_info,
|
||||
network_info,
|
||||
addons_list,
|
||||
) = cast(
|
||||
tuple[
|
||||
RootInfo,
|
||||
HostInfo,
|
||||
StoreInfo,
|
||||
HomeAssistantInfo,
|
||||
SupervisorInfo,
|
||||
OSInfo,
|
||||
NetworkInfo,
|
||||
list[InstalledAddon],
|
||||
],
|
||||
await asyncio.gather(
|
||||
create_eager_task(supervisor_client.info()),
|
||||
create_eager_task(supervisor_client.host.info()),
|
||||
create_eager_task(supervisor_client.store.info()),
|
||||
create_eager_task(supervisor_client.homeassistant.info()),
|
||||
create_eager_task(supervisor_client.supervisor.info()),
|
||||
create_eager_task(supervisor_client.os.info()),
|
||||
create_eager_task(supervisor_client.network.info()),
|
||||
create_eager_task(supervisor_client.addons.list()),
|
||||
),
|
||||
)
|
||||
|
||||
except HassioAPIError as err:
|
||||
except SupervisorError as err:
|
||||
_LOGGER.warning("Can't read Supervisor data: %s", err)
|
||||
else:
|
||||
hass.data[DATA_INFO] = root_info.to_dict()
|
||||
hass.data[DATA_HOST_INFO] = host_info.to_dict()
|
||||
hass.data[DATA_STORE] = store_info.to_dict()
|
||||
hass.data[DATA_CORE_INFO] = homeassistant_info.to_dict()
|
||||
hass.data[DATA_SUPERVISOR_INFO] = supervisor_info.to_dict()
|
||||
hass.data[DATA_OS_INFO] = os_info.to_dict()
|
||||
hass.data[DATA_NETWORK_INFO] = network_info.to_dict()
|
||||
hass.data[DATA_ADDONS_LIST] = [addon.to_dict() for addon in addons_list]
|
||||
|
||||
# Deprecated 2026.4.0: Folding repositories and addons.list results into supervisor_info for compatibility
|
||||
# Can drop this after removal period
|
||||
hass.data[DATA_SUPERVISOR_INFO]["repositories"] = hass.data[DATA_STORE][
|
||||
ATTR_REPOSITORIES
|
||||
]
|
||||
hass.data[DATA_SUPERVISOR_INFO]["addons"] = hass.data[DATA_ADDONS_LIST]
|
||||
|
||||
async_call_later(
|
||||
hass,
|
||||
|
||||
@@ -93,6 +93,7 @@ DATA_SUPERVISOR_INFO = "hassio_supervisor_info"
|
||||
DATA_SUPERVISOR_STATS = "hassio_supervisor_stats"
|
||||
DATA_ADDONS_INFO = "hassio_addons_info"
|
||||
DATA_ADDONS_STATS = "hassio_addons_stats"
|
||||
DATA_ADDONS_LIST = "hassio_addons_list"
|
||||
HASSIO_UPDATE_INTERVAL = timedelta(minutes=5)
|
||||
|
||||
ATTR_AUTO_UPDATE = "auto_update"
|
||||
@@ -106,6 +107,7 @@ ATTR_STATE = "state"
|
||||
ATTR_STARTED = "started"
|
||||
ATTR_URL = "url"
|
||||
ATTR_REPOSITORY = "repository"
|
||||
ATTR_REPOSITORIES = "repositories"
|
||||
|
||||
DATA_KEY_ADDONS = "addons"
|
||||
DATA_KEY_OS = "os"
|
||||
|
||||
@@ -4,13 +4,20 @@ from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from collections import defaultdict
|
||||
from collections.abc import Awaitable
|
||||
from copy import deepcopy
|
||||
import logging
|
||||
from typing import TYPE_CHECKING, Any
|
||||
from typing import TYPE_CHECKING, Any, cast
|
||||
|
||||
from aiohasupervisor import SupervisorError, SupervisorNotFoundError
|
||||
from aiohasupervisor.models import StoreInfo
|
||||
from aiohasupervisor.models.mounts import CIFSMountResponse, NFSMountResponse
|
||||
from aiohasupervisor.models import (
|
||||
AddonState,
|
||||
CIFSMountResponse,
|
||||
InstalledAddon,
|
||||
NFSMountResponse,
|
||||
StoreInfo,
|
||||
)
|
||||
from aiohasupervisor.models.base import ResponseData
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import ATTR_MANUFACTURER, ATTR_NAME
|
||||
@@ -23,16 +30,16 @@ from homeassistant.loader import bind_hass
|
||||
|
||||
from .const import (
|
||||
ATTR_AUTO_UPDATE,
|
||||
ATTR_REPOSITORIES,
|
||||
ATTR_REPOSITORY,
|
||||
ATTR_SLUG,
|
||||
ATTR_STARTED,
|
||||
ATTR_STATE,
|
||||
ATTR_URL,
|
||||
ATTR_VERSION,
|
||||
CONTAINER_INFO,
|
||||
CONTAINER_STATS,
|
||||
CORE_CONTAINER,
|
||||
DATA_ADDONS_INFO,
|
||||
DATA_ADDONS_LIST,
|
||||
DATA_ADDONS_STATS,
|
||||
DATA_COMPONENT,
|
||||
DATA_CORE_INFO,
|
||||
@@ -57,7 +64,7 @@ from .const import (
|
||||
SUPERVISOR_CONTAINER,
|
||||
SupervisorEntityModel,
|
||||
)
|
||||
from .handler import HassioAPIError, get_supervisor_client
|
||||
from .handler import get_supervisor_client
|
||||
from .jobs import SupervisorJobs
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -118,7 +125,7 @@ def get_network_info(hass: HomeAssistant) -> dict[str, Any] | None:
|
||||
|
||||
@callback
|
||||
@bind_hass
|
||||
def get_addons_info(hass: HomeAssistant) -> dict[str, dict[str, Any]] | None:
|
||||
def get_addons_info(hass: HomeAssistant) -> dict[str, dict[str, Any] | None] | None:
|
||||
"""Return Addons info.
|
||||
|
||||
Async friendly.
|
||||
@@ -126,9 +133,18 @@ def get_addons_info(hass: HomeAssistant) -> dict[str, dict[str, Any]] | None:
|
||||
return hass.data.get(DATA_ADDONS_INFO)
|
||||
|
||||
|
||||
@callback
|
||||
def get_addons_list(hass: HomeAssistant) -> list[dict[str, Any]] | None:
|
||||
"""Return list of installed addons and subset of details for each.
|
||||
|
||||
Async friendly.
|
||||
"""
|
||||
return hass.data.get(DATA_ADDONS_LIST)
|
||||
|
||||
|
||||
@callback
|
||||
@bind_hass
|
||||
def get_addons_stats(hass: HomeAssistant) -> dict[str, Any]:
|
||||
def get_addons_stats(hass: HomeAssistant) -> dict[str, dict[str, Any] | None]:
|
||||
"""Return Addons stats.
|
||||
|
||||
Async friendly.
|
||||
@@ -341,7 +357,7 @@ class HassioDataUpdateCoordinator(DataUpdateCoordinator):
|
||||
|
||||
try:
|
||||
await self.force_data_refresh(is_first_update)
|
||||
except HassioAPIError as err:
|
||||
except SupervisorError as err:
|
||||
raise UpdateFailed(f"Error on Supervisor API: {err}") from err
|
||||
|
||||
new_data: dict[str, Any] = {}
|
||||
@@ -350,6 +366,7 @@ class HassioDataUpdateCoordinator(DataUpdateCoordinator):
|
||||
addons_stats = get_addons_stats(self.hass)
|
||||
store_data = get_store(self.hass)
|
||||
mounts_info = await self.supervisor_client.mounts.info()
|
||||
addons_list = get_addons_list(self.hass) or []
|
||||
|
||||
if store_data:
|
||||
repositories = {
|
||||
@@ -360,17 +377,17 @@ class HassioDataUpdateCoordinator(DataUpdateCoordinator):
|
||||
repositories = {}
|
||||
|
||||
new_data[DATA_KEY_ADDONS] = {
|
||||
addon[ATTR_SLUG]: {
|
||||
(slug := addon[ATTR_SLUG]): {
|
||||
**addon,
|
||||
**((addons_stats or {}).get(addon[ATTR_SLUG]) or {}),
|
||||
ATTR_AUTO_UPDATE: (addons_info.get(addon[ATTR_SLUG]) or {}).get(
|
||||
**(addons_stats.get(slug) or {}),
|
||||
ATTR_AUTO_UPDATE: (addons_info.get(slug) or {}).get(
|
||||
ATTR_AUTO_UPDATE, False
|
||||
),
|
||||
ATTR_REPOSITORY: repositories.get(
|
||||
addon.get(ATTR_REPOSITORY), addon.get(ATTR_REPOSITORY, "")
|
||||
repo_slug := addon.get(ATTR_REPOSITORY, ""), repo_slug
|
||||
),
|
||||
}
|
||||
for addon in supervisor_info.get("addons", [])
|
||||
for addon in addons_list
|
||||
}
|
||||
if self.is_hass_os:
|
||||
new_data[DATA_KEY_OS] = get_os_info(self.hass)
|
||||
@@ -462,32 +479,48 @@ class HassioDataUpdateCoordinator(DataUpdateCoordinator):
|
||||
container_updates = self._container_updates
|
||||
|
||||
data = self.hass.data
|
||||
hassio = self.hassio
|
||||
updates = {
|
||||
DATA_INFO: hassio.get_info(),
|
||||
DATA_CORE_INFO: hassio.get_core_info(),
|
||||
DATA_SUPERVISOR_INFO: hassio.get_supervisor_info(),
|
||||
DATA_OS_INFO: hassio.get_os_info(),
|
||||
client = self.supervisor_client
|
||||
|
||||
updates: dict[str, Awaitable[ResponseData]] = {
|
||||
DATA_INFO: client.info(),
|
||||
DATA_CORE_INFO: client.homeassistant.info(),
|
||||
DATA_SUPERVISOR_INFO: client.supervisor.info(),
|
||||
DATA_OS_INFO: client.os.info(),
|
||||
DATA_STORE: client.store.info(),
|
||||
}
|
||||
if CONTAINER_STATS in container_updates[CORE_CONTAINER]:
|
||||
updates[DATA_CORE_STATS] = hassio.get_core_stats()
|
||||
updates[DATA_CORE_STATS] = client.homeassistant.stats()
|
||||
if CONTAINER_STATS in container_updates[SUPERVISOR_CONTAINER]:
|
||||
updates[DATA_SUPERVISOR_STATS] = hassio.get_supervisor_stats()
|
||||
updates[DATA_SUPERVISOR_STATS] = client.supervisor.stats()
|
||||
|
||||
results = await asyncio.gather(*updates.values())
|
||||
for key, result in zip(updates, results, strict=False):
|
||||
data[key] = result
|
||||
# Pull off addons.list results for further processing before caching
|
||||
addons_list, *results = await asyncio.gather(
|
||||
client.addons.list(), *updates.values()
|
||||
)
|
||||
for key, result in zip(updates, cast(list[ResponseData], results), strict=True):
|
||||
data[key] = result.to_dict()
|
||||
|
||||
installed_addons = cast(list[InstalledAddon], addons_list)
|
||||
data[DATA_ADDONS_LIST] = [addon.to_dict() for addon in installed_addons]
|
||||
|
||||
# Deprecated 2026.4.0: Folding repositories and addons.list results into supervisor_info for compatibility
|
||||
# Can drop this after removal period
|
||||
data[DATA_SUPERVISOR_INFO].update(
|
||||
{
|
||||
"repositories": data[DATA_STORE][ATTR_REPOSITORIES],
|
||||
"addons": [addon.to_dict() for addon in installed_addons],
|
||||
}
|
||||
)
|
||||
|
||||
all_addons = {addon.slug for addon in installed_addons}
|
||||
started_addons = {
|
||||
addon.slug
|
||||
for addon in installed_addons
|
||||
if addon.state in {AddonState.STARTED, AddonState.STARTUP}
|
||||
}
|
||||
|
||||
_addon_data = data[DATA_SUPERVISOR_INFO].get("addons", [])
|
||||
all_addons: list[str] = []
|
||||
started_addons: list[str] = []
|
||||
for addon in _addon_data:
|
||||
slug = addon[ATTR_SLUG]
|
||||
all_addons.append(slug)
|
||||
if addon[ATTR_STATE] == ATTR_STARTED:
|
||||
started_addons.append(slug)
|
||||
#
|
||||
# Update add-on info if its the first update or
|
||||
# Update addon info if its the first update or
|
||||
# there is at least one entity that needs the data.
|
||||
#
|
||||
# When entities are added they call async_enable_container_updates
|
||||
@@ -514,6 +547,12 @@ class HassioDataUpdateCoordinator(DataUpdateCoordinator):
|
||||
),
|
||||
):
|
||||
container_data: dict[str, Any] = data.setdefault(data_key, {})
|
||||
|
||||
# Clean up cache
|
||||
for slug in container_data.keys() - wanted_addons:
|
||||
del container_data[slug]
|
||||
|
||||
# Update cache from API
|
||||
container_data.update(
|
||||
dict(
|
||||
await asyncio.gather(
|
||||
@@ -540,7 +579,7 @@ class HassioDataUpdateCoordinator(DataUpdateCoordinator):
|
||||
return (slug, stats.to_dict())
|
||||
|
||||
async def _update_addon_info(self, slug: str) -> tuple[str, dict[str, Any] | None]:
|
||||
"""Return the info for an add-on."""
|
||||
"""Return the info for an addon."""
|
||||
try:
|
||||
info = await self.supervisor_client.addons.addon_info(slug)
|
||||
except SupervisorError as err:
|
||||
|
||||
@@ -87,70 +87,6 @@ class HassIO:
|
||||
"""Return base url for Supervisor."""
|
||||
return self._base_url
|
||||
|
||||
@api_data
|
||||
def get_info(self) -> Coroutine:
|
||||
"""Return generic Supervisor information.
|
||||
|
||||
This method returns a coroutine.
|
||||
"""
|
||||
return self.send_command("/info", method="get")
|
||||
|
||||
@api_data
|
||||
def get_host_info(self) -> Coroutine:
|
||||
"""Return data for Host.
|
||||
|
||||
This method returns a coroutine.
|
||||
"""
|
||||
return self.send_command("/host/info", method="get")
|
||||
|
||||
@api_data
|
||||
def get_os_info(self) -> Coroutine:
|
||||
"""Return data for the OS.
|
||||
|
||||
This method returns a coroutine.
|
||||
"""
|
||||
return self.send_command("/os/info", method="get")
|
||||
|
||||
@api_data
|
||||
def get_core_info(self) -> Coroutine:
|
||||
"""Return data for Home Asssistant Core.
|
||||
|
||||
This method returns a coroutine.
|
||||
"""
|
||||
return self.send_command("/core/info", method="get")
|
||||
|
||||
@api_data
|
||||
def get_supervisor_info(self) -> Coroutine:
|
||||
"""Return data for the Supervisor.
|
||||
|
||||
This method returns a coroutine.
|
||||
"""
|
||||
return self.send_command("/supervisor/info", method="get")
|
||||
|
||||
@api_data
|
||||
def get_network_info(self) -> Coroutine:
|
||||
"""Return data for the Host Network.
|
||||
|
||||
This method returns a coroutine.
|
||||
"""
|
||||
return self.send_command("/network/info", method="get")
|
||||
|
||||
@api_data
|
||||
def get_core_stats(self) -> Coroutine:
|
||||
"""Return stats for the core.
|
||||
|
||||
This method returns a coroutine.
|
||||
"""
|
||||
return self.send_command("/core/stats", method="get")
|
||||
|
||||
@api_data
|
||||
def get_supervisor_stats(self) -> Coroutine:
|
||||
"""Return stats for the supervisor.
|
||||
|
||||
This method returns a coroutine.
|
||||
"""
|
||||
return self.send_command("/supervisor/stats", method="get")
|
||||
|
||||
@api_data
|
||||
def get_ingress_panels(self) -> Coroutine:
|
||||
"""Return data for Add-on ingress panels.
|
||||
|
||||
@@ -17,6 +17,7 @@ from aiohasupervisor.models import (
|
||||
UnsupportedReason,
|
||||
)
|
||||
|
||||
from homeassistant.const import ATTR_NAME
|
||||
from homeassistant.core import HassJob, HomeAssistant, callback
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.event import async_call_later
|
||||
@@ -30,6 +31,7 @@ from .const import (
|
||||
ADDONS_COORDINATOR,
|
||||
ATTR_DATA,
|
||||
ATTR_HEALTHY,
|
||||
ATTR_SLUG,
|
||||
ATTR_STARTUP,
|
||||
ATTR_SUPPORTED,
|
||||
ATTR_UNHEALTHY_REASONS,
|
||||
@@ -59,7 +61,7 @@ from .const import (
|
||||
STARTUP_COMPLETE,
|
||||
UPDATE_KEY_SUPERVISOR,
|
||||
)
|
||||
from .coordinator import HassioDataUpdateCoordinator, get_addons_info, get_host_info
|
||||
from .coordinator import HassioDataUpdateCoordinator, get_addons_list, get_host_info
|
||||
from .handler import HassIO, get_supervisor_client
|
||||
|
||||
ISSUE_KEY_UNHEALTHY = "unhealthy"
|
||||
@@ -265,23 +267,18 @@ class SupervisorIssues:
|
||||
placeholders[PLACEHOLDER_KEY_ADDON_URL] = (
|
||||
f"/hassio/addon/{issue.reference}"
|
||||
)
|
||||
addons = get_addons_info(self._hass)
|
||||
if addons and issue.reference in addons:
|
||||
placeholders[PLACEHOLDER_KEY_ADDON] = addons[issue.reference][
|
||||
"name"
|
||||
]
|
||||
else:
|
||||
placeholders[PLACEHOLDER_KEY_ADDON] = issue.reference
|
||||
addons_list = get_addons_list(self._hass) or []
|
||||
placeholders[PLACEHOLDER_KEY_ADDON] = issue.reference
|
||||
for addon in addons_list:
|
||||
if addon[ATTR_SLUG] == issue.reference:
|
||||
placeholders[PLACEHOLDER_KEY_ADDON] = addon[ATTR_NAME]
|
||||
break
|
||||
|
||||
elif issue.key == ISSUE_KEY_SYSTEM_FREE_SPACE:
|
||||
host_info = get_host_info(self._hass)
|
||||
if (
|
||||
host_info
|
||||
and "data" in host_info
|
||||
and "disk_free" in host_info["data"]
|
||||
):
|
||||
if host_info and "disk_free" in host_info:
|
||||
placeholders[PLACEHOLDER_KEY_FREE_SPACE] = str(
|
||||
host_info["data"]["disk_free"]
|
||||
host_info["disk_free"]
|
||||
)
|
||||
else:
|
||||
placeholders[PLACEHOLDER_KEY_FREE_SPACE] = "<2"
|
||||
|
||||
@@ -11,11 +11,13 @@ from aiohasupervisor.models import ContextType
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.repairs import RepairsFlow
|
||||
from homeassistant.const import ATTR_NAME
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.data_entry_flow import FlowResult
|
||||
|
||||
from . import get_addons_info, get_issues_info
|
||||
from . import get_addons_list, get_issues_info
|
||||
from .const import (
|
||||
ATTR_SLUG,
|
||||
EXTRA_PLACEHOLDERS,
|
||||
ISSUE_KEY_ADDON_BOOT_FAIL,
|
||||
ISSUE_KEY_ADDON_DEPRECATED,
|
||||
@@ -154,7 +156,7 @@ class DockerConfigIssueRepairFlow(SupervisorIssueRepairFlow):
|
||||
placeholders = {PLACEHOLDER_KEY_COMPONENTS: ""}
|
||||
supervisor_issues = get_issues_info(self.hass)
|
||||
if supervisor_issues and self.issue:
|
||||
addons = get_addons_info(self.hass) or {}
|
||||
addons_list = get_addons_list(self.hass) or []
|
||||
components: list[str] = []
|
||||
for issue in supervisor_issues.issues:
|
||||
if issue.key == self.issue.key or issue.type != self.issue.type:
|
||||
@@ -166,9 +168,9 @@ class DockerConfigIssueRepairFlow(SupervisorIssueRepairFlow):
|
||||
components.append(
|
||||
next(
|
||||
(
|
||||
info["name"]
|
||||
for slug, info in addons.items()
|
||||
if slug == issue.reference
|
||||
addon[ATTR_NAME]
|
||||
for addon in addons_list
|
||||
if addon[ATTR_SLUG] == issue.reference
|
||||
),
|
||||
issue.reference or "",
|
||||
)
|
||||
@@ -187,13 +189,12 @@ class AddonIssueRepairFlow(SupervisorIssueRepairFlow):
|
||||
"""Get description placeholders for steps."""
|
||||
placeholders: dict[str, str] = super().description_placeholders or {}
|
||||
if self.issue and self.issue.reference:
|
||||
addons = get_addons_info(self.hass)
|
||||
if addons and self.issue.reference in addons:
|
||||
placeholders[PLACEHOLDER_KEY_ADDON] = addons[self.issue.reference][
|
||||
"name"
|
||||
]
|
||||
else:
|
||||
placeholders[PLACEHOLDER_KEY_ADDON] = self.issue.reference
|
||||
addons_list = get_addons_list(self.hass) or []
|
||||
placeholders[PLACEHOLDER_KEY_ADDON] = self.issue.reference
|
||||
for addon in addons_list:
|
||||
if addon[ATTR_SLUG] == self.issue.reference:
|
||||
placeholders[PLACEHOLDER_KEY_ADDON] = addon[ATTR_NAME]
|
||||
break
|
||||
|
||||
return placeholders or None
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ from homeassistant.components import system_health
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
|
||||
from .coordinator import (
|
||||
get_addons_list,
|
||||
get_host_info,
|
||||
get_info,
|
||||
get_network_info,
|
||||
@@ -35,6 +36,7 @@ async def system_health_info(hass: HomeAssistant) -> dict[str, Any]:
|
||||
host_info = get_host_info(hass) or {}
|
||||
supervisor_info = get_supervisor_info(hass)
|
||||
network_info = get_network_info(hass) or {}
|
||||
addons_list = get_addons_list(hass) or []
|
||||
|
||||
healthy: bool | dict[str, str]
|
||||
if supervisor_info is not None and supervisor_info.get("healthy"):
|
||||
@@ -84,6 +86,8 @@ async def system_health_info(hass: HomeAssistant) -> dict[str, Any]:
|
||||
os_info = get_os_info(hass) or {}
|
||||
information["board"] = os_info.get("board")
|
||||
|
||||
# Not using aiohasupervisor for ping call below intentionally. Given system health
|
||||
# context, it seems preferable to do this check with minimal dependencies
|
||||
information["supervisor_api"] = system_health.async_check_can_reach_url(
|
||||
hass,
|
||||
SUPERVISOR_PING.format(ip_address=ip_address),
|
||||
@@ -95,8 +99,7 @@ async def system_health_info(hass: HomeAssistant) -> dict[str, Any]:
|
||||
)
|
||||
|
||||
information["installed_addons"] = ", ".join(
|
||||
f"{addon['name']} ({addon['version']})"
|
||||
for addon in (supervisor_info or {}).get("addons", [])
|
||||
f"{addon['name']} ({addon['version']})" for addon in addons_list
|
||||
)
|
||||
|
||||
return information
|
||||
|
||||
@@ -39,7 +39,7 @@ from .const import (
|
||||
WS_TYPE_EVENT,
|
||||
WS_TYPE_SUBSCRIBE,
|
||||
)
|
||||
from .coordinator import get_supervisor_info
|
||||
from .coordinator import get_addons_list
|
||||
from .update_helper import update_addon, update_core
|
||||
|
||||
SCHEMA_WEBSOCKET_EVENT = vol.Schema(
|
||||
@@ -168,8 +168,8 @@ async def websocket_update_addon(
|
||||
"""Websocket handler to update an addon."""
|
||||
addon_name: str | None = None
|
||||
addon_version: str | None = None
|
||||
addons: list = (get_supervisor_info(hass) or {}).get("addons", [])
|
||||
for addon in addons:
|
||||
addons_list: list[dict[str, Any]] = get_addons_list(hass) or []
|
||||
for addon in addons_list:
|
||||
if addon[ATTR_SLUG] == msg["addon"]:
|
||||
addon_name = addon[ATTR_NAME]
|
||||
addon_version = addon[ATTR_VERSION]
|
||||
|
||||
@@ -12,6 +12,8 @@ from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
from .coordinator import HuumConfigEntry, HuumDataUpdateCoordinator
|
||||
from .entity import HuumBaseEntity
|
||||
|
||||
PARALLEL_UPDATES = 0
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
|
||||
@@ -24,6 +24,8 @@ from .entity import HuumBaseEntity
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
PARALLEL_UPDATES = 1
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
|
||||
@@ -36,6 +36,7 @@ class HuumConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
"""Handle the initial step."""
|
||||
errors = {}
|
||||
if user_input is not None:
|
||||
self._async_abort_entries_match({CONF_USERNAME: user_input[CONF_USERNAME]})
|
||||
try:
|
||||
huum = Huum(
|
||||
user_input[CONF_USERNAME],
|
||||
@@ -51,9 +52,6 @@ class HuumConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
_LOGGER.exception("Unknown error")
|
||||
errors["base"] = "unknown"
|
||||
else:
|
||||
self._async_abort_entries_match(
|
||||
{CONF_USERNAME: user_input[CONF_USERNAME]}
|
||||
)
|
||||
return self.async_create_entry(
|
||||
title=user_input[CONF_USERNAME], data=user_input
|
||||
)
|
||||
|
||||
@@ -15,6 +15,8 @@ from .entity import HuumBaseEntity
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
PARALLEL_UPDATES = 1
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
|
||||
@@ -16,6 +16,8 @@ from .entity import HuumBaseEntity
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
PARALLEL_UPDATES = 1
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
|
||||
@@ -6,17 +6,12 @@ rules:
|
||||
appropriate-polling: done
|
||||
brands: done
|
||||
common-modules: done
|
||||
config-flow-test-coverage:
|
||||
status: done
|
||||
comment: |
|
||||
PLANNED: Rename result2 -> result throughout test_config_flow.py.
|
||||
config-flow-test-coverage: done
|
||||
config-flow:
|
||||
status: done
|
||||
comment: |
|
||||
PLANNED: Move _async_abort_entries_match before the try block so duplicate
|
||||
entries are rejected before credentials are validated. Remove _LOGGER.error
|
||||
call from config_flow.py — the error message is redundant with the errors
|
||||
dict entry.
|
||||
PLANNED: Remove _LOGGER.error call from config_flow.py — the error
|
||||
message is redundant with the errors dict entry.
|
||||
dependency-transparency: done
|
||||
docs-actions:
|
||||
status: exempt
|
||||
@@ -32,12 +27,7 @@ rules:
|
||||
runtime-data: done
|
||||
test-before-configure: done
|
||||
test-before-setup: done
|
||||
unique-config-entry:
|
||||
status: done
|
||||
comment: |
|
||||
PLANNED: Move _async_abort_entries_match before the try block in
|
||||
config_flow.py so duplicate entries are rejected before credentials are
|
||||
validated.
|
||||
unique-config-entry: done
|
||||
|
||||
# Silver
|
||||
action-exceptions:
|
||||
@@ -55,14 +45,12 @@ rules:
|
||||
comment: |
|
||||
PLANNED: Remove _LOGGER.error from coordinator.py — the message is already
|
||||
passed to UpdateFailed, so logging it separately is redundant.
|
||||
parallel-updates: todo
|
||||
parallel-updates: done
|
||||
reauthentication-flow: todo
|
||||
test-coverage:
|
||||
status: todo
|
||||
comment: |
|
||||
PLANNED: Remove unique_id from mock config entry in conftest.py. Use
|
||||
freezer-based time advancement instead of directly calling async_refresh().
|
||||
Rename result2 -> result in test files.
|
||||
PLANNED: Use freezer-based time advancement instead of directly calling async_refresh().
|
||||
|
||||
# Gold
|
||||
devices: done
|
||||
|
||||
@@ -14,6 +14,8 @@ from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
from .coordinator import HuumConfigEntry, HuumDataUpdateCoordinator
|
||||
from .entity import HuumBaseEntity
|
||||
|
||||
PARALLEL_UPDATES = 0
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
|
||||
@@ -8,6 +8,6 @@
|
||||
"integration_type": "hub",
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["tesla-fleet-api"],
|
||||
"quality_scale": "silver",
|
||||
"quality_scale": "platinum",
|
||||
"requirements": ["tesla-fleet-api==1.4.3", "teslemetry-stream==0.9.0"]
|
||||
}
|
||||
|
||||
@@ -850,3 +850,17 @@ async def assert_condition_gated_by_labs_flag(
|
||||
"conditions' feature to be enabled in Home Assistant Labs settings "
|
||||
"(feature flag: 'new_triggers_conditions')"
|
||||
) in caplog.text
|
||||
|
||||
|
||||
async def assert_trigger_gated_by_labs_flag(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, trigger: str
|
||||
) -> None:
|
||||
"""Helper to check that a trigger is gated by the labs flag."""
|
||||
|
||||
await arm_trigger(hass, trigger, None, {ATTR_LABEL_ID: "test_label"})
|
||||
assert (
|
||||
"Unnamed automation failed to setup triggers and has been disabled: Trigger "
|
||||
f"'{trigger}' requires the experimental 'New triggers and conditions' "
|
||||
"feature to be enabled in Home Assistant Labs settings (feature flag: "
|
||||
"'new_triggers_conditions')"
|
||||
) in caplog.text
|
||||
|
||||
@@ -8,12 +8,13 @@ from homeassistant.components.alarm_control_panel import (
|
||||
AlarmControlPanelEntityFeature,
|
||||
AlarmControlPanelState,
|
||||
)
|
||||
from homeassistant.const import ATTR_LABEL_ID, ATTR_SUPPORTED_FEATURES, CONF_ENTITY_ID
|
||||
from homeassistant.const import ATTR_SUPPORTED_FEATURES, CONF_ENTITY_ID
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
|
||||
from tests.components import (
|
||||
TriggerStateDescription,
|
||||
arm_trigger,
|
||||
assert_trigger_gated_by_labs_flag,
|
||||
other_states,
|
||||
parametrize_target_entities,
|
||||
parametrize_trigger_states,
|
||||
@@ -44,13 +45,7 @@ async def test_alarm_control_panel_triggers_gated_by_labs_flag(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, trigger_key: str
|
||||
) -> None:
|
||||
"""Test the ACP triggers are gated by the labs flag."""
|
||||
await arm_trigger(hass, trigger_key, None, {ATTR_LABEL_ID: "test_label"})
|
||||
assert (
|
||||
"Unnamed automation failed to setup triggers and has been disabled: Trigger "
|
||||
f"'{trigger_key}' requires the experimental 'New triggers and conditions' "
|
||||
"feature to be enabled in Home Assistant Labs settings (feature flag: "
|
||||
"'new_triggers_conditions')"
|
||||
) in caplog.text
|
||||
await assert_trigger_gated_by_labs_flag(hass, caplog, trigger_key)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("enable_labs_preview_features")
|
||||
|
||||
@@ -359,10 +359,13 @@ async def test_send_usage_with_supervisor(
|
||||
"healthy": True,
|
||||
"supported": True,
|
||||
"arch": "amd64",
|
||||
"addons": [{"slug": "test_addon"}],
|
||||
}
|
||||
),
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.hassio.get_addons_info",
|
||||
side_effect=Mock(return_value={"test_addon": {}}),
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.hassio.get_os_info",
|
||||
side_effect=Mock(return_value={}),
|
||||
@@ -578,10 +581,13 @@ async def test_send_statistics_with_supervisor(
|
||||
"healthy": True,
|
||||
"supported": True,
|
||||
"arch": "amd64",
|
||||
"addons": [{"slug": "test_addon"}],
|
||||
}
|
||||
),
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.hassio.get_addons_info",
|
||||
side_effect=Mock(return_value={"test_addon": {}}),
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.hassio.get_os_info",
|
||||
side_effect=Mock(return_value={}),
|
||||
|
||||
@@ -5,12 +5,13 @@ from typing import Any
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.assist_satellite.entity import AssistSatelliteState
|
||||
from homeassistant.const import ATTR_LABEL_ID, CONF_ENTITY_ID
|
||||
from homeassistant.const import CONF_ENTITY_ID
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
|
||||
from tests.components import (
|
||||
TriggerStateDescription,
|
||||
arm_trigger,
|
||||
assert_trigger_gated_by_labs_flag,
|
||||
other_states,
|
||||
parametrize_target_entities,
|
||||
parametrize_trigger_states,
|
||||
@@ -38,13 +39,7 @@ async def test_assist_satellite_triggers_gated_by_labs_flag(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, trigger_key: str
|
||||
) -> None:
|
||||
"""Test the Assist satellite triggers are gated by the labs flag."""
|
||||
await arm_trigger(hass, trigger_key, None, {ATTR_LABEL_ID: "test_label"})
|
||||
assert (
|
||||
"Unnamed automation failed to setup triggers and has been disabled: Trigger "
|
||||
f"'{trigger_key}' requires the experimental 'New triggers and conditions' "
|
||||
"feature to be enabled in Home Assistant Labs settings (feature flag: "
|
||||
"'new_triggers_conditions')"
|
||||
) in caplog.text
|
||||
await assert_trigger_gated_by_labs_flag(hass, caplog, trigger_key)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("enable_labs_preview_features")
|
||||
|
||||
@@ -2,17 +2,13 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.const import (
|
||||
ATTR_LABEL_ID,
|
||||
CONF_ENTITY_ID,
|
||||
STATE_UNAVAILABLE,
|
||||
STATE_UNKNOWN,
|
||||
)
|
||||
from homeassistant.const import CONF_ENTITY_ID, STATE_UNAVAILABLE, STATE_UNKNOWN
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
|
||||
from tests.components import (
|
||||
TriggerStateDescription,
|
||||
arm_trigger,
|
||||
assert_trigger_gated_by_labs_flag,
|
||||
parametrize_target_entities,
|
||||
set_or_remove_state,
|
||||
target_entities,
|
||||
@@ -30,13 +26,7 @@ async def test_button_triggers_gated_by_labs_flag(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, trigger_key: str
|
||||
) -> None:
|
||||
"""Test the button triggers are gated by the labs flag."""
|
||||
await arm_trigger(hass, trigger_key, None, {ATTR_LABEL_ID: "test_label"})
|
||||
assert (
|
||||
"Unnamed automation failed to setup triggers and has been disabled: Trigger "
|
||||
f"'{trigger_key}' requires the experimental 'New triggers and conditions' "
|
||||
"feature to be enabled in Home Assistant Labs settings (feature flag: "
|
||||
"'new_triggers_conditions')"
|
||||
) in caplog.text
|
||||
await assert_trigger_gated_by_labs_flag(hass, caplog, trigger_key)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("enable_labs_preview_features")
|
||||
|
||||
@@ -14,7 +14,6 @@ from homeassistant.components.climate.const import (
|
||||
)
|
||||
from homeassistant.components.climate.trigger import CONF_HVAC_MODE
|
||||
from homeassistant.const import (
|
||||
ATTR_LABEL_ID,
|
||||
ATTR_TEMPERATURE,
|
||||
CONF_ENTITY_ID,
|
||||
CONF_OPTIONS,
|
||||
@@ -26,6 +25,7 @@ from homeassistant.helpers.trigger import async_validate_trigger_config
|
||||
from tests.components import (
|
||||
TriggerStateDescription,
|
||||
arm_trigger,
|
||||
assert_trigger_gated_by_labs_flag,
|
||||
other_states,
|
||||
parametrize_numerical_attribute_changed_trigger_states,
|
||||
parametrize_numerical_attribute_crossed_threshold_trigger_states,
|
||||
@@ -59,13 +59,7 @@ async def test_climate_triggers_gated_by_labs_flag(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, trigger_key: str
|
||||
) -> None:
|
||||
"""Test the climate triggers are gated by the labs flag."""
|
||||
await arm_trigger(hass, trigger_key, None, {ATTR_LABEL_ID: "test_label"})
|
||||
assert (
|
||||
"Unnamed automation failed to setup triggers and has been disabled: Trigger "
|
||||
f"'{trigger_key}' requires the experimental 'New triggers and conditions' "
|
||||
"feature to be enabled in Home Assistant Labs settings (feature flag: "
|
||||
"'new_triggers_conditions')"
|
||||
) in caplog.text
|
||||
await assert_trigger_gated_by_labs_flag(hass, caplog, trigger_key)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("enable_labs_preview_features")
|
||||
|
||||
@@ -7,23 +7,52 @@ from collections.abc import AsyncGenerator, Callable, Coroutine, Generator, Mapp
|
||||
from functools import lru_cache
|
||||
from importlib.util import find_spec
|
||||
import inspect
|
||||
from ipaddress import IPv4Address, IPv4Network
|
||||
from pathlib import Path
|
||||
import re
|
||||
import string
|
||||
from typing import TYPE_CHECKING, Any
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
from aiohasupervisor import SupervisorNotFoundError
|
||||
from aiohasupervisor import SupervisorClient, SupervisorNotFoundError
|
||||
from aiohasupervisor.addons import AddonsClient
|
||||
from aiohasupervisor.backups import BackupsClient
|
||||
from aiohasupervisor.discovery import DiscoveryClient
|
||||
from aiohasupervisor.homeassistant import HomeAssistantClient
|
||||
from aiohasupervisor.host import HostClient
|
||||
from aiohasupervisor.jobs import JobsClient
|
||||
from aiohasupervisor.models import (
|
||||
AddonStage,
|
||||
AddonState,
|
||||
Discovery,
|
||||
DockerNetwork,
|
||||
GreenInfo,
|
||||
HomeAssistantInfo,
|
||||
HomeAssistantStats,
|
||||
HostInfo,
|
||||
InstalledAddon,
|
||||
JobsInfo,
|
||||
LogLevel,
|
||||
MountsInfo,
|
||||
NetworkInfo,
|
||||
OSInfo,
|
||||
Repository,
|
||||
ResolutionInfo,
|
||||
RootInfo,
|
||||
StoreAddon,
|
||||
StoreInfo,
|
||||
SupervisorInfo,
|
||||
SupervisorState,
|
||||
SupervisorStats,
|
||||
UpdateChannel,
|
||||
YellowInfo,
|
||||
)
|
||||
from aiohasupervisor.mounts import MountsClient
|
||||
from aiohasupervisor.network import NetworkClient
|
||||
from aiohasupervisor.os import OSClient
|
||||
from aiohasupervisor.resolution import ResolutionClient
|
||||
from aiohasupervisor.store import StoreClient
|
||||
from aiohasupervisor.supervisor import SupervisorManagementClient
|
||||
import pytest
|
||||
import voluptuous as vol
|
||||
|
||||
@@ -538,23 +567,239 @@ def os_green_info_fixture(supervisor_client: AsyncMock) -> AsyncMock:
|
||||
return supervisor_client.os.green_info
|
||||
|
||||
|
||||
@pytest.fixture(name="supervisor_root_info")
|
||||
def supervisor_root_info_fixture(supervisor_client: AsyncMock) -> AsyncMock:
|
||||
"""Mock root info API from supervisor."""
|
||||
supervisor_client.info.return_value = RootInfo(
|
||||
supervisor="222",
|
||||
homeassistant="0.110.0",
|
||||
hassos="1.2.3",
|
||||
docker="",
|
||||
hostname=None,
|
||||
operating_system=None,
|
||||
features=[],
|
||||
machine=None,
|
||||
machine_id=None,
|
||||
arch="",
|
||||
state=SupervisorState.RUNNING,
|
||||
supported_arch=[],
|
||||
supported=True,
|
||||
channel=UpdateChannel.STABLE,
|
||||
logging=LogLevel.INFO,
|
||||
timezone="Etc/UTC",
|
||||
)
|
||||
return supervisor_client.info
|
||||
|
||||
|
||||
@pytest.fixture(name="host_info")
|
||||
def host_info_fixture(supervisor_client: AsyncMock) -> AsyncMock:
|
||||
"""Mock host info API from supervisor."""
|
||||
supervisor_client.host.info.return_value = HostInfo(
|
||||
agent_version=None,
|
||||
apparmor_version=None,
|
||||
chassis="vm",
|
||||
virtualization=None,
|
||||
cpe=None,
|
||||
deployment=None,
|
||||
disk_free=1.6,
|
||||
disk_total=100.0,
|
||||
disk_used=98.4,
|
||||
disk_life_time=None,
|
||||
features=[],
|
||||
hostname=None,
|
||||
llmnr_hostname=None,
|
||||
kernel="4.19.0-6-amd64",
|
||||
operating_system="Debian GNU/Linux 10 (buster)",
|
||||
timezone=None,
|
||||
dt_utc=None,
|
||||
dt_synchronized=None,
|
||||
use_ntp=None,
|
||||
startup_time=None,
|
||||
boot_timestamp=None,
|
||||
broadcast_llmnr=None,
|
||||
broadcast_mdns=None,
|
||||
)
|
||||
return supervisor_client.host.info
|
||||
|
||||
|
||||
@pytest.fixture(name="homeassistant_info")
|
||||
def homeassistant_info_fixture(supervisor_client: AsyncMock) -> AsyncMock:
|
||||
"""Mock Home Assistant info API from supervisor."""
|
||||
supervisor_client.homeassistant.info.return_value = HomeAssistantInfo(
|
||||
version="1.0.0",
|
||||
version_latest="1.0.0",
|
||||
update_available=False,
|
||||
machine=None,
|
||||
ip_address=IPv4Address("172.30.32.1"),
|
||||
arch=None,
|
||||
image="homeassistant",
|
||||
boot=True,
|
||||
port=8123,
|
||||
ssl=False,
|
||||
watchdog=True,
|
||||
audio_input=None,
|
||||
audio_output=None,
|
||||
backups_exclude_database=False,
|
||||
duplicate_log_file=False,
|
||||
)
|
||||
return supervisor_client.homeassistant.info
|
||||
|
||||
|
||||
@pytest.fixture(name="supervisor_info")
|
||||
def supervisor_info_fixture(supervisor_client: AsyncMock) -> AsyncMock:
|
||||
"""Mock supervisor info API from supervisor."""
|
||||
supervisor_client.supervisor.info.return_value = SupervisorInfo(
|
||||
version="1.0.0",
|
||||
version_latest="1.0.0",
|
||||
update_available=False,
|
||||
channel=UpdateChannel.STABLE,
|
||||
arch="",
|
||||
supported=True,
|
||||
healthy=True,
|
||||
ip_address=IPv4Address("172.30.32.2"),
|
||||
timezone=None,
|
||||
logging=LogLevel.INFO,
|
||||
debug=False,
|
||||
debug_block=False,
|
||||
diagnostics=None,
|
||||
auto_update=True,
|
||||
country=None,
|
||||
detect_blocking_io=False,
|
||||
)
|
||||
return supervisor_client.supervisor.info
|
||||
|
||||
|
||||
@pytest.fixture(name="addons_list")
|
||||
def addons_list_fixture(supervisor_client: AsyncMock) -> AsyncMock:
|
||||
"""Mock addons list API from supervisor."""
|
||||
supervisor_client.addons.list.return_value = [
|
||||
InstalledAddon(
|
||||
detached=False,
|
||||
advanced=False,
|
||||
available=True,
|
||||
build=False,
|
||||
description="",
|
||||
homeassistant=None,
|
||||
icon=False,
|
||||
logo=False,
|
||||
name="test",
|
||||
repository="core",
|
||||
slug="test",
|
||||
stage=AddonStage.STABLE,
|
||||
update_available=True,
|
||||
url="https://github.com/home-assistant/addons/test",
|
||||
version_latest="2.0.1",
|
||||
version="2.0.0",
|
||||
state=AddonState.STARTED,
|
||||
),
|
||||
InstalledAddon(
|
||||
detached=False,
|
||||
advanced=False,
|
||||
available=True,
|
||||
build=False,
|
||||
description="",
|
||||
homeassistant=None,
|
||||
icon=False,
|
||||
logo=False,
|
||||
name="test2",
|
||||
repository="core",
|
||||
slug="test2",
|
||||
stage=AddonStage.STABLE,
|
||||
update_available=False,
|
||||
url="https://github.com",
|
||||
version_latest="3.1.0",
|
||||
version="3.1.0",
|
||||
state=AddonState.STOPPED,
|
||||
),
|
||||
]
|
||||
return supervisor_client.addons.list
|
||||
|
||||
|
||||
@pytest.fixture(name="network_info")
|
||||
def network_info_fixture(supervisor_client: AsyncMock) -> AsyncMock:
|
||||
"""Mock network info API from supervisor."""
|
||||
supervisor_client.network.info.return_value = NetworkInfo(
|
||||
interfaces=[],
|
||||
docker=DockerNetwork(
|
||||
interface="hassio",
|
||||
address=IPv4Network("172.30.32.0/23"),
|
||||
gateway=IPv4Address("172.30.32.1"),
|
||||
dns=IPv4Address("172.30.32.3"),
|
||||
),
|
||||
host_internet=True,
|
||||
supervisor_internet=True,
|
||||
)
|
||||
return supervisor_client.network.info
|
||||
|
||||
|
||||
@pytest.fixture(name="os_info")
|
||||
def os_info_fixture(supervisor_client: AsyncMock) -> AsyncMock:
|
||||
"""Mock os info API from supervisor."""
|
||||
supervisor_client.os.info.return_value = OSInfo(
|
||||
version="1.0.0",
|
||||
version_latest="1.0.0",
|
||||
update_available=False,
|
||||
board=None,
|
||||
boot=None,
|
||||
data_disk=None,
|
||||
boot_slots={},
|
||||
)
|
||||
return supervisor_client.os.info
|
||||
|
||||
|
||||
@pytest.fixture(name="homeassistant_stats")
|
||||
def homeassistant_stats_fixture(supervisor_client: AsyncMock) -> AsyncMock:
|
||||
"""Mock Home Assistant stats API from supervisor."""
|
||||
supervisor_client.homeassistant.stats.return_value = HomeAssistantStats(
|
||||
cpu_percent=0.99,
|
||||
memory_usage=182611968,
|
||||
memory_limit=3977146368,
|
||||
memory_percent=4.59,
|
||||
network_rx=362570232,
|
||||
network_tx=82374138,
|
||||
blk_read=46010945536,
|
||||
blk_write=15051526144,
|
||||
)
|
||||
return supervisor_client.homeassistant.stats
|
||||
|
||||
|
||||
@pytest.fixture(name="supervisor_stats")
|
||||
def supervisor_stats_fixture(supervisor_client: AsyncMock) -> AsyncMock:
|
||||
"""Mock supervisor stats API from supervisor."""
|
||||
supervisor_client.supervisor.stats.return_value = SupervisorStats(
|
||||
cpu_percent=0.99,
|
||||
memory_usage=182611968,
|
||||
memory_limit=3977146368,
|
||||
memory_percent=4.59,
|
||||
network_rx=362570232,
|
||||
network_tx=82374138,
|
||||
blk_read=46010945536,
|
||||
blk_write=15051526144,
|
||||
)
|
||||
return supervisor_client.supervisor.stats
|
||||
|
||||
|
||||
@pytest.fixture(name="supervisor_client")
|
||||
def supervisor_client() -> Generator[AsyncMock]:
|
||||
"""Mock the supervisor client."""
|
||||
mounts_info_mock = AsyncMock(spec_set=["default_backup_mount", "mounts"])
|
||||
mounts_info_mock.default_backup_mount = None
|
||||
mounts_info_mock.mounts = []
|
||||
supervisor_client = AsyncMock()
|
||||
supervisor_client.addons = AsyncMock()
|
||||
supervisor_client.discovery = AsyncMock()
|
||||
supervisor_client.homeassistant = AsyncMock()
|
||||
supervisor_client.host = AsyncMock()
|
||||
supervisor_client.jobs = AsyncMock()
|
||||
supervisor_client.jobs.info.return_value = MagicMock()
|
||||
supervisor_client.mounts.info.return_value = mounts_info_mock
|
||||
supervisor_client.os = AsyncMock()
|
||||
supervisor_client.resolution = AsyncMock()
|
||||
supervisor_client.supervisor = AsyncMock()
|
||||
supervisor_client = AsyncMock(spec=SupervisorClient)
|
||||
supervisor_client.addons = AsyncMock(spec=AddonsClient)
|
||||
supervisor_client.backups = AsyncMock(spec=BackupsClient)
|
||||
supervisor_client.discovery = AsyncMock(spec=DiscoveryClient)
|
||||
supervisor_client.homeassistant = AsyncMock(spec=HomeAssistantClient)
|
||||
supervisor_client.host = AsyncMock(spec=HostClient)
|
||||
supervisor_client.jobs = AsyncMock(spec=JobsClient)
|
||||
supervisor_client.jobs.info.return_value = JobsInfo(ignore_conditions=[], jobs=[])
|
||||
supervisor_client.mounts = AsyncMock(spec=MountsClient)
|
||||
supervisor_client.mounts.info.return_value = MagicMock(
|
||||
spec=MountsInfo, default_backup_mount=None, mounts=[]
|
||||
)
|
||||
supervisor_client.network = AsyncMock(spec=NetworkClient)
|
||||
supervisor_client.os = AsyncMock(spec=OSClient)
|
||||
supervisor_client.resolution = AsyncMock(spec=ResolutionClient)
|
||||
supervisor_client.supervisor = AsyncMock(spec=SupervisorManagementClient)
|
||||
supervisor_client.store = AsyncMock(spec=StoreClient)
|
||||
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.hassio.get_supervisor_client",
|
||||
|
||||
@@ -5,12 +5,13 @@ from typing import Any
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.cover import ATTR_IS_CLOSED, CoverState
|
||||
from homeassistant.const import ATTR_DEVICE_CLASS, ATTR_LABEL_ID, CONF_ENTITY_ID
|
||||
from homeassistant.const import ATTR_DEVICE_CLASS, CONF_ENTITY_ID
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
|
||||
from tests.components import (
|
||||
TriggerStateDescription,
|
||||
arm_trigger,
|
||||
assert_trigger_gated_by_labs_flag,
|
||||
parametrize_target_entities,
|
||||
parametrize_trigger_states,
|
||||
set_or_remove_state,
|
||||
@@ -44,13 +45,7 @@ async def test_cover_triggers_gated_by_labs_flag(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, trigger_key: str
|
||||
) -> None:
|
||||
"""Test the cover triggers are gated by the labs flag."""
|
||||
await arm_trigger(hass, trigger_key, None, {ATTR_LABEL_ID: "test_label"})
|
||||
assert (
|
||||
"Unnamed automation failed to setup triggers and has been disabled: Trigger "
|
||||
f"'{trigger_key}' requires the experimental 'New triggers and conditions' "
|
||||
"feature to be enabled in Home Assistant Labs settings (feature flag: "
|
||||
"'new_triggers_conditions')"
|
||||
) in caplog.text
|
||||
await assert_trigger_gated_by_labs_flag(hass, caplog, trigger_key)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("enable_labs_preview_features")
|
||||
|
||||
@@ -4,17 +4,13 @@ from typing import Any
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.const import (
|
||||
ATTR_LABEL_ID,
|
||||
CONF_ENTITY_ID,
|
||||
STATE_HOME,
|
||||
STATE_NOT_HOME,
|
||||
)
|
||||
from homeassistant.const import CONF_ENTITY_ID, STATE_HOME, STATE_NOT_HOME
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
|
||||
from tests.components import (
|
||||
TriggerStateDescription,
|
||||
arm_trigger,
|
||||
assert_trigger_gated_by_labs_flag,
|
||||
parametrize_target_entities,
|
||||
parametrize_trigger_states,
|
||||
set_or_remove_state,
|
||||
@@ -38,13 +34,7 @@ async def test_device_tracker_triggers_gated_by_labs_flag(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, trigger_key: str
|
||||
) -> None:
|
||||
"""Test the device_tracker triggers are gated by the labs flag."""
|
||||
await arm_trigger(hass, trigger_key, None, {ATTR_LABEL_ID: "test_label"})
|
||||
assert (
|
||||
"Unnamed automation failed to setup triggers and has been disabled: Trigger "
|
||||
f"'{trigger_key}' requires the experimental 'New triggers and conditions' "
|
||||
"feature to be enabled in Home Assistant Labs settings (feature flag: "
|
||||
"'new_triggers_conditions')"
|
||||
) in caplog.text
|
||||
await assert_trigger_gated_by_labs_flag(hass, caplog, trigger_key)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("enable_labs_preview_features")
|
||||
|
||||
@@ -5,18 +5,13 @@ from typing import Any
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.cover import ATTR_IS_CLOSED, CoverState
|
||||
from homeassistant.const import (
|
||||
ATTR_DEVICE_CLASS,
|
||||
ATTR_LABEL_ID,
|
||||
CONF_ENTITY_ID,
|
||||
STATE_OFF,
|
||||
STATE_ON,
|
||||
)
|
||||
from homeassistant.const import ATTR_DEVICE_CLASS, CONF_ENTITY_ID, STATE_OFF, STATE_ON
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
|
||||
from tests.components import (
|
||||
TriggerStateDescription,
|
||||
arm_trigger,
|
||||
assert_trigger_gated_by_labs_flag,
|
||||
parametrize_target_entities,
|
||||
parametrize_trigger_states,
|
||||
set_or_remove_state,
|
||||
@@ -47,13 +42,7 @@ async def test_door_triggers_gated_by_labs_flag(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, trigger_key: str
|
||||
) -> None:
|
||||
"""Test the door triggers are gated by the labs flag."""
|
||||
await arm_trigger(hass, trigger_key, None, {ATTR_LABEL_ID: "test_label"})
|
||||
assert (
|
||||
"Unnamed automation failed to setup triggers and has been disabled: Trigger "
|
||||
f"'{trigger_key}' requires the experimental 'New triggers and conditions' "
|
||||
"feature to be enabled in Home Assistant Labs settings (feature flag: "
|
||||
"'new_triggers_conditions')"
|
||||
) in caplog.text
|
||||
await assert_trigger_gated_by_labs_flag(hass, caplog, trigger_key)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("enable_labs_preview_features")
|
||||
|
||||
@@ -4,12 +4,13 @@ from typing import Any
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.const import ATTR_LABEL_ID, CONF_ENTITY_ID, STATE_OFF, STATE_ON
|
||||
from homeassistant.const import CONF_ENTITY_ID, STATE_OFF, STATE_ON
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
|
||||
from tests.components import (
|
||||
TriggerStateDescription,
|
||||
arm_trigger,
|
||||
assert_trigger_gated_by_labs_flag,
|
||||
parametrize_target_entities,
|
||||
parametrize_trigger_states,
|
||||
set_or_remove_state,
|
||||
@@ -34,13 +35,7 @@ async def test_fan_triggers_gated_by_labs_flag(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, trigger_key: str
|
||||
) -> None:
|
||||
"""Test the fan triggers are gated by the labs flag."""
|
||||
await arm_trigger(hass, trigger_key, None, {ATTR_LABEL_ID: "test_label"})
|
||||
assert (
|
||||
"Unnamed automation failed to setup triggers and has been disabled: Trigger "
|
||||
f"'{trigger_key}' requires the experimental 'New triggers and conditions' "
|
||||
"feature to be enabled in Home Assistant Labs settings (feature flag: "
|
||||
"'new_triggers_conditions')"
|
||||
) in caplog.text
|
||||
await assert_trigger_gated_by_labs_flag(hass, caplog, trigger_key)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("enable_labs_preview_features")
|
||||
|
||||
@@ -5,18 +5,13 @@ from typing import Any
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.cover import ATTR_IS_CLOSED, CoverState
|
||||
from homeassistant.const import (
|
||||
ATTR_DEVICE_CLASS,
|
||||
ATTR_LABEL_ID,
|
||||
CONF_ENTITY_ID,
|
||||
STATE_OFF,
|
||||
STATE_ON,
|
||||
)
|
||||
from homeassistant.const import ATTR_DEVICE_CLASS, CONF_ENTITY_ID, STATE_OFF, STATE_ON
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
|
||||
from tests.components import (
|
||||
TriggerStateDescription,
|
||||
arm_trigger,
|
||||
assert_trigger_gated_by_labs_flag,
|
||||
parametrize_target_entities,
|
||||
parametrize_trigger_states,
|
||||
set_or_remove_state,
|
||||
@@ -47,13 +42,7 @@ async def test_garage_door_triggers_gated_by_labs_flag(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, trigger_key: str
|
||||
) -> None:
|
||||
"""Test the garage door triggers are gated by the labs flag."""
|
||||
await arm_trigger(hass, trigger_key, None, {ATTR_LABEL_ID: "test_label"})
|
||||
assert (
|
||||
"Unnamed automation failed to setup triggers and has been disabled: Trigger "
|
||||
f"'{trigger_key}' requires the experimental 'New triggers and conditions' "
|
||||
"feature to be enabled in Home Assistant Labs settings (feature flag: "
|
||||
"'new_triggers_conditions')"
|
||||
) in caplog.text
|
||||
await assert_trigger_gated_by_labs_flag(hass, caplog, trigger_key)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("enable_labs_preview_features")
|
||||
|
||||
@@ -5,12 +5,13 @@ from typing import Any
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.cover import ATTR_IS_CLOSED, CoverState
|
||||
from homeassistant.const import ATTR_DEVICE_CLASS, ATTR_LABEL_ID, CONF_ENTITY_ID
|
||||
from homeassistant.const import ATTR_DEVICE_CLASS, CONF_ENTITY_ID
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
|
||||
from tests.components import (
|
||||
TriggerStateDescription,
|
||||
arm_trigger,
|
||||
assert_trigger_gated_by_labs_flag,
|
||||
parametrize_target_entities,
|
||||
parametrize_trigger_states,
|
||||
set_or_remove_state,
|
||||
@@ -35,13 +36,7 @@ async def test_gate_triggers_gated_by_labs_flag(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, trigger_key: str
|
||||
) -> None:
|
||||
"""Test the gate triggers are gated by the labs flag."""
|
||||
await arm_trigger(hass, trigger_key, None, {ATTR_LABEL_ID: "test_label"})
|
||||
assert (
|
||||
"Unnamed automation failed to setup triggers and has been disabled: Trigger "
|
||||
f"'{trigger_key}' requires the experimental 'New triggers and conditions' "
|
||||
"feature to be enabled in Home Assistant Labs settings (feature flag: "
|
||||
"'new_triggers_conditions')"
|
||||
) in caplog.text
|
||||
await assert_trigger_gated_by_labs_flag(hass, caplog, trigger_key)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("enable_labs_preview_features")
|
||||
|
||||
@@ -84,6 +84,7 @@ def mock_addon_store_info(
|
||||
supervisor_client.store.addon_info.return_value = addon_info = Mock(
|
||||
spec=StoreAddonComplete,
|
||||
slug="test",
|
||||
name="test",
|
||||
repository="core",
|
||||
available=True,
|
||||
installed=False,
|
||||
@@ -109,15 +110,18 @@ def mock_addon_info(
|
||||
supervisor_client.addons.addon_info.return_value = addon_info = Mock(
|
||||
spec=InstalledAddonComplete,
|
||||
slug="test",
|
||||
name="test",
|
||||
repository="core",
|
||||
available=False,
|
||||
hostname="",
|
||||
options={},
|
||||
state="unknown",
|
||||
update_available=False,
|
||||
version=None,
|
||||
version="1.0.0",
|
||||
version_latest="1.0.0",
|
||||
supervisor_api=False,
|
||||
supervisor_role="default",
|
||||
icon=False,
|
||||
)
|
||||
addon_info.name = "test"
|
||||
addon_info.to_dict = MethodType(
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
"""Fixtures for Hass.io."""
|
||||
|
||||
from collections.abc import Generator
|
||||
from dataclasses import replace
|
||||
import os
|
||||
import re
|
||||
from unittest.mock import AsyncMock, patch
|
||||
from unittest.mock import AsyncMock, Mock, patch
|
||||
|
||||
from aiohasupervisor.models import AddonsStats, AddonState
|
||||
from aiohasupervisor.models import AddonsStats, AddonState, InstalledAddonComplete
|
||||
from aiohttp.test_utils import TestClient
|
||||
import pytest
|
||||
|
||||
@@ -80,6 +81,15 @@ def all_setup_requests(
|
||||
addon_changelog: AsyncMock,
|
||||
addon_stats: AsyncMock,
|
||||
jobs_info: AsyncMock,
|
||||
host_info: AsyncMock,
|
||||
supervisor_root_info: AsyncMock,
|
||||
homeassistant_info: AsyncMock,
|
||||
supervisor_info: AsyncMock,
|
||||
addons_list: AsyncMock,
|
||||
network_info: AsyncMock,
|
||||
os_info: AsyncMock,
|
||||
homeassistant_stats: AsyncMock,
|
||||
supervisor_stats: AsyncMock,
|
||||
) -> None:
|
||||
"""Mock all setup requests."""
|
||||
include_addons = hasattr(request, "param") and request.param.get(
|
||||
@@ -88,87 +98,26 @@ def all_setup_requests(
|
||||
|
||||
aioclient_mock.post("http://127.0.0.1/homeassistant/options", json={"result": "ok"})
|
||||
aioclient_mock.post("http://127.0.0.1/supervisor/options", json={"result": "ok"})
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"supervisor": "222",
|
||||
"homeassistant": "0.110.0",
|
||||
"hassos": "1.2.3",
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/host/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"chassis": "vm",
|
||||
"operating_system": "Debian GNU/Linux 10 (buster)",
|
||||
"kernel": "4.19.0-6-amd64",
|
||||
"disk_free": 1.6,
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/core/info",
|
||||
json={"result": "ok", "data": {"version_latest": "1.0.0", "version": "1.0.0"}},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/os/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"version_latest": "1.0.0",
|
||||
"version": "1.0.0",
|
||||
"update_available": False,
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"result": "ok",
|
||||
"version": "1.0.0",
|
||||
"version_latest": "1.0.0",
|
||||
"auto_update": True,
|
||||
"addons": [
|
||||
{
|
||||
"name": "test",
|
||||
"slug": "test",
|
||||
"update_available": False,
|
||||
"version": "1.0.0",
|
||||
"version_latest": "1.0.0",
|
||||
"repository": "core",
|
||||
"state": "started",
|
||||
"icon": False,
|
||||
},
|
||||
{
|
||||
"name": "test2",
|
||||
"slug": "test2",
|
||||
"update_available": False,
|
||||
"version": "1.0.0",
|
||||
"version_latest": "1.0.0",
|
||||
"repository": "core",
|
||||
"state": "started",
|
||||
"icon": False,
|
||||
},
|
||||
]
|
||||
if include_addons
|
||||
else [],
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/ingress/panels", json={"result": "ok", "data": {"panels": {}}}
|
||||
)
|
||||
|
||||
if include_addons:
|
||||
addons_list.return_value[0] = replace(
|
||||
addons_list.return_value[0],
|
||||
version="1.0.0",
|
||||
version_latest="1.0.0",
|
||||
update_available=False,
|
||||
)
|
||||
addons_list.return_value[1] = replace(
|
||||
addons_list.return_value[1],
|
||||
version="1.0.0",
|
||||
version_latest="1.0.0",
|
||||
state=AddonState.STARTED,
|
||||
)
|
||||
else:
|
||||
addons_list.return_value = []
|
||||
|
||||
addon_installed.return_value.update_available = False
|
||||
addon_installed.return_value.version = "1.0.0"
|
||||
addon_installed.return_value.version_latest = "1.0.0"
|
||||
@@ -177,56 +126,26 @@ def all_setup_requests(
|
||||
addon_installed.return_value.icon = False
|
||||
|
||||
def mock_addon_info(slug: str):
|
||||
addon = Mock(
|
||||
spec=InstalledAddonComplete,
|
||||
to_dict=addon_installed.return_value.to_dict,
|
||||
**addon_installed.return_value.to_dict(),
|
||||
)
|
||||
if slug == "test":
|
||||
addon_installed.return_value.name = "test"
|
||||
addon_installed.return_value.slug = "test"
|
||||
addon_installed.return_value.url = (
|
||||
"https://github.com/home-assistant/addons/test"
|
||||
)
|
||||
addon_installed.return_value.auto_update = True
|
||||
addon.name = "test"
|
||||
addon.slug = "test"
|
||||
addon.url = "https://github.com/home-assistant/addons/test"
|
||||
addon.auto_update = True
|
||||
else:
|
||||
addon_installed.return_value.name = "test2"
|
||||
addon_installed.return_value.slug = "test2"
|
||||
addon_installed.return_value.url = "https://github.com"
|
||||
addon_installed.return_value.auto_update = False
|
||||
addon.name = "test2"
|
||||
addon.slug = "test2"
|
||||
addon.url = "https://github.com"
|
||||
addon.auto_update = False
|
||||
|
||||
return addon_installed.return_value
|
||||
return addon
|
||||
|
||||
addon_installed.side_effect = mock_addon_info
|
||||
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/core/stats",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"cpu_percent": 0.99,
|
||||
"memory_usage": 182611968,
|
||||
"memory_limit": 3977146368,
|
||||
"memory_percent": 4.59,
|
||||
"network_rx": 362570232,
|
||||
"network_tx": 82374138,
|
||||
"blk_read": 46010945536,
|
||||
"blk_write": 15051526144,
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/stats",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"cpu_percent": 0.99,
|
||||
"memory_usage": 182611968,
|
||||
"memory_limit": 3977146368,
|
||||
"memory_percent": 4.59,
|
||||
"network_rx": 362570232,
|
||||
"network_tx": 82374138,
|
||||
"blk_read": 46010945536,
|
||||
"blk_write": 15051526144,
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
async def mock_addon_stats(addon: str) -> AddonsStats:
|
||||
"""Mock addon stats for test and test2."""
|
||||
if addon == "test2":
|
||||
@@ -252,16 +171,6 @@ def all_setup_requests(
|
||||
)
|
||||
|
||||
addon_stats.side_effect = mock_addon_stats
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/network/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"host_internet": True,
|
||||
"supervisor_internet": True,
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/jobs/info",
|
||||
|
||||
@@ -4,9 +4,10 @@ from dataclasses import replace
|
||||
from datetime import timedelta
|
||||
import os
|
||||
from pathlib import PurePath
|
||||
from unittest.mock import AsyncMock, patch
|
||||
from unittest.mock import AsyncMock, Mock, patch
|
||||
from uuid import uuid4
|
||||
|
||||
from aiohasupervisor.models import AddonState, InstalledAddonComplete
|
||||
from aiohasupervisor.models.mounts import (
|
||||
CIFSMountResponse,
|
||||
MountsInfo,
|
||||
@@ -41,133 +42,51 @@ def mock_all(
|
||||
addon_stats: AsyncMock,
|
||||
resolution_info: AsyncMock,
|
||||
jobs_info: AsyncMock,
|
||||
host_info: AsyncMock,
|
||||
supervisor_root_info: AsyncMock,
|
||||
homeassistant_info: AsyncMock,
|
||||
supervisor_info: AsyncMock,
|
||||
addons_list: AsyncMock,
|
||||
network_info: AsyncMock,
|
||||
os_info: AsyncMock,
|
||||
homeassistant_stats: AsyncMock,
|
||||
supervisor_stats: AsyncMock,
|
||||
) -> None:
|
||||
"""Mock all setup requests."""
|
||||
aioclient_mock.post("http://127.0.0.1/homeassistant/options", json={"result": "ok"})
|
||||
aioclient_mock.post("http://127.0.0.1/supervisor/options", json={"result": "ok"})
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"supervisor": "222",
|
||||
"homeassistant": "0.110.0",
|
||||
"hassos": "1.2.3",
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/host/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"chassis": "vm",
|
||||
"operating_system": "Debian GNU/Linux 10 (buster)",
|
||||
"kernel": "4.19.0-6-amd64",
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/core/info",
|
||||
json={"result": "ok", "data": {"version_latest": "1.0.0", "version": "1.0.0"}},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/os/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"version_latest": "1.0.0",
|
||||
"version": "1.0.0",
|
||||
"update_available": False,
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"result": "ok",
|
||||
"version": "1.0.0",
|
||||
"version_latest": "1.0.0",
|
||||
"auto_update": True,
|
||||
"addons": [
|
||||
{
|
||||
"name": "test",
|
||||
"state": "started",
|
||||
"slug": "test",
|
||||
"installed": True,
|
||||
"update_available": True,
|
||||
"version": "2.0.0",
|
||||
"version_latest": "2.0.1",
|
||||
"repository": "core",
|
||||
"url": "https://github.com/home-assistant/addons/test",
|
||||
"icon": False,
|
||||
},
|
||||
{
|
||||
"name": "test2",
|
||||
"state": "stopped",
|
||||
"slug": "test2",
|
||||
"installed": True,
|
||||
"update_available": False,
|
||||
"version": "3.1.0",
|
||||
"version_latest": "3.1.0",
|
||||
"repository": "core",
|
||||
"url": "https://github.com",
|
||||
"icon": False,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/core/stats",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"cpu_percent": 0.99,
|
||||
"memory_usage": 182611968,
|
||||
"memory_limit": 3977146368,
|
||||
"memory_percent": 4.59,
|
||||
"network_rx": 362570232,
|
||||
"network_tx": 82374138,
|
||||
"blk_read": 46010945536,
|
||||
"blk_write": 15051526144,
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/stats",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"cpu_percent": 0.99,
|
||||
"memory_usage": 182611968,
|
||||
"memory_limit": 3977146368,
|
||||
"memory_percent": 4.59,
|
||||
"network_rx": 362570232,
|
||||
"network_tx": 82374138,
|
||||
"blk_read": 46010945536,
|
||||
"blk_write": 15051526144,
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/ingress/panels", json={"result": "ok", "data": {"panels": {}}}
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/network/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"host_internet": True,
|
||||
"supervisor_internet": True,
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
def mock_addon_info(slug: str):
|
||||
addon = Mock(
|
||||
spec=InstalledAddonComplete,
|
||||
to_dict=addon_installed.return_value.to_dict,
|
||||
**addon_installed.return_value.to_dict(),
|
||||
)
|
||||
if slug == "test":
|
||||
addon.name = "test"
|
||||
addon.slug = "test"
|
||||
addon.version = "2.0.0"
|
||||
addon.version_latest = "2.0.1"
|
||||
addon.update_available = True
|
||||
addon.state = AddonState.STARTED
|
||||
addon.url = "https://github.com/home-assistant/addons/test"
|
||||
addon.auto_update = True
|
||||
else:
|
||||
addon.name = "test2"
|
||||
addon.slug = "test2"
|
||||
addon.version = "3.1.0"
|
||||
addon.version_latest = "3.1.0"
|
||||
addon.update_available = False
|
||||
addon.state = AddonState.STOPPED
|
||||
addon.url = "https://github.com"
|
||||
addon.auto_update = False
|
||||
|
||||
return addon
|
||||
|
||||
addon_installed.side_effect = mock_addon_info
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"""Test websocket API."""
|
||||
|
||||
from collections.abc import Generator
|
||||
from dataclasses import replace
|
||||
from typing import Any
|
||||
from unittest.mock import AsyncMock, patch
|
||||
from uuid import UUID, uuid4
|
||||
@@ -28,77 +29,24 @@ def mock_all(
|
||||
supervisor_is_connected: AsyncMock,
|
||||
resolution_info: AsyncMock,
|
||||
addon_info: AsyncMock,
|
||||
host_info: AsyncMock,
|
||||
supervisor_root_info: AsyncMock,
|
||||
homeassistant_info: AsyncMock,
|
||||
supervisor_info: AsyncMock,
|
||||
addons_list: AsyncMock,
|
||||
network_info: AsyncMock,
|
||||
os_info: AsyncMock,
|
||||
) -> None:
|
||||
"""Mock all setup requests."""
|
||||
aioclient_mock.post("http://127.0.0.1/homeassistant/options", json={"result": "ok"})
|
||||
aioclient_mock.post("http://127.0.0.1/supervisor/options", json={"result": "ok"})
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {"supervisor": "222", "homeassistant": "0.110.0", "hassos": None},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/host/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"chassis": "vm",
|
||||
"operating_system": "Debian GNU/Linux 10 (buster)",
|
||||
"kernel": "4.19.0-6-amd64",
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/core/info",
|
||||
json={"result": "ok", "data": {"version_latest": "1.0.0", "version": "1.0.0"}},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/os/info",
|
||||
json={"result": "ok", "data": {"version_latest": "1.0.0"}},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"version": "1.0.0",
|
||||
"version_latest": "1.0.0",
|
||||
"auto_update": True,
|
||||
"addons": [
|
||||
{
|
||||
"name": "test",
|
||||
"state": "started",
|
||||
"slug": "test",
|
||||
"installed": True,
|
||||
"update_available": True,
|
||||
"icon": False,
|
||||
"version": "2.0.0",
|
||||
"version_latest": "2.0.1",
|
||||
"repository": "core",
|
||||
"url": "https://github.com/home-assistant/addons/test",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
supervisor_root_info.return_value = replace(
|
||||
supervisor_root_info.return_value, hassos=None
|
||||
)
|
||||
addons_list.return_value.pop(1)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/ingress/panels", json={"result": "ok", "data": {"panels": {}}}
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/network/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"host_internet": True,
|
||||
"supervisor_internet": True,
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
"""Test Supervisor diagnostics."""
|
||||
|
||||
from dataclasses import replace
|
||||
import os
|
||||
from unittest.mock import AsyncMock, patch
|
||||
from unittest.mock import AsyncMock, Mock, patch
|
||||
|
||||
from aiohasupervisor.models import AddonState, InstalledAddonComplete
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.hassio import DOMAIN
|
||||
@@ -26,135 +28,68 @@ def mock_all(
|
||||
addon_changelog: AsyncMock,
|
||||
resolution_info: AsyncMock,
|
||||
jobs_info: AsyncMock,
|
||||
host_info: AsyncMock,
|
||||
supervisor_root_info: AsyncMock,
|
||||
homeassistant_info: AsyncMock,
|
||||
supervisor_info: AsyncMock,
|
||||
addons_list: AsyncMock,
|
||||
network_info: AsyncMock,
|
||||
os_info: AsyncMock,
|
||||
homeassistant_stats: AsyncMock,
|
||||
supervisor_stats: AsyncMock,
|
||||
) -> None:
|
||||
"""Mock all setup requests."""
|
||||
aioclient_mock.post("http://127.0.0.1/homeassistant/options", json={"result": "ok"})
|
||||
aioclient_mock.post("http://127.0.0.1/supervisor/options", json={"result": "ok"})
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"supervisor": "222",
|
||||
"homeassistant": "0.110.0",
|
||||
"hassos": "1.2.3",
|
||||
},
|
||||
},
|
||||
homeassistant_info.return_value = replace(
|
||||
homeassistant_info.return_value,
|
||||
version="1.0.0dev221",
|
||||
version_latest="1.0.0dev222",
|
||||
update_available=True,
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/host/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"chassis": "vm",
|
||||
"operating_system": "Debian GNU/Linux 10 (buster)",
|
||||
"kernel": "4.19.0-6-amd64",
|
||||
},
|
||||
},
|
||||
},
|
||||
os_info.return_value = replace(
|
||||
os_info.return_value,
|
||||
version="1.0.0dev2221",
|
||||
version_latest="1.0.0dev2222",
|
||||
update_available=True,
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/core/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {"version_latest": "1.0.0dev222", "version": "1.0.0dev221"},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/os/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"version_latest": "1.0.0dev2222",
|
||||
"version": "1.0.0dev2221",
|
||||
"update_available": False,
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"result": "ok",
|
||||
"version": "1.0.0",
|
||||
"version_latest": "1.0.1dev222",
|
||||
"addons": [
|
||||
{
|
||||
"name": "test",
|
||||
"state": "started",
|
||||
"slug": "test",
|
||||
"installed": True,
|
||||
"update_available": True,
|
||||
"icon": False,
|
||||
"version": "2.0.0",
|
||||
"version_latest": "2.0.1",
|
||||
"repository": "core",
|
||||
"url": "https://github.com/home-assistant/addons/test",
|
||||
},
|
||||
{
|
||||
"name": "test2",
|
||||
"state": "stopped",
|
||||
"slug": "test2",
|
||||
"installed": True,
|
||||
"update_available": False,
|
||||
"icon": True,
|
||||
"version": "3.1.0",
|
||||
"version_latest": "3.1.0",
|
||||
"repository": "core",
|
||||
"url": "https://github.com",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/core/stats",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"cpu_percent": 0.99,
|
||||
"memory_usage": 182611968,
|
||||
"memory_limit": 3977146368,
|
||||
"memory_percent": 4.59,
|
||||
"network_rx": 362570232,
|
||||
"network_tx": 82374138,
|
||||
"blk_read": 46010945536,
|
||||
"blk_write": 15051526144,
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/stats",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"cpu_percent": 0.99,
|
||||
"memory_usage": 182611968,
|
||||
"memory_limit": 3977146368,
|
||||
"memory_percent": 4.59,
|
||||
"network_rx": 362570232,
|
||||
"network_tx": 82374138,
|
||||
"blk_read": 46010945536,
|
||||
"blk_write": 15051526144,
|
||||
},
|
||||
},
|
||||
supervisor_info.return_value = replace(
|
||||
supervisor_info.return_value,
|
||||
version_latest="1.0.1dev222",
|
||||
update_available=True,
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/ingress/panels", json={"result": "ok", "data": {"panels": {}}}
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/network/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"host_internet": True,
|
||||
"supervisor_internet": True,
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
def mock_addon_info(slug: str):
|
||||
addon = Mock(
|
||||
spec=InstalledAddonComplete,
|
||||
to_dict=addon_installed.return_value.to_dict,
|
||||
**addon_installed.return_value.to_dict(),
|
||||
)
|
||||
if slug == "test":
|
||||
addon.name = "test"
|
||||
addon.slug = "test"
|
||||
addon.version = "2.0.0"
|
||||
addon.version_latest = "2.0.1"
|
||||
addon.update_available = True
|
||||
addon.state = AddonState.STARTED
|
||||
addon.url = "https://github.com/home-assistant/addons/test"
|
||||
addon.auto_update = True
|
||||
else:
|
||||
addon.name = "test2"
|
||||
addon.slug = "test2"
|
||||
addon.version = "3.1.0"
|
||||
addon.version_latest = "3.1.0"
|
||||
addon.update_available = False
|
||||
addon.state = AddonState.STOPPED
|
||||
addon.url = "https://github.com"
|
||||
addon.auto_update = False
|
||||
|
||||
return addon
|
||||
|
||||
addon_installed.side_effect = mock_addon_info
|
||||
|
||||
|
||||
async def test_diagnostics(
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
|
||||
from collections.abc import Generator
|
||||
from http import HTTPStatus
|
||||
from unittest.mock import AsyncMock, Mock, patch
|
||||
from unittest.mock import AsyncMock, patch
|
||||
from uuid import uuid4
|
||||
|
||||
from aiohasupervisor import SupervisorError
|
||||
from aiohasupervisor.models import Discovery
|
||||
from aiohttp.test_utils import TestClient
|
||||
import pytest
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.components.hassio.handler import HassioAPIError
|
||||
from homeassistant.components.mqtt import DOMAIN as MQTT_DOMAIN
|
||||
from homeassistant.const import EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STARTED
|
||||
from homeassistant.core import HomeAssistant
|
||||
@@ -103,6 +103,7 @@ async def test_hassio_discovery_startup_done(
|
||||
mock_mqtt: type[config_entries.ConfigFlow],
|
||||
addon_installed: AsyncMock,
|
||||
get_addon_discovery_info: AsyncMock,
|
||||
supervisor_root_info: AsyncMock,
|
||||
) -> None:
|
||||
"""Test startup and discovery with hass discovery."""
|
||||
aioclient_mock.post(
|
||||
@@ -125,15 +126,12 @@ async def test_hassio_discovery_startup_done(
|
||||
]
|
||||
addon_installed.return_value.name = "Mosquitto Test"
|
||||
|
||||
supervisor_root_info.side_effect = SupervisorError()
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.hassio.HassIO.update_hass_api",
|
||||
return_value={"result": "ok"},
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.hassio.HassIO.get_info",
|
||||
Mock(side_effect=HassioAPIError()),
|
||||
),
|
||||
):
|
||||
await hass.async_start()
|
||||
await async_setup_component(hass, "hassio", {})
|
||||
|
||||
@@ -14,169 +14,6 @@ from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
from tests.test_util.aiohttp import AiohttpClientMocker
|
||||
|
||||
|
||||
async def test_api_info(
|
||||
hassio_handler: HassIO, aioclient_mock: AiohttpClientMocker
|
||||
) -> None:
|
||||
"""Test setup with API generic info."""
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {"supervisor": "222", "homeassistant": "0.110.0", "hassos": None},
|
||||
},
|
||||
)
|
||||
|
||||
data = await hassio_handler.get_info()
|
||||
assert aioclient_mock.call_count == 1
|
||||
assert data["hassos"] is None
|
||||
assert data["homeassistant"] == "0.110.0"
|
||||
assert data["supervisor"] == "222"
|
||||
|
||||
|
||||
async def test_api_info_error(
|
||||
hassio_handler: HassIO, aioclient_mock: AiohttpClientMocker
|
||||
) -> None:
|
||||
"""Test setup with API Home Assistant info error."""
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/info", json={"result": "error", "message": None}
|
||||
)
|
||||
|
||||
with pytest.raises(HassioAPIError):
|
||||
await hassio_handler.get_info()
|
||||
|
||||
assert aioclient_mock.call_count == 1
|
||||
|
||||
|
||||
async def test_api_host_info(
|
||||
hassio_handler: HassIO, aioclient_mock: AiohttpClientMocker
|
||||
) -> None:
|
||||
"""Test setup with API Host info."""
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/host/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"chassis": "vm",
|
||||
"operating_system": "Debian GNU/Linux 10 (buster)",
|
||||
"kernel": "4.19.0-6-amd64",
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
data = await hassio_handler.get_host_info()
|
||||
assert aioclient_mock.call_count == 1
|
||||
assert data["chassis"] == "vm"
|
||||
assert data["kernel"] == "4.19.0-6-amd64"
|
||||
assert data["operating_system"] == "Debian GNU/Linux 10 (buster)"
|
||||
|
||||
|
||||
async def test_api_supervisor_info(
|
||||
hassio_handler: HassIO, aioclient_mock: AiohttpClientMocker
|
||||
) -> None:
|
||||
"""Test setup with API Supervisor info."""
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {"supported": True, "version": "2020.11.1", "channel": "stable"},
|
||||
},
|
||||
)
|
||||
|
||||
data = await hassio_handler.get_supervisor_info()
|
||||
assert aioclient_mock.call_count == 1
|
||||
assert data["supported"]
|
||||
assert data["version"] == "2020.11.1"
|
||||
assert data["channel"] == "stable"
|
||||
|
||||
|
||||
async def test_api_os_info(
|
||||
hassio_handler: HassIO, aioclient_mock: AiohttpClientMocker
|
||||
) -> None:
|
||||
"""Test setup with API OS info."""
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/os/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {"board": "odroid-n2", "version": "2020.11.1"},
|
||||
},
|
||||
)
|
||||
|
||||
data = await hassio_handler.get_os_info()
|
||||
assert aioclient_mock.call_count == 1
|
||||
assert data["board"] == "odroid-n2"
|
||||
assert data["version"] == "2020.11.1"
|
||||
|
||||
|
||||
async def test_api_host_info_error(
|
||||
hassio_handler: HassIO, aioclient_mock: AiohttpClientMocker
|
||||
) -> None:
|
||||
"""Test setup with API Home Assistant info error."""
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/host/info", json={"result": "error", "message": None}
|
||||
)
|
||||
|
||||
with pytest.raises(HassioAPIError):
|
||||
await hassio_handler.get_host_info()
|
||||
|
||||
assert aioclient_mock.call_count == 1
|
||||
|
||||
|
||||
async def test_api_core_info(
|
||||
hassio_handler: HassIO, aioclient_mock: AiohttpClientMocker
|
||||
) -> None:
|
||||
"""Test setup with API Home Assistant Core info."""
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/core/info",
|
||||
json={"result": "ok", "data": {"version_latest": "1.0.0"}},
|
||||
)
|
||||
|
||||
data = await hassio_handler.get_core_info()
|
||||
assert aioclient_mock.call_count == 1
|
||||
assert data["version_latest"] == "1.0.0"
|
||||
|
||||
|
||||
async def test_api_core_info_error(
|
||||
hassio_handler: HassIO, aioclient_mock: AiohttpClientMocker
|
||||
) -> None:
|
||||
"""Test setup with API Home Assistant Core info error."""
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/core/info", json={"result": "error", "message": None}
|
||||
)
|
||||
|
||||
with pytest.raises(HassioAPIError):
|
||||
await hassio_handler.get_core_info()
|
||||
|
||||
assert aioclient_mock.call_count == 1
|
||||
|
||||
|
||||
async def test_api_core_stats(
|
||||
hassio_handler: HassIO, aioclient_mock: AiohttpClientMocker
|
||||
) -> None:
|
||||
"""Test setup with API Add-on stats."""
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/core/stats",
|
||||
json={"result": "ok", "data": {"memory_percent": 0.01}},
|
||||
)
|
||||
|
||||
data = await hassio_handler.get_core_stats()
|
||||
assert data["memory_percent"] == 0.01
|
||||
assert aioclient_mock.call_count == 1
|
||||
|
||||
|
||||
async def test_api_supervisor_stats(
|
||||
hassio_handler: HassIO, aioclient_mock: AiohttpClientMocker
|
||||
) -> None:
|
||||
"""Test setup with API Add-on stats."""
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/stats",
|
||||
json={"result": "ok", "data": {"memory_percent": 0.01}},
|
||||
)
|
||||
|
||||
data = await hassio_handler.get_supervisor_stats()
|
||||
assert data["memory_percent"] == 0.01
|
||||
assert aioclient_mock.call_count == 1
|
||||
|
||||
|
||||
async def test_api_ingress_panels(
|
||||
hassio_handler: HassIO, aioclient_mock: AiohttpClientMocker
|
||||
) -> None:
|
||||
@@ -207,7 +44,7 @@ async def test_api_ingress_panels(
|
||||
@pytest.mark.parametrize(
|
||||
("api_call", "method", "payload"),
|
||||
[
|
||||
("get_network_info", "GET", None),
|
||||
("get_ingress_panels", "GET", None),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("socket_enabled")
|
||||
|
||||
@@ -1,15 +1,20 @@
|
||||
"""The tests for the hassio component."""
|
||||
|
||||
from dataclasses import replace
|
||||
from datetime import timedelta
|
||||
import os
|
||||
from pathlib import PurePath
|
||||
from typing import Any
|
||||
from unittest.mock import AsyncMock, patch
|
||||
from unittest.mock import AsyncMock, Mock, patch
|
||||
|
||||
from aiohasupervisor import SupervisorError
|
||||
from aiohasupervisor.models import AddonsStats
|
||||
from aiohasupervisor.models.mounts import (
|
||||
from aiohasupervisor.models import (
|
||||
AddonsStats,
|
||||
AddonStage,
|
||||
AddonState,
|
||||
CIFSMountResponse,
|
||||
InstalledAddon,
|
||||
InstalledAddonComplete,
|
||||
MountsInfo,
|
||||
MountState,
|
||||
MountType,
|
||||
@@ -52,135 +57,42 @@ from tests.test_util.aiohttp import AiohttpClientMocker
|
||||
MOCK_ENVIRON = {"SUPERVISOR": "127.0.0.1", "SUPERVISOR_TOKEN": "abcdefgh"}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def extra_os_info():
|
||||
"""Extra os/info."""
|
||||
return {}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def os_info(extra_os_info):
|
||||
"""Mock os/info."""
|
||||
return {
|
||||
"json": {
|
||||
"result": "ok",
|
||||
"data": {"version_latest": "1.0.0", "version": "1.0.0", **extra_os_info},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def mock_all(
|
||||
aioclient_mock: AiohttpClientMocker,
|
||||
os_info: AsyncMock,
|
||||
store_info: AsyncMock,
|
||||
addon_info: AsyncMock,
|
||||
addon_stats: AsyncMock,
|
||||
addon_changelog: AsyncMock,
|
||||
resolution_info: AsyncMock,
|
||||
jobs_info: AsyncMock,
|
||||
host_info: AsyncMock,
|
||||
supervisor_root_info: AsyncMock,
|
||||
homeassistant_info: AsyncMock,
|
||||
supervisor_info: AsyncMock,
|
||||
addons_list: AsyncMock,
|
||||
network_info: AsyncMock,
|
||||
os_info: AsyncMock,
|
||||
homeassistant_stats: AsyncMock,
|
||||
supervisor_stats: AsyncMock,
|
||||
addon_installed: AsyncMock,
|
||||
) -> None:
|
||||
"""Mock all setup requests."""
|
||||
aioclient_mock.post("http://127.0.0.1/homeassistant/options", json={"result": "ok"})
|
||||
aioclient_mock.post("http://127.0.0.1/supervisor/options", json={"result": "ok"})
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"supervisor": "222",
|
||||
"homeassistant": "0.110.0",
|
||||
"hassos": "1.2.3",
|
||||
},
|
||||
},
|
||||
addons_list.return_value[0] = replace(
|
||||
addons_list.return_value[0],
|
||||
version="1.0.0",
|
||||
version_latest="1.0.0",
|
||||
update_available=False,
|
||||
state=AddonState.STOPPED,
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/host/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"chassis": "vm",
|
||||
"operating_system": "Debian GNU/Linux 10 (buster)",
|
||||
"kernel": "4.19.0-6-amd64",
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/core/info",
|
||||
json={"result": "ok", "data": {"version_latest": "1.0.0", "version": "1.0.0"}},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/os/info",
|
||||
**os_info,
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"version_latest": "1.0.0",
|
||||
"version": "1.0.0",
|
||||
"auto_update": True,
|
||||
"addons": [
|
||||
{
|
||||
"name": "test",
|
||||
"slug": "test",
|
||||
"state": "stopped",
|
||||
"update_available": False,
|
||||
"version": "1.0.0",
|
||||
"version_latest": "1.0.0",
|
||||
"repository": "core",
|
||||
"icon": False,
|
||||
},
|
||||
{
|
||||
"name": "test2",
|
||||
"slug": "test2",
|
||||
"state": "stopped",
|
||||
"update_available": False,
|
||||
"version": "1.0.0",
|
||||
"version_latest": "1.0.0",
|
||||
"repository": "core",
|
||||
"icon": False,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/core/stats",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"cpu_percent": 0.99,
|
||||
"memory_usage": 182611968,
|
||||
"memory_limit": 3977146368,
|
||||
"memory_percent": 4.59,
|
||||
"network_rx": 362570232,
|
||||
"network_tx": 82374138,
|
||||
"blk_read": 46010945536,
|
||||
"blk_write": 15051526144,
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/stats",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"cpu_percent": 0.99,
|
||||
"memory_usage": 182611968,
|
||||
"memory_limit": 3977146368,
|
||||
"memory_percent": 4.59,
|
||||
"network_rx": 362570232,
|
||||
"network_tx": 82374138,
|
||||
"blk_read": 46010945536,
|
||||
"blk_write": 15051526144,
|
||||
},
|
||||
},
|
||||
addons_list.return_value[1] = replace(
|
||||
addons_list.return_value[1],
|
||||
version="1.0.0",
|
||||
version_latest="1.0.0",
|
||||
)
|
||||
addon_installed.return_value.state = AddonState.STOPPED
|
||||
|
||||
async def mock_addon_stats(addon: str) -> AddonsStats:
|
||||
"""Mock addon stats for test and test2."""
|
||||
@@ -209,23 +121,28 @@ def mock_all(
|
||||
addon_stats.side_effect = mock_addon_stats
|
||||
|
||||
def mock_addon_info(slug: str):
|
||||
addon_info.return_value.auto_update = slug == "test"
|
||||
return addon_info.return_value
|
||||
addon = Mock(
|
||||
spec=InstalledAddonComplete,
|
||||
to_dict=addon_installed.return_value.to_dict,
|
||||
**addon_installed.return_value.to_dict(),
|
||||
)
|
||||
if slug == "test":
|
||||
addon.name = "test"
|
||||
addon.slug = "test"
|
||||
addon.url = "https://github.com/home-assistant/addons/test"
|
||||
addon.auto_update = True
|
||||
else:
|
||||
addon.name = "test2"
|
||||
addon.slug = "test2"
|
||||
addon.url = "https://github.com"
|
||||
addon.auto_update = False
|
||||
|
||||
return addon
|
||||
|
||||
addon_info.side_effect = mock_addon_info
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/ingress/panels", json={"result": "ok", "data": {"panels": {}}}
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/network/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"host_internet": True,
|
||||
"supervisor_internet": True,
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
async def test_setup_api_ping(
|
||||
@@ -239,7 +156,7 @@ async def test_setup_api_ping(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 20
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 23
|
||||
assert get_core_info(hass)["version_latest"] == "1.0.0"
|
||||
assert is_hassio(hass)
|
||||
|
||||
@@ -310,7 +227,7 @@ async def test_setup_api_push_api_data(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 20
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 23
|
||||
assert not aioclient_mock.mock_calls[0][2]["ssl"]
|
||||
assert aioclient_mock.mock_calls[0][2]["port"] == 9999
|
||||
assert "watchdog" not in aioclient_mock.mock_calls[0][2]
|
||||
@@ -331,7 +248,7 @@ async def test_setup_api_push_api_data_server_host(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 20
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 23
|
||||
assert not aioclient_mock.mock_calls[0][2]["ssl"]
|
||||
assert aioclient_mock.mock_calls[0][2]["port"] == 9999
|
||||
assert not aioclient_mock.mock_calls[0][2]["watchdog"]
|
||||
@@ -352,7 +269,7 @@ async def test_setup_api_push_api_data_default(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 20
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 23
|
||||
assert not aioclient_mock.mock_calls[0][2]["ssl"]
|
||||
assert aioclient_mock.mock_calls[0][2]["port"] == 8123
|
||||
refresh_token = aioclient_mock.mock_calls[0][2]["refresh_token"]
|
||||
@@ -433,7 +350,7 @@ async def test_setup_api_existing_hassio_user(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 20
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 23
|
||||
assert not aioclient_mock.mock_calls[0][2]["ssl"]
|
||||
assert aioclient_mock.mock_calls[0][2]["port"] == 8123
|
||||
assert aioclient_mock.mock_calls[0][2]["refresh_token"] == token.token
|
||||
@@ -452,7 +369,7 @@ async def test_setup_core_push_config(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 20
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 23
|
||||
assert aioclient_mock.mock_calls[1][2]["timezone"] == "testzone"
|
||||
|
||||
with patch("homeassistant.util.dt.set_default_time_zone"):
|
||||
@@ -476,7 +393,7 @@ async def test_setup_hassio_no_additional_data(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 20
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 23
|
||||
assert aioclient_mock.mock_calls[-1][3]["Authorization"] == "Bearer 123456"
|
||||
|
||||
|
||||
@@ -536,7 +453,6 @@ async def test_service_calls(
|
||||
hass: HomeAssistant,
|
||||
aioclient_mock: AiohttpClientMocker,
|
||||
supervisor_client: AsyncMock,
|
||||
addon_installed: AsyncMock,
|
||||
supervisor_is_connected: AsyncMock,
|
||||
app_or_addon: str,
|
||||
) -> None:
|
||||
@@ -576,14 +492,14 @@ async def test_service_calls(
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 24
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 27
|
||||
assert aioclient_mock.mock_calls[-1][2] == "test"
|
||||
|
||||
await hass.services.async_call("hassio", "host_shutdown", {})
|
||||
await hass.services.async_call("hassio", "host_reboot", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 26
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 29
|
||||
|
||||
await hass.services.async_call("hassio", "backup_full", {})
|
||||
await hass.services.async_call(
|
||||
@@ -598,7 +514,7 @@ async def test_service_calls(
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 28
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 31
|
||||
# API receives "addons" even when we pass "apps"
|
||||
assert aioclient_mock.mock_calls[-1][2] == {
|
||||
"name": "2021-11-13 03:48:00",
|
||||
@@ -624,7 +540,7 @@ async def test_service_calls(
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 30
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 33
|
||||
# API receives "addons" even when we pass "apps"
|
||||
assert aioclient_mock.mock_calls[-1][2] == {
|
||||
"addons": ["test"],
|
||||
@@ -644,7 +560,7 @@ async def test_service_calls(
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 31
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 34
|
||||
assert aioclient_mock.mock_calls[-1][2] == {
|
||||
"name": "backup_name",
|
||||
"location": "backup_share",
|
||||
@@ -660,7 +576,7 @@ async def test_service_calls(
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 32
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 35
|
||||
assert aioclient_mock.mock_calls[-1][2] == {
|
||||
"name": "2021-11-13 03:48:00",
|
||||
"location": None,
|
||||
@@ -679,7 +595,7 @@ async def test_service_calls(
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 34
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 37
|
||||
assert aioclient_mock.mock_calls[-1][2] == {
|
||||
"name": "2021-11-13 11:48:00",
|
||||
"location": None,
|
||||
@@ -750,38 +666,37 @@ async def test_service_calls_apps_addons_exclusive(
|
||||
"app_or_addon",
|
||||
["app", "addon"],
|
||||
)
|
||||
@pytest.mark.usefixtures("aioclient_mock")
|
||||
async def test_addon_service_call_with_complex_slug(
|
||||
hass: HomeAssistant,
|
||||
aioclient_mock: AiohttpClientMocker,
|
||||
supervisor_is_connected: AsyncMock,
|
||||
app_or_addon: str,
|
||||
addons_list: AsyncMock,
|
||||
) -> None:
|
||||
"""Addon slugs can have ., - and _, confirm that passes validation."""
|
||||
supervisor_mock_data = {
|
||||
"version_latest": "1.0.0",
|
||||
"version": "1.0.0",
|
||||
"auto_update": True,
|
||||
"addons": [
|
||||
{
|
||||
"name": "test.a_1-2",
|
||||
"slug": "test.a_1-2",
|
||||
"state": "stopped",
|
||||
"update_available": False,
|
||||
"version": "1.0.0",
|
||||
"version_latest": "1.0.0",
|
||||
"repository": "core",
|
||||
"icon": False,
|
||||
},
|
||||
],
|
||||
}
|
||||
addons_list.return_value = [
|
||||
InstalledAddon(
|
||||
detached=False,
|
||||
advanced=False,
|
||||
available=True,
|
||||
build=False,
|
||||
description="",
|
||||
homeassistant=None,
|
||||
icon=False,
|
||||
logo=False,
|
||||
name="test.a_1-2",
|
||||
repository="core",
|
||||
slug="test.a_1-2",
|
||||
stage=AddonStage.STABLE,
|
||||
update_available=False,
|
||||
url="https://github.com",
|
||||
version_latest="1.0.0",
|
||||
version="1.0.0",
|
||||
state=AddonState.STOPPED,
|
||||
)
|
||||
]
|
||||
supervisor_is_connected.side_effect = SupervisorError
|
||||
with (
|
||||
patch.dict(os.environ, MOCK_ENVIRON),
|
||||
patch(
|
||||
"homeassistant.components.hassio.HassIO.get_supervisor_info",
|
||||
return_value=supervisor_mock_data,
|
||||
),
|
||||
):
|
||||
with patch.dict(os.environ, MOCK_ENVIRON):
|
||||
assert await async_setup_component(hass, "hassio", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
@@ -806,12 +721,12 @@ async def test_service_calls_core(
|
||||
await hass.services.async_call("homeassistant", "stop")
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 6
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 20
|
||||
|
||||
await hass.services.async_call("homeassistant", "check_config")
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 6
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 20
|
||||
|
||||
with patch(
|
||||
"homeassistant.config.async_check_ha_config_file", return_value=None
|
||||
@@ -820,7 +735,7 @@ async def test_service_calls_core(
|
||||
await hass.async_block_till_done()
|
||||
assert mock_check_config.called
|
||||
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 7
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 21
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("addon_installed")
|
||||
@@ -850,157 +765,79 @@ async def test_migration_off_hassio(hass: HomeAssistant) -> None:
|
||||
assert hass.config_entries.async_entries(DOMAIN) == []
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("addon_installed")
|
||||
@pytest.mark.usefixtures("addon_installed", "supervisor_info")
|
||||
async def test_device_registry_calls(
|
||||
hass: HomeAssistant, device_registry: dr.DeviceRegistry
|
||||
hass: HomeAssistant,
|
||||
device_registry: dr.DeviceRegistry,
|
||||
addons_list: AsyncMock,
|
||||
os_info: AsyncMock,
|
||||
) -> None:
|
||||
"""Test device registry entries for hassio."""
|
||||
supervisor_mock_data = {
|
||||
"version": "1.0.0",
|
||||
"version_latest": "1.0.0",
|
||||
"auto_update": True,
|
||||
"addons": [
|
||||
{
|
||||
"name": "test",
|
||||
"state": "started",
|
||||
"slug": "test",
|
||||
"installed": True,
|
||||
"icon": False,
|
||||
"update_available": False,
|
||||
"version": "1.0.0",
|
||||
"version_latest": "1.0.0",
|
||||
"repository": "test",
|
||||
"url": "https://github.com/home-assistant/addons/test",
|
||||
},
|
||||
{
|
||||
"name": "test2",
|
||||
"state": "started",
|
||||
"slug": "test2",
|
||||
"installed": True,
|
||||
"icon": False,
|
||||
"update_available": False,
|
||||
"version": "1.0.0",
|
||||
"version_latest": "1.0.0",
|
||||
"url": "https://github.com",
|
||||
},
|
||||
],
|
||||
}
|
||||
os_mock_data = {
|
||||
"board": "odroid-n2",
|
||||
"boot": "A",
|
||||
"update_available": False,
|
||||
"version": "5.12",
|
||||
"version_latest": "5.12",
|
||||
}
|
||||
addons_list.return_value[0] = replace(
|
||||
addons_list.return_value[0],
|
||||
version="1.0.0",
|
||||
version_latest="1.0.0",
|
||||
update_available=False,
|
||||
)
|
||||
addons_list.return_value[1] = replace(
|
||||
addons_list.return_value[1],
|
||||
version="1.0.0",
|
||||
version_latest="1.0.0",
|
||||
state=AddonState.STARTED,
|
||||
)
|
||||
os_info.return_value = replace(
|
||||
os_info.return_value,
|
||||
board="odroid-n2",
|
||||
boot="A",
|
||||
version="5.12",
|
||||
version_latest="5.12",
|
||||
)
|
||||
|
||||
with (
|
||||
patch.dict(os.environ, MOCK_ENVIRON),
|
||||
patch(
|
||||
"homeassistant.components.hassio.HassIO.get_supervisor_info",
|
||||
return_value=supervisor_mock_data,
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.hassio.HassIO.get_os_info",
|
||||
return_value=os_mock_data,
|
||||
),
|
||||
):
|
||||
with patch.dict(os.environ, MOCK_ENVIRON):
|
||||
config_entry = MockConfigEntry(domain=DOMAIN, data={}, unique_id=DOMAIN)
|
||||
config_entry.add_to_hass(hass)
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert len(device_registry.devices) == 6
|
||||
|
||||
supervisor_mock_data = {
|
||||
"version": "1.0.0",
|
||||
"version_latest": "1.0.0",
|
||||
"auto_update": True,
|
||||
"addons": [
|
||||
{
|
||||
"name": "test2",
|
||||
"state": "started",
|
||||
"slug": "test2",
|
||||
"installed": True,
|
||||
"icon": False,
|
||||
"update_available": False,
|
||||
"version": "1.0.0",
|
||||
"version_latest": "1.0.0",
|
||||
"url": "https://github.com",
|
||||
},
|
||||
],
|
||||
}
|
||||
addons_list.return_value.pop(0)
|
||||
|
||||
# Test that when addon is removed, next update will remove the add-on and subsequent updates won't
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.hassio.HassIO.get_supervisor_info",
|
||||
return_value=supervisor_mock_data,
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.hassio.HassIO.get_os_info",
|
||||
return_value=os_mock_data,
|
||||
),
|
||||
):
|
||||
async_fire_time_changed(hass, dt_util.now() + timedelta(hours=1))
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert len(device_registry.devices) == 5
|
||||
async_fire_time_changed(hass, dt_util.now() + timedelta(hours=1))
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert len(device_registry.devices) == 5
|
||||
|
||||
async_fire_time_changed(hass, dt_util.now() + timedelta(hours=2))
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert len(device_registry.devices) == 5
|
||||
async_fire_time_changed(hass, dt_util.now() + timedelta(hours=2))
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert len(device_registry.devices) == 5
|
||||
|
||||
supervisor_mock_data = {
|
||||
"version": "1.0.0",
|
||||
"version_latest": "1.0.0",
|
||||
"auto_update": True,
|
||||
"addons": [
|
||||
{
|
||||
"name": "test2",
|
||||
"slug": "test2",
|
||||
"state": "started",
|
||||
"installed": True,
|
||||
"icon": False,
|
||||
"update_available": False,
|
||||
"version": "1.0.0",
|
||||
"version_latest": "1.0.0",
|
||||
"url": "https://github.com",
|
||||
},
|
||||
{
|
||||
"name": "test3",
|
||||
"slug": "test3",
|
||||
"state": "stopped",
|
||||
"installed": True,
|
||||
"icon": False,
|
||||
"update_available": False,
|
||||
"version": "1.0.0",
|
||||
"version_latest": "1.0.0",
|
||||
"url": "https://github.com",
|
||||
},
|
||||
],
|
||||
}
|
||||
addons_list.return_value.append(
|
||||
InstalledAddon(
|
||||
detached=False,
|
||||
advanced=False,
|
||||
available=True,
|
||||
build=False,
|
||||
description="",
|
||||
homeassistant=None,
|
||||
icon=False,
|
||||
logo=False,
|
||||
name="test3",
|
||||
repository="core",
|
||||
slug="test3",
|
||||
stage=AddonStage.STABLE,
|
||||
update_available=False,
|
||||
url="https://github.com",
|
||||
version_latest="1.0.0",
|
||||
version="1.0.0",
|
||||
state=AddonState.STOPPED,
|
||||
)
|
||||
)
|
||||
|
||||
# Test that when addon is added, next update will reload the entry so we register
|
||||
# a new device
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.hassio.HassIO.get_supervisor_info",
|
||||
return_value=supervisor_mock_data,
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.hassio.HassIO.get_os_info",
|
||||
return_value=os_mock_data,
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.hassio.HassIO.get_info",
|
||||
return_value={
|
||||
"supervisor": "222",
|
||||
"homeassistant": "0.110.0",
|
||||
"hassos": None,
|
||||
},
|
||||
),
|
||||
):
|
||||
async_fire_time_changed(hass, dt_util.now() + timedelta(hours=3))
|
||||
await hass.async_block_till_done()
|
||||
assert len(device_registry.devices) == 5
|
||||
async_fire_time_changed(hass, dt_util.now() + timedelta(hours=3))
|
||||
await hass.async_block_till_done()
|
||||
assert len(device_registry.devices) == 5
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("addon_installed")
|
||||
@@ -1137,28 +974,31 @@ async def test_coordinator_updates_stats_entities_enabled(
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("extra_os_info", "integration"),
|
||||
("board", "integration"),
|
||||
[
|
||||
({"board": "green"}, "homeassistant_green"),
|
||||
({"board": "odroid-c2"}, "hardkernel"),
|
||||
({"board": "odroid-c4"}, "hardkernel"),
|
||||
({"board": "odroid-n2"}, "hardkernel"),
|
||||
({"board": "odroid-xu4"}, "hardkernel"),
|
||||
({"board": "rpi2"}, "raspberry_pi"),
|
||||
({"board": "rpi3"}, "raspberry_pi"),
|
||||
({"board": "rpi3-64"}, "raspberry_pi"),
|
||||
({"board": "rpi4"}, "raspberry_pi"),
|
||||
({"board": "rpi4-64"}, "raspberry_pi"),
|
||||
({"board": "yellow"}, "homeassistant_yellow"),
|
||||
("green", "homeassistant_green"),
|
||||
("odroid-c2", "hardkernel"),
|
||||
("odroid-c4", "hardkernel"),
|
||||
("odroid-n2", "hardkernel"),
|
||||
("odroid-xu4", "hardkernel"),
|
||||
("rpi2", "raspberry_pi"),
|
||||
("rpi3", "raspberry_pi"),
|
||||
("rpi3-64", "raspberry_pi"),
|
||||
("rpi4", "raspberry_pi"),
|
||||
("rpi4-64", "raspberry_pi"),
|
||||
("yellow", "homeassistant_yellow"),
|
||||
],
|
||||
)
|
||||
async def test_setup_hardware_integration(
|
||||
hass: HomeAssistant,
|
||||
aioclient_mock: AiohttpClientMocker,
|
||||
supervisor_client: AsyncMock,
|
||||
integration,
|
||||
os_info: AsyncMock,
|
||||
board: str,
|
||||
integration: str,
|
||||
) -> None:
|
||||
"""Test setup initiates hardware integration."""
|
||||
os_info.return_value = replace(os_info.return_value, board=board)
|
||||
|
||||
with (
|
||||
patch.dict(os.environ, MOCK_ENVIRON),
|
||||
@@ -1175,7 +1015,7 @@ async def test_setup_hardware_integration(
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert result
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 20
|
||||
assert aioclient_mock.call_count + len(supervisor_client.mock_calls) == 23
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
|
||||
@@ -1047,13 +1047,16 @@ async def test_supervisor_issues_free_space(
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("all_setup_requests")
|
||||
async def test_supervisor_issues_free_space_host_info_fail(
|
||||
hass: HomeAssistant,
|
||||
supervisor_client: AsyncMock,
|
||||
hass_ws_client: WebSocketGenerator,
|
||||
host_info: AsyncMock,
|
||||
) -> None:
|
||||
"""Test supervisor issue for too little free space remaining without host info."""
|
||||
mock_resolution_info(supervisor_client)
|
||||
host_info.side_effect = SupervisorError()
|
||||
|
||||
result = await async_setup_component(hass, "hassio", {})
|
||||
assert result
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
"""The tests for the hassio sensors."""
|
||||
|
||||
from dataclasses import replace
|
||||
from datetime import timedelta
|
||||
import os
|
||||
from unittest.mock import AsyncMock, patch
|
||||
from unittest.mock import AsyncMock, Mock, patch
|
||||
|
||||
from aiohasupervisor import SupervisorError
|
||||
from aiohasupervisor.models import AddonState, InstalledAddonComplete
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
import pytest
|
||||
|
||||
@@ -35,130 +37,57 @@ def mock_all(
|
||||
addon_changelog: AsyncMock,
|
||||
resolution_info: AsyncMock,
|
||||
jobs_info: AsyncMock,
|
||||
host_info: AsyncMock,
|
||||
supervisor_root_info: AsyncMock,
|
||||
homeassistant_info: AsyncMock,
|
||||
supervisor_info: AsyncMock,
|
||||
addons_list: AsyncMock,
|
||||
network_info: AsyncMock,
|
||||
os_info: AsyncMock,
|
||||
homeassistant_stats: AsyncMock,
|
||||
supervisor_stats: AsyncMock,
|
||||
) -> None:
|
||||
"""Mock all setup requests."""
|
||||
_install_default_mocks(aioclient_mock)
|
||||
|
||||
|
||||
def _install_default_mocks(aioclient_mock: AiohttpClientMocker):
|
||||
"""Install default mocks."""
|
||||
aioclient_mock.post("http://127.0.0.1/homeassistant/options", json={"result": "ok"})
|
||||
aioclient_mock.post("http://127.0.0.1/supervisor/options", json={"result": "ok"})
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"supervisor": "222",
|
||||
"homeassistant": "0.110.0",
|
||||
"hassos": "1.2.3",
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/host/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"agent_version": "1.0.0",
|
||||
"chassis": "vm",
|
||||
"operating_system": "Debian GNU/Linux 10 (buster)",
|
||||
"kernel": "4.19.0-6-amd64",
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/core/info",
|
||||
json={"result": "ok", "data": {"version_latest": "1.0.0", "version": "1.0.0"}},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/os/info",
|
||||
json={"result": "ok", "data": {"version_latest": "1.0.0", "version": "1.0.0"}},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"result": "ok",
|
||||
"version": "1.0.0",
|
||||
"version_latest": "1.0.0",
|
||||
"auto_update": True,
|
||||
"addons": [
|
||||
{
|
||||
"name": "test",
|
||||
"state": "started",
|
||||
"slug": "test",
|
||||
"installed": True,
|
||||
"update_available": False,
|
||||
"version": "2.0.0",
|
||||
"version_latest": "2.0.1",
|
||||
"repository": "core",
|
||||
"url": "https://github.com/home-assistant/addons/test",
|
||||
"icon": False,
|
||||
},
|
||||
{
|
||||
"name": "test2",
|
||||
"state": "stopped",
|
||||
"slug": "test2",
|
||||
"installed": True,
|
||||
"update_available": False,
|
||||
"version": "3.1.0",
|
||||
"version_latest": "3.2.0",
|
||||
"repository": "core",
|
||||
"url": "https://github.com",
|
||||
"icon": False,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/core/stats",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"cpu_percent": 0.99,
|
||||
"memory_usage": 182611968,
|
||||
"memory_limit": 3977146368,
|
||||
"memory_percent": 4.59,
|
||||
"network_rx": 362570232,
|
||||
"network_tx": 82374138,
|
||||
"blk_read": 46010945536,
|
||||
"blk_write": 15051526144,
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/stats",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"cpu_percent": 0.99,
|
||||
"memory_usage": 182611968,
|
||||
"memory_limit": 3977146368,
|
||||
"memory_percent": 4.59,
|
||||
"network_rx": 362570232,
|
||||
"network_tx": 82374138,
|
||||
"blk_read": 46010945536,
|
||||
"blk_write": 15051526144,
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/ingress/panels", json={"result": "ok", "data": {"panels": {}}}
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/network/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"host_internet": True,
|
||||
"supervisor_internet": True,
|
||||
},
|
||||
},
|
||||
|
||||
host_info.return_value = replace(host_info.return_value, agent_version="1.0.0")
|
||||
addons_list.return_value[1] = replace(
|
||||
addons_list.return_value[1], version_latest="3.2.0", update_available=True
|
||||
)
|
||||
|
||||
def mock_addon_info(slug: str):
|
||||
addon = Mock(
|
||||
spec=InstalledAddonComplete,
|
||||
to_dict=addon_installed.return_value.to_dict,
|
||||
**addon_installed.return_value.to_dict(),
|
||||
)
|
||||
if slug == "test":
|
||||
addon.name = "test"
|
||||
addon.slug = "test"
|
||||
addon.version = "2.0.0"
|
||||
addon.version_latest = "2.0.1"
|
||||
addon.update_available = True
|
||||
addon.state = AddonState.STARTED
|
||||
addon.url = "https://github.com/home-assistant/addons/test"
|
||||
addon.auto_update = True
|
||||
else:
|
||||
addon.name = "test2"
|
||||
addon.slug = "test2"
|
||||
addon.version = "3.1.0"
|
||||
addon.version_latest = "3.2.0"
|
||||
addon.update_available = True
|
||||
addon.state = AddonState.STOPPED
|
||||
addon.url = "https://github.com"
|
||||
addon.auto_update = False
|
||||
|
||||
return addon
|
||||
|
||||
addon_installed.side_effect = mock_addon_info
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("store_addons", "store_repositories"), [(MOCK_STORE_ADDONS, MOCK_REPOSITORIES)]
|
||||
@@ -256,20 +185,14 @@ async def test_stats_addon_sensor(
|
||||
# Verify that the entity is disabled by default.
|
||||
assert hass.states.get(entity_id) is None
|
||||
|
||||
aioclient_mock.clear_requests()
|
||||
_install_default_mocks(aioclient_mock)
|
||||
addon_stats.side_effect = SupervisorError
|
||||
|
||||
freezer.tick(HASSIO_UPDATE_INTERVAL + timedelta(seconds=1))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert "Could not fetch stats" not in caplog.text
|
||||
|
||||
aioclient_mock.clear_requests()
|
||||
_install_default_mocks(aioclient_mock)
|
||||
addon_stats.side_effect = None
|
||||
|
||||
freezer.tick(HASSIO_UPDATE_INTERVAL + timedelta(seconds=1))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
@@ -299,10 +222,7 @@ async def test_stats_addon_sensor(
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == expected
|
||||
|
||||
aioclient_mock.clear_requests()
|
||||
_install_default_mocks(aioclient_mock)
|
||||
addon_stats.side_effect = SupervisorError
|
||||
|
||||
freezer.tick(HASSIO_UPDATE_INTERVAL + timedelta(seconds=1))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
"""The tests for the hassio switch."""
|
||||
|
||||
from collections.abc import AsyncGenerator
|
||||
from dataclasses import replace
|
||||
import os
|
||||
from unittest.mock import AsyncMock, patch
|
||||
from unittest.mock import AsyncMock, Mock, patch
|
||||
|
||||
from aiohasupervisor.models import AddonState, InstalledAddonComplete
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.hassio import DOMAIN
|
||||
@@ -61,134 +63,55 @@ def mock_all(
|
||||
addon_stats: AsyncMock,
|
||||
resolution_info: AsyncMock,
|
||||
jobs_info: AsyncMock,
|
||||
host_info: AsyncMock,
|
||||
supervisor_root_info: AsyncMock,
|
||||
homeassistant_info: AsyncMock,
|
||||
supervisor_info: AsyncMock,
|
||||
addons_list: AsyncMock,
|
||||
network_info: AsyncMock,
|
||||
os_info: AsyncMock,
|
||||
homeassistant_stats: AsyncMock,
|
||||
supervisor_stats: AsyncMock,
|
||||
) -> None:
|
||||
"""Mock all setup requests."""
|
||||
aioclient_mock.post("http://127.0.0.1/homeassistant/options", json={"result": "ok"})
|
||||
aioclient_mock.post("http://127.0.0.1/supervisor/options", json={"result": "ok"})
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"supervisor": "222",
|
||||
"homeassistant": "0.110.0",
|
||||
"hassos": "1.2.3",
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/host/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"chassis": "vm",
|
||||
"operating_system": "Debian GNU/Linux 10 (buster)",
|
||||
"kernel": "4.19.0-6-amd64",
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/core/info",
|
||||
json={"result": "ok", "data": {"version_latest": "1.0.0", "version": "1.0.0"}},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/os/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"version_latest": "1.0.0",
|
||||
"version": "1.0.0",
|
||||
"update_available": False,
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"result": "ok",
|
||||
"version": "1.0.0",
|
||||
"version_latest": "1.0.0",
|
||||
"auto_update": True,
|
||||
"addons": [
|
||||
{
|
||||
"name": "test",
|
||||
"state": "started",
|
||||
"slug": "test",
|
||||
"installed": True,
|
||||
"update_available": True,
|
||||
"icon": False,
|
||||
"version": "2.0.0",
|
||||
"version_latest": "2.0.1",
|
||||
"repository": "core",
|
||||
"url": "https://github.com/home-assistant/addons/test",
|
||||
},
|
||||
{
|
||||
"name": "test-two",
|
||||
"state": "stopped",
|
||||
"slug": "test-two",
|
||||
"installed": True,
|
||||
"update_available": False,
|
||||
"icon": True,
|
||||
"version": "3.1.0",
|
||||
"version_latest": "3.1.0",
|
||||
"repository": "core",
|
||||
"url": "https://github.com",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/core/stats",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"cpu_percent": 0.99,
|
||||
"memory_usage": 182611968,
|
||||
"memory_limit": 3977146368,
|
||||
"memory_percent": 4.59,
|
||||
"network_rx": 362570232,
|
||||
"network_tx": 82374138,
|
||||
"blk_read": 46010945536,
|
||||
"blk_write": 15051526144,
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/stats",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"cpu_percent": 0.99,
|
||||
"memory_usage": 182611968,
|
||||
"memory_limit": 3977146368,
|
||||
"memory_percent": 4.59,
|
||||
"network_rx": 362570232,
|
||||
"network_tx": 82374138,
|
||||
"blk_read": 46010945536,
|
||||
"blk_write": 15051526144,
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/ingress/panels", json={"result": "ok", "data": {"panels": {}}}
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/network/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"host_internet": True,
|
||||
"supervisor_internet": True,
|
||||
},
|
||||
},
|
||||
addons_list.return_value[1] = replace(
|
||||
addons_list.return_value[1], name="test-two", slug="test-two"
|
||||
)
|
||||
|
||||
def mock_addon_info(slug: str):
|
||||
addon = Mock(
|
||||
spec=InstalledAddonComplete,
|
||||
to_dict=addon_installed.return_value.to_dict,
|
||||
**addon_installed.return_value.to_dict(),
|
||||
)
|
||||
if slug == "test":
|
||||
addon.name = "test"
|
||||
addon.slug = "test"
|
||||
addon.version = "2.0.0"
|
||||
addon.version_latest = "2.0.1"
|
||||
addon.update_available = True
|
||||
addon.state = AddonState.STARTED
|
||||
addon.url = "https://github.com/home-assistant/addons/test"
|
||||
addon.auto_update = True
|
||||
else:
|
||||
addon.name = "test-two"
|
||||
addon.slug = "test-two"
|
||||
addon.version = "3.1.0"
|
||||
addon.version_latest = "3.1.0"
|
||||
addon.update_available = False
|
||||
addon.state = AddonState.STOPPED
|
||||
addon.url = "https://github.com"
|
||||
addon.auto_update = False
|
||||
|
||||
return addon
|
||||
|
||||
addon_installed.side_effect = mock_addon_info
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("store_addons", "store_repositories"), [(MOCK_STORE_ADDONS, MOCK_REPOSITORIES)]
|
||||
|
||||
@@ -5,6 +5,7 @@ import os
|
||||
from unittest.mock import patch
|
||||
|
||||
from aiohttp import ClientError
|
||||
import pytest
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.setup import async_setup_component
|
||||
@@ -15,18 +16,15 @@ from tests.common import get_system_health_info
|
||||
from tests.test_util.aiohttp import AiohttpClientMocker
|
||||
|
||||
|
||||
@pytest.mark.usefixtures(
|
||||
"supervisor_root_info", "host_info", "os_info", "supervisor_info"
|
||||
)
|
||||
async def test_hassio_system_health(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
) -> None:
|
||||
"""Test hassio system health."""
|
||||
aioclient_mock.get("http://127.0.0.1/info", json={"result": "ok", "data": {}})
|
||||
aioclient_mock.get("http://127.0.0.1/host/info", json={"result": "ok", "data": {}})
|
||||
aioclient_mock.get("http://127.0.0.1/os/info", json={"result": "ok", "data": {}})
|
||||
aioclient_mock.get("http://127.0.0.1/supervisor/ping", text="")
|
||||
aioclient_mock.get("https://version.home-assistant.io/stable.json", text="")
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/info", json={"result": "ok", "data": {}}
|
||||
)
|
||||
|
||||
hass.config.components.add("hassio")
|
||||
assert await async_setup_component(hass, "system_health", {})
|
||||
@@ -50,8 +48,21 @@ async def test_hassio_system_health(
|
||||
hass.data["hassio_supervisor_info"] = {
|
||||
"healthy": True,
|
||||
"supported": True,
|
||||
"addons": [{"name": "Awesome Addon", "version": "1.0.0"}],
|
||||
}
|
||||
hass.data["hassio_addons_info"] = {
|
||||
"test": {
|
||||
"name": "Awesome Addon",
|
||||
"slug": "test",
|
||||
"version": "1.0.0",
|
||||
}
|
||||
}
|
||||
hass.data["hassio_addons_list"] = [
|
||||
{
|
||||
"slug": "test",
|
||||
"name": "Awesome Addon",
|
||||
"version": "1.0.0",
|
||||
}
|
||||
]
|
||||
hass.data["hassio_network_info"] = {
|
||||
"host_internet": True,
|
||||
"supervisor_internet": True,
|
||||
@@ -90,18 +101,15 @@ async def test_hassio_system_health(
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.usefixtures(
|
||||
"supervisor_root_info", "host_info", "os_info", "supervisor_info"
|
||||
)
|
||||
async def test_hassio_system_health_with_issues(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
) -> None:
|
||||
"""Test hassio system health."""
|
||||
aioclient_mock.get("http://127.0.0.1/info", json={"result": "ok", "data": {}})
|
||||
aioclient_mock.get("http://127.0.0.1/host/info", json={"result": "ok", "data": {}})
|
||||
aioclient_mock.get("http://127.0.0.1/os/info", json={"result": "ok", "data": {}})
|
||||
aioclient_mock.get("http://127.0.0.1/supervisor/ping", text="")
|
||||
aioclient_mock.get("https://version.home-assistant.io/stable.json", exc=ClientError)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/info", json={"result": "ok", "data": {}}
|
||||
)
|
||||
|
||||
hass.config.components.add("hassio")
|
||||
assert await async_setup_component(hass, "system_health", {})
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
"""The tests for the hassio update entities."""
|
||||
|
||||
from dataclasses import replace
|
||||
from datetime import datetime, timedelta
|
||||
import os
|
||||
from typing import Any
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
from unittest.mock import AsyncMock, MagicMock, Mock, patch
|
||||
from uuid import uuid4
|
||||
|
||||
from aiohasupervisor import (
|
||||
@@ -12,7 +13,9 @@ from aiohasupervisor import (
|
||||
SupervisorNotFoundError,
|
||||
)
|
||||
from aiohasupervisor.models import (
|
||||
AddonState,
|
||||
HomeAssistantUpdateOptions,
|
||||
InstalledAddonComplete,
|
||||
Job,
|
||||
JobsInfo,
|
||||
OSUpdate,
|
||||
@@ -48,136 +51,68 @@ def mock_all(
|
||||
addon_changelog: AsyncMock,
|
||||
resolution_info: AsyncMock,
|
||||
jobs_info: AsyncMock,
|
||||
host_info: AsyncMock,
|
||||
supervisor_root_info: AsyncMock,
|
||||
homeassistant_info: AsyncMock,
|
||||
supervisor_info: AsyncMock,
|
||||
addons_list: AsyncMock,
|
||||
network_info: AsyncMock,
|
||||
os_info: AsyncMock,
|
||||
homeassistant_stats: AsyncMock,
|
||||
supervisor_stats: AsyncMock,
|
||||
) -> None:
|
||||
"""Mock all setup requests."""
|
||||
aioclient_mock.post("http://127.0.0.1/homeassistant/options", json={"result": "ok"})
|
||||
aioclient_mock.post("http://127.0.0.1/supervisor/options", json={"result": "ok"})
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"supervisor": "222",
|
||||
"homeassistant": "0.110.0",
|
||||
"hassos": "1.2.3",
|
||||
},
|
||||
},
|
||||
homeassistant_info.return_value = replace(
|
||||
homeassistant_info.return_value,
|
||||
version="1.0.0dev221",
|
||||
version_latest="1.0.0dev222",
|
||||
update_available=True,
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/host/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"chassis": "vm",
|
||||
"operating_system": "Debian GNU/Linux 10 (buster)",
|
||||
"kernel": "4.19.0-6-amd64",
|
||||
},
|
||||
},
|
||||
},
|
||||
os_info.return_value = replace(
|
||||
os_info.return_value,
|
||||
version="1.0.0dev2221",
|
||||
version_latest="1.0.0dev2222",
|
||||
update_available=True,
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/core/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {"version_latest": "1.0.0dev222", "version": "1.0.0dev221"},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/os/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"version_latest": "1.0.0dev2222",
|
||||
"version": "1.0.0dev2221",
|
||||
"update_available": False,
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"result": "ok",
|
||||
"version": "1.0.0",
|
||||
"version_latest": "1.0.1dev222",
|
||||
"auto_update": True,
|
||||
"addons": [
|
||||
{
|
||||
"name": "test",
|
||||
"state": "started",
|
||||
"slug": "test",
|
||||
"installed": True,
|
||||
"update_available": True,
|
||||
"icon": False,
|
||||
"version": "2.0.0",
|
||||
"version_latest": "2.0.1",
|
||||
"repository": "core",
|
||||
"url": "https://github.com/home-assistant/addons/test",
|
||||
},
|
||||
{
|
||||
"name": "test2",
|
||||
"state": "stopped",
|
||||
"slug": "test2",
|
||||
"installed": True,
|
||||
"update_available": False,
|
||||
"icon": True,
|
||||
"version": "3.1.0",
|
||||
"version_latest": "3.1.0",
|
||||
"repository": "core",
|
||||
"url": "https://github.com",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/core/stats",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"cpu_percent": 0.99,
|
||||
"memory_usage": 182611968,
|
||||
"memory_limit": 3977146368,
|
||||
"memory_percent": 4.59,
|
||||
"network_rx": 362570232,
|
||||
"network_tx": 82374138,
|
||||
"blk_read": 46010945536,
|
||||
"blk_write": 15051526144,
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/stats",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"cpu_percent": 0.99,
|
||||
"memory_usage": 182611968,
|
||||
"memory_limit": 3977146368,
|
||||
"memory_percent": 4.59,
|
||||
"network_rx": 362570232,
|
||||
"network_tx": 82374138,
|
||||
"blk_read": 46010945536,
|
||||
"blk_write": 15051526144,
|
||||
},
|
||||
},
|
||||
supervisor_info.return_value = replace(
|
||||
supervisor_info.return_value,
|
||||
version_latest="1.0.1dev222",
|
||||
update_available=True,
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/ingress/panels", json={"result": "ok", "data": {"panels": {}}}
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/network/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"host_internet": True,
|
||||
"supervisor_internet": True,
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
def mock_addon_info(slug: str):
|
||||
addon = Mock(
|
||||
spec=InstalledAddonComplete,
|
||||
to_dict=addon_installed.return_value.to_dict,
|
||||
**addon_installed.return_value.to_dict(),
|
||||
)
|
||||
if slug == "test":
|
||||
addon.name = "test"
|
||||
addon.slug = "test"
|
||||
addon.version = "2.0.0"
|
||||
addon.version_latest = "2.0.1"
|
||||
addon.update_available = True
|
||||
addon.state = AddonState.STARTED
|
||||
addon.url = "https://github.com/home-assistant/addons/test"
|
||||
addon.auto_update = True
|
||||
else:
|
||||
addon.name = "test2"
|
||||
addon.slug = "test2"
|
||||
addon.version = "3.1.0"
|
||||
addon.version_latest = "3.1.0"
|
||||
addon.update_available = False
|
||||
addon.state = AddonState.STOPPED
|
||||
addon.url = "https://github.com"
|
||||
addon.auto_update = False
|
||||
|
||||
return addon
|
||||
|
||||
addon_installed.side_effect = mock_addon_info
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -1588,19 +1523,14 @@ async def test_not_release_notes(
|
||||
assert result["result"] is None
|
||||
|
||||
|
||||
async def test_no_os_entity(hass: HomeAssistant) -> None:
|
||||
async def test_no_os_entity(
|
||||
hass: HomeAssistant, supervisor_root_info: AsyncMock
|
||||
) -> None:
|
||||
"""Test handling where there is no os entity."""
|
||||
with (
|
||||
patch.dict(os.environ, MOCK_ENVIRON),
|
||||
patch(
|
||||
"homeassistant.components.hassio.HassIO.get_info",
|
||||
return_value={
|
||||
"supervisor": "222",
|
||||
"homeassistant": "0.110.0",
|
||||
"hassos": None,
|
||||
},
|
||||
),
|
||||
):
|
||||
supervisor_root_info.return_value = replace(
|
||||
supervisor_root_info.return_value, hassos=None
|
||||
)
|
||||
with patch.dict(os.environ, MOCK_ENVIRON):
|
||||
result = await async_setup_component(
|
||||
hass,
|
||||
"hassio",
|
||||
@@ -1624,9 +1554,7 @@ async def test_setting_up_core_update_when_addon_fails(
|
||||
addon_installed.side_effect = SupervisorBadRequestError("Addon Test does not exist")
|
||||
addon_stats.side_effect = SupervisorBadRequestError("add-on is not running")
|
||||
addon_changelog.side_effect = SupervisorBadRequestError("add-on is not running")
|
||||
with (
|
||||
patch.dict(os.environ, MOCK_ENVIRON),
|
||||
):
|
||||
with patch.dict(os.environ, MOCK_ENVIRON):
|
||||
result = await async_setup_component(
|
||||
hass,
|
||||
"hassio",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"""Test websocket API."""
|
||||
|
||||
from dataclasses import replace
|
||||
import os
|
||||
from typing import Any
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
@@ -44,39 +45,31 @@ def mock_all(
|
||||
supervisor_is_connected: AsyncMock,
|
||||
resolution_info: AsyncMock,
|
||||
addon_info: AsyncMock,
|
||||
host_info: AsyncMock,
|
||||
supervisor_root_info: AsyncMock,
|
||||
homeassistant_info: AsyncMock,
|
||||
supervisor_info: AsyncMock,
|
||||
addons_list: AsyncMock,
|
||||
network_info: AsyncMock,
|
||||
os_info: AsyncMock,
|
||||
store_info: AsyncMock,
|
||||
) -> None:
|
||||
"""Mock all setup requests."""
|
||||
aioclient_mock.post("http://127.0.0.1/homeassistant/options", json={"result": "ok"})
|
||||
aioclient_mock.post("http://127.0.0.1/supervisor/options", json={"result": "ok"})
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {"supervisor": "222", "homeassistant": "0.110.0", "hassos": None},
|
||||
},
|
||||
supervisor_root_info.return_value = replace(
|
||||
supervisor_root_info.return_value, hassos=None
|
||||
)
|
||||
addons_list.return_value.pop(1)
|
||||
addon_info.return_value.version = "2.0.0"
|
||||
addon_info.return_value.version_latest = "2.0.1"
|
||||
addon_info.return_value.update_available = True
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/host/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"chassis": "vm",
|
||||
"operating_system": "Debian GNU/Linux 10 (buster)",
|
||||
"kernel": "4.19.0-6-amd64",
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/core/info",
|
||||
json={"result": "ok", "data": {"version_latest": "1.0.0", "version": "1.0.0"}},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/os/info",
|
||||
json={"result": "ok", "data": {"version_latest": "1.0.0"}},
|
||||
"http://127.0.0.1/ingress/panels", json={"result": "ok", "data": {"panels": {}}}
|
||||
)
|
||||
|
||||
# The websocket API still relies on HassIO.send_command for all Supervisor API calls
|
||||
# So must keep some aioclient mocks normally covered by aiohasupervisor in component
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/info",
|
||||
json={
|
||||
@@ -102,19 +95,6 @@ def mock_all(
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/ingress/panels", json={"result": "ok", "data": {"panels": {}}}
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/network/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"host_internet": True,
|
||||
"supervisor_internet": True,
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("hassio_env")
|
||||
|
||||
@@ -245,14 +245,15 @@ async def test_ip_ban_manager_never_started(
|
||||
)
|
||||
),
|
||||
)
|
||||
@pytest.mark.usefixtures(
|
||||
"hassio_env", "resolution_info", "os_info", "store_info", "supervisor_info"
|
||||
)
|
||||
async def test_access_from_supervisor_ip(
|
||||
remote_addr,
|
||||
bans,
|
||||
status,
|
||||
hass: HomeAssistant,
|
||||
aiohttp_client: ClientSessionGenerator,
|
||||
hassio_env,
|
||||
resolution_info: AsyncMock,
|
||||
) -> None:
|
||||
"""Test accessing to server from supervisor IP."""
|
||||
app = web.Application()
|
||||
|
||||
@@ -5,12 +5,13 @@ from typing import Any
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.humidifier.const import ATTR_ACTION, HumidifierAction
|
||||
from homeassistant.const import ATTR_LABEL_ID, CONF_ENTITY_ID, STATE_OFF, STATE_ON
|
||||
from homeassistant.const import CONF_ENTITY_ID, STATE_OFF, STATE_ON
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
|
||||
from tests.components import (
|
||||
TriggerStateDescription,
|
||||
arm_trigger,
|
||||
assert_trigger_gated_by_labs_flag,
|
||||
parametrize_target_entities,
|
||||
parametrize_trigger_states,
|
||||
set_or_remove_state,
|
||||
@@ -37,13 +38,7 @@ async def test_humidifier_triggers_gated_by_labs_flag(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, trigger_key: str
|
||||
) -> None:
|
||||
"""Test the humidifier triggers are gated by the labs flag."""
|
||||
await arm_trigger(hass, trigger_key, None, {ATTR_LABEL_ID: "test_label"})
|
||||
assert (
|
||||
"Unnamed automation failed to setup triggers and has been disabled: Trigger "
|
||||
f"'{trigger_key}' requires the experimental 'New triggers and conditions' "
|
||||
"feature to be enabled in Home Assistant Labs settings (feature flag: "
|
||||
"'new_triggers_conditions')"
|
||||
) in caplog.text
|
||||
await assert_trigger_gated_by_labs_flag(hass, caplog, trigger_key)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("enable_labs_preview_features")
|
||||
|
||||
@@ -12,17 +12,13 @@ from homeassistant.components.humidifier import (
|
||||
ATTR_CURRENT_HUMIDITY as HUMIDIFIER_ATTR_CURRENT_HUMIDITY,
|
||||
)
|
||||
from homeassistant.components.weather import ATTR_WEATHER_HUMIDITY
|
||||
from homeassistant.const import (
|
||||
ATTR_DEVICE_CLASS,
|
||||
ATTR_LABEL_ID,
|
||||
CONF_ENTITY_ID,
|
||||
STATE_ON,
|
||||
)
|
||||
from homeassistant.const import ATTR_DEVICE_CLASS, CONF_ENTITY_ID, STATE_ON
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
|
||||
from tests.components import (
|
||||
TriggerStateDescription,
|
||||
arm_trigger,
|
||||
assert_trigger_gated_by_labs_flag,
|
||||
parametrize_numerical_attribute_changed_trigger_states,
|
||||
parametrize_numerical_attribute_crossed_threshold_trigger_states,
|
||||
parametrize_numerical_state_value_changed_trigger_states,
|
||||
@@ -68,13 +64,7 @@ async def test_humidity_triggers_gated_by_labs_flag(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, trigger_key: str
|
||||
) -> None:
|
||||
"""Test the humidity triggers are gated by the labs flag."""
|
||||
await arm_trigger(hass, trigger_key, None, {ATTR_LABEL_ID: "test_label"})
|
||||
assert (
|
||||
"Unnamed automation failed to setup triggers and has been disabled: Trigger "
|
||||
f"'{trigger_key}' requires the experimental 'New triggers and conditions' "
|
||||
"feature to be enabled in Home Assistant Labs settings (feature flag: "
|
||||
"'new_triggers_conditions')"
|
||||
) in caplog.text
|
||||
await assert_trigger_gated_by_labs_flag(hass, caplog, trigger_key)
|
||||
|
||||
|
||||
# --- Sensor domain tests (value in state.state) ---
|
||||
|
||||
@@ -74,6 +74,5 @@ def mock_config_entry() -> MockConfigEntry:
|
||||
CONF_USERNAME: "huum@sauna.org",
|
||||
CONF_PASSWORD: "ukuuku",
|
||||
},
|
||||
unique_id="123456",
|
||||
entry_id="AABBCC112233",
|
||||
)
|
||||
|
||||
@@ -28,7 +28,7 @@ async def test_form(
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["errors"] == {}
|
||||
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{
|
||||
CONF_USERNAME: TEST_USERNAME,
|
||||
@@ -37,9 +37,9 @@ async def test_form(
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result2["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result2["title"] == TEST_USERNAME
|
||||
assert result2["data"] == {
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == TEST_USERNAME
|
||||
assert result["data"] == {
|
||||
CONF_USERNAME: TEST_USERNAME,
|
||||
CONF_PASSWORD: TEST_PASSWORD,
|
||||
}
|
||||
@@ -59,7 +59,7 @@ async def test_signup_flow_already_set_up(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{
|
||||
CONF_USERNAME: TEST_USERNAME,
|
||||
@@ -67,7 +67,7 @@ async def test_signup_flow_already_set_up(
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert result2["type"] is FlowResultType.ABORT
|
||||
assert result["type"] is FlowResultType.ABORT
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -96,7 +96,7 @@ async def test_huum_errors(
|
||||
"homeassistant.components.huum.config_flow.Huum.status",
|
||||
side_effect=raises,
|
||||
):
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{
|
||||
CONF_USERNAME: TEST_USERNAME,
|
||||
@@ -104,14 +104,14 @@ async def test_huum_errors(
|
||||
},
|
||||
)
|
||||
|
||||
assert result2["type"] is FlowResultType.FORM
|
||||
assert result2["errors"] == {"base": error_base}
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["errors"] == {"base": error_base}
|
||||
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{
|
||||
CONF_USERNAME: TEST_USERNAME,
|
||||
CONF_PASSWORD: TEST_PASSWORD,
|
||||
},
|
||||
)
|
||||
assert result2["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
|
||||
@@ -5,12 +5,13 @@ from typing import Any
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.input_boolean import DOMAIN
|
||||
from homeassistant.const import ATTR_LABEL_ID, CONF_ENTITY_ID, STATE_OFF, STATE_ON
|
||||
from homeassistant.const import CONF_ENTITY_ID, STATE_OFF, STATE_ON
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
|
||||
from tests.components import (
|
||||
TriggerStateDescription,
|
||||
arm_trigger,
|
||||
assert_trigger_gated_by_labs_flag,
|
||||
parametrize_target_entities,
|
||||
parametrize_trigger_states,
|
||||
set_or_remove_state,
|
||||
@@ -35,13 +36,7 @@ async def test_input_boolean_triggers_gated_by_labs_flag(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, trigger_key: str
|
||||
) -> None:
|
||||
"""Test the input_boolean triggers are gated by the labs flag."""
|
||||
await arm_trigger(hass, trigger_key, None, {ATTR_LABEL_ID: "test_label"})
|
||||
assert (
|
||||
"Unnamed automation failed to setup triggers and has been disabled: Trigger "
|
||||
f"'{trigger_key}' requires the experimental 'New triggers and conditions' "
|
||||
"feature to be enabled in Home Assistant Labs settings (feature flag: "
|
||||
"'new_triggers_conditions')"
|
||||
) in caplog.text
|
||||
await assert_trigger_gated_by_labs_flag(hass, caplog, trigger_key)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("enable_labs_preview_features")
|
||||
|
||||
@@ -5,12 +5,13 @@ from typing import Any
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.lawn_mower import LawnMowerActivity
|
||||
from homeassistant.const import ATTR_LABEL_ID, CONF_ENTITY_ID
|
||||
from homeassistant.const import CONF_ENTITY_ID
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
|
||||
from tests.components import (
|
||||
TriggerStateDescription,
|
||||
arm_trigger,
|
||||
assert_trigger_gated_by_labs_flag,
|
||||
other_states,
|
||||
parametrize_target_entities,
|
||||
parametrize_trigger_states,
|
||||
@@ -39,13 +40,7 @@ async def test_lawn_mower_triggers_gated_by_labs_flag(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, trigger_key: str
|
||||
) -> None:
|
||||
"""Test the lawn mower triggers are gated by the labs flag."""
|
||||
await arm_trigger(hass, trigger_key, None, {ATTR_LABEL_ID: "test_label"})
|
||||
assert (
|
||||
"Unnamed automation failed to setup triggers and has been disabled: Trigger "
|
||||
f"'{trigger_key}' requires the experimental 'New triggers and conditions' "
|
||||
"feature to be enabled in Home Assistant Labs settings (feature flag: "
|
||||
"'new_triggers_conditions')"
|
||||
) in caplog.text
|
||||
await assert_trigger_gated_by_labs_flag(hass, caplog, trigger_key)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("enable_labs_preview_features")
|
||||
|
||||
@@ -6,7 +6,6 @@ import pytest
|
||||
|
||||
from homeassistant.components.light import ATTR_BRIGHTNESS
|
||||
from homeassistant.const import (
|
||||
ATTR_LABEL_ID,
|
||||
CONF_ABOVE,
|
||||
CONF_BELOW,
|
||||
CONF_ENTITY_ID,
|
||||
@@ -24,6 +23,7 @@ from homeassistant.helpers.trigger import (
|
||||
from tests.components import (
|
||||
TriggerStateDescription,
|
||||
arm_trigger,
|
||||
assert_trigger_gated_by_labs_flag,
|
||||
parametrize_target_entities,
|
||||
parametrize_trigger_states,
|
||||
set_or_remove_state,
|
||||
@@ -175,13 +175,7 @@ async def test_light_triggers_gated_by_labs_flag(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, trigger_key: str
|
||||
) -> None:
|
||||
"""Test the light triggers are gated by the labs flag."""
|
||||
await arm_trigger(hass, trigger_key, None, {ATTR_LABEL_ID: "test_label"})
|
||||
assert (
|
||||
"Unnamed automation failed to setup triggers and has been disabled: Trigger "
|
||||
f"'{trigger_key}' requires the experimental 'New triggers and conditions' "
|
||||
"feature to be enabled in Home Assistant Labs settings (feature flag: "
|
||||
"'new_triggers_conditions')"
|
||||
) in caplog.text
|
||||
await assert_trigger_gated_by_labs_flag(hass, caplog, trigger_key)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("enable_labs_preview_features")
|
||||
|
||||
@@ -5,12 +5,13 @@ from typing import Any
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.lock import DOMAIN, LockState
|
||||
from homeassistant.const import ATTR_LABEL_ID, CONF_ENTITY_ID
|
||||
from homeassistant.const import CONF_ENTITY_ID
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
|
||||
from tests.components import (
|
||||
TriggerStateDescription,
|
||||
arm_trigger,
|
||||
assert_trigger_gated_by_labs_flag,
|
||||
other_states,
|
||||
parametrize_target_entities,
|
||||
parametrize_trigger_states,
|
||||
@@ -38,13 +39,7 @@ async def test_lock_triggers_gated_by_labs_flag(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, trigger_key: str
|
||||
) -> None:
|
||||
"""Test the lock triggers are gated by the labs flag."""
|
||||
await arm_trigger(hass, trigger_key, None, {ATTR_LABEL_ID: "test_label"})
|
||||
assert (
|
||||
"Unnamed automation failed to setup triggers and has been disabled: Trigger "
|
||||
f"'{trigger_key}' requires the experimental 'New triggers and conditions' "
|
||||
"feature to be enabled in Home Assistant Labs settings (feature flag: "
|
||||
"'new_triggers_conditions')"
|
||||
) in caplog.text
|
||||
await assert_trigger_gated_by_labs_flag(hass, caplog, trigger_key)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("enable_labs_preview_features")
|
||||
|
||||
@@ -5,12 +5,13 @@ from typing import Any
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.media_player import MediaPlayerState
|
||||
from homeassistant.const import ATTR_LABEL_ID, CONF_ENTITY_ID
|
||||
from homeassistant.const import CONF_ENTITY_ID
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
|
||||
from tests.components import (
|
||||
TriggerStateDescription,
|
||||
arm_trigger,
|
||||
assert_trigger_gated_by_labs_flag,
|
||||
parametrize_target_entities,
|
||||
parametrize_trigger_states,
|
||||
set_or_remove_state,
|
||||
@@ -34,13 +35,7 @@ async def test_media_player_triggers_gated_by_labs_flag(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, trigger_key: str
|
||||
) -> None:
|
||||
"""Test the media player triggers are gated by the labs flag."""
|
||||
await arm_trigger(hass, trigger_key, None, {ATTR_LABEL_ID: "test_label"})
|
||||
assert (
|
||||
"Unnamed automation failed to setup triggers and has been disabled: Trigger "
|
||||
f"'{trigger_key}' requires the experimental 'New triggers and conditions' "
|
||||
"feature to be enabled in Home Assistant Labs settings (feature flag: "
|
||||
"'new_triggers_conditions')"
|
||||
) in caplog.text
|
||||
await assert_trigger_gated_by_labs_flag(hass, caplog, trigger_key)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("enable_labs_preview_features")
|
||||
|
||||
@@ -4,18 +4,13 @@ from typing import Any
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.const import (
|
||||
ATTR_DEVICE_CLASS,
|
||||
ATTR_LABEL_ID,
|
||||
CONF_ENTITY_ID,
|
||||
STATE_OFF,
|
||||
STATE_ON,
|
||||
)
|
||||
from homeassistant.const import ATTR_DEVICE_CLASS, CONF_ENTITY_ID, STATE_OFF, STATE_ON
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
|
||||
from tests.components import (
|
||||
TriggerStateDescription,
|
||||
arm_trigger,
|
||||
assert_trigger_gated_by_labs_flag,
|
||||
parametrize_target_entities,
|
||||
parametrize_trigger_states,
|
||||
set_or_remove_state,
|
||||
@@ -40,13 +35,7 @@ async def test_motion_triggers_gated_by_labs_flag(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, trigger_key: str
|
||||
) -> None:
|
||||
"""Test the motion triggers are gated by the labs flag."""
|
||||
await arm_trigger(hass, trigger_key, None, {ATTR_LABEL_ID: "test_label"})
|
||||
assert (
|
||||
"Unnamed automation failed to setup triggers and has been disabled: Trigger "
|
||||
f"'{trigger_key}' requires the experimental 'New triggers and conditions' "
|
||||
"feature to be enabled in Home Assistant Labs settings (feature flag: "
|
||||
"'new_triggers_conditions')"
|
||||
) in caplog.text
|
||||
await assert_trigger_gated_by_labs_flag(hass, caplog, trigger_key)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("enable_labs_preview_features")
|
||||
|
||||
@@ -4,18 +4,13 @@ from typing import Any
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.const import (
|
||||
ATTR_DEVICE_CLASS,
|
||||
ATTR_LABEL_ID,
|
||||
CONF_ENTITY_ID,
|
||||
STATE_OFF,
|
||||
STATE_ON,
|
||||
)
|
||||
from homeassistant.const import ATTR_DEVICE_CLASS, CONF_ENTITY_ID, STATE_OFF, STATE_ON
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
|
||||
from tests.components import (
|
||||
TriggerStateDescription,
|
||||
arm_trigger,
|
||||
assert_trigger_gated_by_labs_flag,
|
||||
parametrize_target_entities,
|
||||
parametrize_trigger_states,
|
||||
set_or_remove_state,
|
||||
@@ -40,13 +35,7 @@ async def test_occupancy_triggers_gated_by_labs_flag(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, trigger_key: str
|
||||
) -> None:
|
||||
"""Test the occupancy triggers are gated by the labs flag."""
|
||||
await arm_trigger(hass, trigger_key, None, {ATTR_LABEL_ID: "test_label"})
|
||||
assert (
|
||||
"Unnamed automation failed to setup triggers and has been disabled: Trigger "
|
||||
f"'{trigger_key}' requires the experimental 'New triggers and conditions' "
|
||||
"feature to be enabled in Home Assistant Labs settings (feature flag: "
|
||||
"'new_triggers_conditions')"
|
||||
) in caplog.text
|
||||
await assert_trigger_gated_by_labs_flag(hass, caplog, trigger_key)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("enable_labs_preview_features")
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import asyncio
|
||||
from collections.abc import AsyncGenerator
|
||||
from dataclasses import replace
|
||||
from http import HTTPStatus
|
||||
import os
|
||||
from typing import Any
|
||||
@@ -54,15 +55,14 @@ async def rpi_fixture(
|
||||
|
||||
@pytest.fixture(name="no_rpi")
|
||||
async def no_rpi_fixture(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker, mock_supervisor
|
||||
hass: HomeAssistant,
|
||||
aioclient_mock: AiohttpClientMocker,
|
||||
homeassistant_info: AsyncMock,
|
||||
mock_supervisor,
|
||||
) -> None:
|
||||
"""Mock core info with rpi."""
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/core/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {"version_latest": "1.0.0", "machine": "odroid-n2"},
|
||||
},
|
||||
homeassistant_info.return_value = replace(
|
||||
homeassistant_info.return_value, machine="odroid-n2"
|
||||
)
|
||||
assert await async_setup_component(hass, "hassio", {})
|
||||
await hass.async_block_till_done()
|
||||
@@ -74,38 +74,20 @@ async def mock_supervisor_fixture(
|
||||
store_info: AsyncMock,
|
||||
supervisor_is_connected: AsyncMock,
|
||||
resolution_info: AsyncMock,
|
||||
supervisor_root_info: AsyncMock,
|
||||
host_info: AsyncMock,
|
||||
supervisor_info: AsyncMock,
|
||||
network_info: AsyncMock,
|
||||
os_info: AsyncMock,
|
||||
) -> AsyncGenerator[None]:
|
||||
"""Mock supervisor."""
|
||||
aioclient_mock.post("http://127.0.0.1/homeassistant/options", json={"result": "ok"})
|
||||
aioclient_mock.post("http://127.0.0.1/supervisor/options", json={"result": "ok"})
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/network/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"host_internet": True,
|
||||
"supervisor_internet": True,
|
||||
},
|
||||
},
|
||||
supervisor_info.return_value = replace(
|
||||
supervisor_info.return_value, diagnostics=True
|
||||
)
|
||||
with (
|
||||
patch.dict(os.environ, {"SUPERVISOR": "127.0.0.1"}),
|
||||
patch(
|
||||
"homeassistant.components.hassio.HassIO.get_info",
|
||||
return_value={},
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.hassio.HassIO.get_host_info",
|
||||
return_value={},
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.hassio.HassIO.get_supervisor_info",
|
||||
return_value={"diagnostics": True},
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.hassio.HassIO.get_os_info",
|
||||
return_value={},
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.hassio.HassIO.get_ingress_panels",
|
||||
return_value={"panels": {}},
|
||||
|
||||
@@ -5,17 +5,13 @@ from typing import Any
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.person.const import DOMAIN
|
||||
from homeassistant.const import (
|
||||
ATTR_LABEL_ID,
|
||||
CONF_ENTITY_ID,
|
||||
STATE_HOME,
|
||||
STATE_NOT_HOME,
|
||||
)
|
||||
from homeassistant.const import CONF_ENTITY_ID, STATE_HOME, STATE_NOT_HOME
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
|
||||
from tests.components import (
|
||||
TriggerStateDescription,
|
||||
arm_trigger,
|
||||
assert_trigger_gated_by_labs_flag,
|
||||
parametrize_target_entities,
|
||||
parametrize_trigger_states,
|
||||
set_or_remove_state,
|
||||
@@ -39,13 +35,7 @@ async def test_person_triggers_gated_by_labs_flag(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, trigger_key: str
|
||||
) -> None:
|
||||
"""Test the person triggers are gated by the labs flag."""
|
||||
await arm_trigger(hass, trigger_key, None, {ATTR_LABEL_ID: "test_label"})
|
||||
assert (
|
||||
"Unnamed automation failed to setup triggers and has been disabled: Trigger "
|
||||
f"'{trigger_key}' requires the experimental 'New triggers and conditions' "
|
||||
"feature to be enabled in Home Assistant Labs settings (feature flag: "
|
||||
"'new_triggers_conditions')"
|
||||
) in caplog.text
|
||||
await assert_trigger_gated_by_labs_flag(hass, caplog, trigger_key)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("enable_labs_preview_features")
|
||||
|
||||
@@ -53,10 +53,10 @@ def mock_pterodactyl() -> Generator[AsyncMock]:
|
||||
mock.return_value.client.servers.list_servers.return_value = PaginatedResponse(
|
||||
mock.return_value, "client", server_list_data
|
||||
)
|
||||
mock.return_value.client.servers.get_server.side_effect = [
|
||||
server_1_data,
|
||||
server_2_data,
|
||||
]
|
||||
server_data = {"1": server_1_data, "2": server_2_data}
|
||||
mock.return_value.client.servers.get_server.side_effect = lambda identifier: (
|
||||
server_data[identifier]
|
||||
)
|
||||
mock.return_value.client.servers.get_server_utilization.return_value = (
|
||||
utilization_data
|
||||
)
|
||||
|
||||
@@ -5,12 +5,13 @@ from typing import Any
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.remote import DOMAIN
|
||||
from homeassistant.const import ATTR_LABEL_ID, CONF_ENTITY_ID, STATE_OFF, STATE_ON
|
||||
from homeassistant.const import CONF_ENTITY_ID, STATE_OFF, STATE_ON
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
|
||||
from tests.components import (
|
||||
TriggerStateDescription,
|
||||
arm_trigger,
|
||||
assert_trigger_gated_by_labs_flag,
|
||||
parametrize_target_entities,
|
||||
parametrize_trigger_states,
|
||||
set_or_remove_state,
|
||||
@@ -32,13 +33,7 @@ async def test_remote_triggers_gated_by_labs_flag(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, trigger_key: str
|
||||
) -> None:
|
||||
"""Test the remote triggers are gated by the labs flag."""
|
||||
await arm_trigger(hass, trigger_key, None, {ATTR_LABEL_ID: "test_label"})
|
||||
assert (
|
||||
"Unnamed automation failed to setup triggers and has been disabled: Trigger "
|
||||
f"'{trigger_key}' requires the experimental 'New triggers and conditions' "
|
||||
"feature to be enabled in Home Assistant Labs settings (feature flag: "
|
||||
"'new_triggers_conditions')"
|
||||
) in caplog.text
|
||||
await assert_trigger_gated_by_labs_flag(hass, caplog, trigger_key)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("enable_labs_preview_features")
|
||||
|
||||
@@ -2,17 +2,13 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.const import (
|
||||
ATTR_LABEL_ID,
|
||||
CONF_ENTITY_ID,
|
||||
STATE_UNAVAILABLE,
|
||||
STATE_UNKNOWN,
|
||||
)
|
||||
from homeassistant.const import CONF_ENTITY_ID, STATE_UNAVAILABLE, STATE_UNKNOWN
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
|
||||
from tests.components import (
|
||||
TriggerStateDescription,
|
||||
arm_trigger,
|
||||
assert_trigger_gated_by_labs_flag,
|
||||
parametrize_target_entities,
|
||||
set_or_remove_state,
|
||||
target_entities,
|
||||
@@ -30,13 +26,7 @@ async def test_scene_triggers_gated_by_labs_flag(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, trigger_key: str
|
||||
) -> None:
|
||||
"""Test the scene triggers are gated by the labs flag."""
|
||||
await arm_trigger(hass, trigger_key, None, {ATTR_LABEL_ID: "test_label"})
|
||||
assert (
|
||||
"Unnamed automation failed to setup triggers and has been disabled: Trigger "
|
||||
f"'{trigger_key}' requires the experimental 'New triggers and conditions' "
|
||||
"feature to be enabled in Home Assistant Labs settings (feature flag: "
|
||||
"'new_triggers_conditions')"
|
||||
) in caplog.text
|
||||
await assert_trigger_gated_by_labs_flag(hass, caplog, trigger_key)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("enable_labs_preview_features")
|
||||
|
||||
@@ -14,7 +14,6 @@ from homeassistant.components.schedule.const import (
|
||||
DOMAIN,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
ATTR_LABEL_ID,
|
||||
CONF_ENTITY_ID,
|
||||
CONF_ICON,
|
||||
CONF_NAME,
|
||||
@@ -27,6 +26,7 @@ from tests.common import async_fire_time_changed
|
||||
from tests.components import (
|
||||
TriggerStateDescription,
|
||||
arm_trigger,
|
||||
assert_trigger_gated_by_labs_flag,
|
||||
parametrize_target_entities,
|
||||
parametrize_trigger_states,
|
||||
set_or_remove_state,
|
||||
@@ -51,13 +51,7 @@ async def test_schedule_triggers_gated_by_labs_flag(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, trigger_key: str
|
||||
) -> None:
|
||||
"""Test the schedule triggers are gated by the labs flag."""
|
||||
await arm_trigger(hass, trigger_key, None, {ATTR_LABEL_ID: "test_label"})
|
||||
assert (
|
||||
"Unnamed automation failed to setup triggers and has been disabled: Trigger "
|
||||
f"'{trigger_key}' requires the experimental 'New triggers and conditions' "
|
||||
"feature to be enabled in Home Assistant Labs settings (feature flag: "
|
||||
"'new_triggers_conditions')"
|
||||
) in caplog.text
|
||||
await assert_trigger_gated_by_labs_flag(hass, caplog, trigger_key)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("enable_labs_preview_features")
|
||||
|
||||
@@ -5,12 +5,13 @@ from typing import Any
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.siren import DOMAIN
|
||||
from homeassistant.const import ATTR_LABEL_ID, CONF_ENTITY_ID, STATE_OFF, STATE_ON
|
||||
from homeassistant.const import CONF_ENTITY_ID, STATE_OFF, STATE_ON
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
|
||||
from tests.components import (
|
||||
TriggerStateDescription,
|
||||
arm_trigger,
|
||||
assert_trigger_gated_by_labs_flag,
|
||||
parametrize_target_entities,
|
||||
parametrize_trigger_states,
|
||||
set_or_remove_state,
|
||||
@@ -35,13 +36,7 @@ async def test_siren_triggers_gated_by_labs_flag(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, trigger_key: str
|
||||
) -> None:
|
||||
"""Test the siren triggers are gated by the labs flag."""
|
||||
await arm_trigger(hass, trigger_key, None, {ATTR_LABEL_ID: "test_label"})
|
||||
assert (
|
||||
"Unnamed automation failed to setup triggers and has been disabled: Trigger "
|
||||
f"'{trigger_key}' requires the experimental 'New triggers and conditions' "
|
||||
"feature to be enabled in Home Assistant Labs settings (feature flag: "
|
||||
"'new_triggers_conditions')"
|
||||
) in caplog.text
|
||||
await assert_trigger_gated_by_labs_flag(hass, caplog, trigger_key)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("enable_labs_preview_features")
|
||||
|
||||
@@ -5,12 +5,13 @@ from typing import Any
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.switch import DOMAIN
|
||||
from homeassistant.const import ATTR_LABEL_ID, CONF_ENTITY_ID, STATE_OFF, STATE_ON
|
||||
from homeassistant.const import CONF_ENTITY_ID, STATE_OFF, STATE_ON
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
|
||||
from tests.components import (
|
||||
TriggerStateDescription,
|
||||
arm_trigger,
|
||||
assert_trigger_gated_by_labs_flag,
|
||||
parametrize_target_entities,
|
||||
parametrize_trigger_states,
|
||||
set_or_remove_state,
|
||||
@@ -35,13 +36,7 @@ async def test_switch_triggers_gated_by_labs_flag(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, trigger_key: str
|
||||
) -> None:
|
||||
"""Test the switch triggers are gated by the labs flag."""
|
||||
await arm_trigger(hass, trigger_key, None, {ATTR_LABEL_ID: "test_label"})
|
||||
assert (
|
||||
"Unnamed automation failed to setup triggers and has been disabled: Trigger "
|
||||
f"'{trigger_key}' requires the experimental 'New triggers and conditions' "
|
||||
"feature to be enabled in Home Assistant Labs settings (feature flag: "
|
||||
"'new_triggers_conditions')"
|
||||
) in caplog.text
|
||||
await assert_trigger_gated_by_labs_flag(hass, caplog, trigger_key)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("enable_labs_preview_features")
|
||||
|
||||
@@ -2,17 +2,13 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.const import (
|
||||
ATTR_LABEL_ID,
|
||||
CONF_ENTITY_ID,
|
||||
STATE_UNAVAILABLE,
|
||||
STATE_UNKNOWN,
|
||||
)
|
||||
from homeassistant.const import CONF_ENTITY_ID, STATE_UNAVAILABLE, STATE_UNKNOWN
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
|
||||
from tests.components import (
|
||||
TriggerStateDescription,
|
||||
arm_trigger,
|
||||
assert_trigger_gated_by_labs_flag,
|
||||
parametrize_target_entities,
|
||||
set_or_remove_state,
|
||||
target_entities,
|
||||
@@ -30,13 +26,7 @@ async def test_text_triggers_gated_by_labs_flag(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, trigger_key: str
|
||||
) -> None:
|
||||
"""Test the text triggers are gated by the labs flag."""
|
||||
await arm_trigger(hass, trigger_key, None, {ATTR_LABEL_ID: "test_label"})
|
||||
assert (
|
||||
"Unnamed automation failed to setup triggers and has been disabled: Trigger "
|
||||
f"'{trigger_key}' requires the experimental 'New triggers and conditions' "
|
||||
"feature to be enabled in Home Assistant Labs settings (feature flag: "
|
||||
"'new_triggers_conditions')"
|
||||
) in caplog.text
|
||||
await assert_trigger_gated_by_labs_flag(hass, caplog, trigger_key)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("enable_labs_preview_features")
|
||||
|
||||
@@ -5,12 +5,13 @@ from typing import Any
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.update import DOMAIN
|
||||
from homeassistant.const import ATTR_LABEL_ID, CONF_ENTITY_ID, STATE_OFF, STATE_ON
|
||||
from homeassistant.const import CONF_ENTITY_ID, STATE_OFF, STATE_ON
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
|
||||
from tests.components import (
|
||||
TriggerStateDescription,
|
||||
arm_trigger,
|
||||
assert_trigger_gated_by_labs_flag,
|
||||
parametrize_target_entities,
|
||||
parametrize_trigger_states,
|
||||
set_or_remove_state,
|
||||
@@ -34,13 +35,7 @@ async def test_update_triggers_gated_by_labs_flag(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, trigger_key: str
|
||||
) -> None:
|
||||
"""Test the update triggers are gated by the labs flag."""
|
||||
await arm_trigger(hass, trigger_key, None, {ATTR_LABEL_ID: "test_label"})
|
||||
assert (
|
||||
"Unnamed automation failed to setup triggers and has been disabled: Trigger "
|
||||
f"'{trigger_key}' requires the experimental 'New triggers and conditions' "
|
||||
"feature to be enabled in Home Assistant Labs settings (feature flag: "
|
||||
"'new_triggers_conditions')"
|
||||
) in caplog.text
|
||||
await assert_trigger_gated_by_labs_flag(hass, caplog, trigger_key)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("enable_labs_preview_features")
|
||||
|
||||
@@ -5,12 +5,13 @@ from typing import Any
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.vacuum import VacuumActivity
|
||||
from homeassistant.const import ATTR_LABEL_ID, CONF_ENTITY_ID
|
||||
from homeassistant.const import CONF_ENTITY_ID
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
|
||||
from tests.components import (
|
||||
TriggerStateDescription,
|
||||
arm_trigger,
|
||||
assert_trigger_gated_by_labs_flag,
|
||||
other_states,
|
||||
parametrize_target_entities,
|
||||
parametrize_trigger_states,
|
||||
@@ -39,13 +40,7 @@ async def test_vacuum_triggers_gated_by_labs_flag(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, trigger_key: str
|
||||
) -> None:
|
||||
"""Test the vacuum triggers are gated by the labs flag."""
|
||||
await arm_trigger(hass, trigger_key, None, {ATTR_LABEL_ID: "test_label"})
|
||||
assert (
|
||||
"Unnamed automation failed to setup triggers and has been disabled: Trigger "
|
||||
f"'{trigger_key}' requires the experimental 'New triggers and conditions' "
|
||||
"feature to be enabled in Home Assistant Labs settings (feature flag: "
|
||||
"'new_triggers_conditions')"
|
||||
) in caplog.text
|
||||
await assert_trigger_gated_by_labs_flag(hass, caplog, trigger_key)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("enable_labs_preview_features")
|
||||
|
||||
@@ -5,18 +5,13 @@ from typing import Any
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.cover import ATTR_IS_CLOSED, CoverState
|
||||
from homeassistant.const import (
|
||||
ATTR_DEVICE_CLASS,
|
||||
ATTR_LABEL_ID,
|
||||
CONF_ENTITY_ID,
|
||||
STATE_OFF,
|
||||
STATE_ON,
|
||||
)
|
||||
from homeassistant.const import ATTR_DEVICE_CLASS, CONF_ENTITY_ID, STATE_OFF, STATE_ON
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
|
||||
from tests.components import (
|
||||
TriggerStateDescription,
|
||||
arm_trigger,
|
||||
assert_trigger_gated_by_labs_flag,
|
||||
parametrize_target_entities,
|
||||
parametrize_trigger_states,
|
||||
set_or_remove_state,
|
||||
@@ -47,13 +42,7 @@ async def test_window_triggers_gated_by_labs_flag(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, trigger_key: str
|
||||
) -> None:
|
||||
"""Test the window triggers are gated by the labs flag."""
|
||||
await arm_trigger(hass, trigger_key, None, {ATTR_LABEL_ID: "test_label"})
|
||||
assert (
|
||||
"Unnamed automation failed to setup triggers and has been disabled: Trigger "
|
||||
f"'{trigger_key}' requires the experimental 'New triggers and conditions' "
|
||||
"feature to be enabled in Home Assistant Labs settings (feature flag: "
|
||||
"'new_triggers_conditions')"
|
||||
) in caplog.text
|
||||
await assert_trigger_gated_by_labs_flag(hass, caplog, trigger_key)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("enable_labs_preview_features")
|
||||
|
||||
@@ -1986,19 +1986,18 @@ def mock_bleak_scanner_start() -> Generator[MagicMock]:
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def hassio_env(supervisor_is_connected: AsyncMock) -> Generator[None]:
|
||||
def hassio_env(
|
||||
supervisor_is_connected: AsyncMock, supervisor_root_info: AsyncMock
|
||||
) -> Generator[None]:
|
||||
"""Fixture to inject hassio env."""
|
||||
from homeassistant.components.hassio import HassioAPIError # noqa: PLC0415
|
||||
from aiohasupervisor import SupervisorError # noqa: PLC0415
|
||||
|
||||
from .components.hassio import SUPERVISOR_TOKEN # noqa: PLC0415
|
||||
|
||||
supervisor_root_info.side_effect = SupervisorError()
|
||||
with (
|
||||
patch.dict(os.environ, {"SUPERVISOR": "127.0.0.1"}),
|
||||
patch.dict(os.environ, {"SUPERVISOR_TOKEN": SUPERVISOR_TOKEN}),
|
||||
patch(
|
||||
"homeassistant.components.hassio.HassIO.get_info",
|
||||
Mock(side_effect=HassioAPIError()),
|
||||
),
|
||||
):
|
||||
yield
|
||||
|
||||
@@ -2012,8 +2011,6 @@ async def hassio_stubs(
|
||||
supervisor_client: AsyncMock,
|
||||
) -> RefreshToken:
|
||||
"""Create mock hassio http client."""
|
||||
from homeassistant.components.hassio import HassioAPIError # noqa: PLC0415
|
||||
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.hassio.HassIO.update_hass_api",
|
||||
@@ -2023,10 +2020,6 @@ async def hassio_stubs(
|
||||
"homeassistant.components.hassio.HassIO.update_hass_config",
|
||||
return_value={"result": "ok"},
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.hassio.HassIO.get_info",
|
||||
side_effect=HassioAPIError(),
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.hassio.HassIO.get_ingress_panels",
|
||||
return_value={"panels": []},
|
||||
|
||||
Reference in New Issue
Block a user