Create Repairs based on Alerts (#75397)
Co-authored-by: Paulus Schoutsen <balloob@gmail.com> Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
parent
bbdce93291
commit
51c3836ec2
15 changed files with 1078 additions and 0 deletions
|
@ -115,6 +115,7 @@ homeassistant.components.group.*
|
||||||
homeassistant.components.guardian.*
|
homeassistant.components.guardian.*
|
||||||
homeassistant.components.history.*
|
homeassistant.components.history.*
|
||||||
homeassistant.components.homeassistant.triggers.event
|
homeassistant.components.homeassistant.triggers.event
|
||||||
|
homeassistant.components.homeassistant_alerts.*
|
||||||
homeassistant.components.homekit
|
homeassistant.components.homekit
|
||||||
homeassistant.components.homekit.accessories
|
homeassistant.components.homekit.accessories
|
||||||
homeassistant.components.homekit.aidmanager
|
homeassistant.components.homekit.aidmanager
|
||||||
|
|
|
@ -455,6 +455,8 @@ build.json @home-assistant/supervisor
|
||||||
/tests/components/home_plus_control/ @chemaaa
|
/tests/components/home_plus_control/ @chemaaa
|
||||||
/homeassistant/components/homeassistant/ @home-assistant/core
|
/homeassistant/components/homeassistant/ @home-assistant/core
|
||||||
/tests/components/homeassistant/ @home-assistant/core
|
/tests/components/homeassistant/ @home-assistant/core
|
||||||
|
/homeassistant/components/homeassistant_alerts/ @home-assistant/core
|
||||||
|
/tests/components/homeassistant_alerts/ @home-assistant/core
|
||||||
/homeassistant/components/homeassistant_yellow/ @home-assistant/core
|
/homeassistant/components/homeassistant_yellow/ @home-assistant/core
|
||||||
/tests/components/homeassistant_yellow/ @home-assistant/core
|
/tests/components/homeassistant_yellow/ @home-assistant/core
|
||||||
/homeassistant/components/homekit/ @bdraco
|
/homeassistant/components/homekit/ @bdraco
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
"dhcp",
|
"dhcp",
|
||||||
"energy",
|
"energy",
|
||||||
"frontend",
|
"frontend",
|
||||||
|
"homeassistant_alerts",
|
||||||
"history",
|
"history",
|
||||||
"input_boolean",
|
"input_boolean",
|
||||||
"input_button",
|
"input_button",
|
||||||
|
|
185
homeassistant/components/homeassistant_alerts/__init__.py
Normal file
185
homeassistant/components/homeassistant_alerts/__init__.py
Normal file
|
@ -0,0 +1,185 @@
|
||||||
|
"""The Home Assistant alerts integration."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
import dataclasses
|
||||||
|
from datetime import timedelta
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import aiohttp
|
||||||
|
from awesomeversion import AwesomeVersion, AwesomeVersionStrategy
|
||||||
|
|
||||||
|
from homeassistant.components.repairs import async_create_issue, async_delete_issue
|
||||||
|
from homeassistant.components.repairs.models import IssueSeverity
|
||||||
|
from homeassistant.const import __version__
|
||||||
|
from homeassistant.core import HomeAssistant, callback
|
||||||
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
|
from homeassistant.helpers.typing import ConfigType
|
||||||
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||||
|
from homeassistant.util.yaml import parse_yaml
|
||||||
|
|
||||||
|
DOMAIN = "homeassistant_alerts"
|
||||||
|
UPDATE_INTERVAL = timedelta(hours=3)
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||||
|
"""Set up alerts."""
|
||||||
|
last_alerts: dict[str, str | None] = {}
|
||||||
|
|
||||||
|
async def async_update_alerts() -> None:
|
||||||
|
nonlocal last_alerts
|
||||||
|
|
||||||
|
active_alerts: dict[str, str | None] = {}
|
||||||
|
|
||||||
|
for issue_id, alert in coordinator.data.items():
|
||||||
|
# Skip creation if already created and not updated since then
|
||||||
|
if issue_id in last_alerts and alert.date_updated == last_alerts[issue_id]:
|
||||||
|
active_alerts[issue_id] = alert.date_updated
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Fetch alert to get title + description
|
||||||
|
try:
|
||||||
|
response = await async_get_clientsession(hass).get(
|
||||||
|
f"https://alerts.home-assistant.io/alerts/{alert.filename}",
|
||||||
|
timeout=aiohttp.ClientTimeout(total=10),
|
||||||
|
)
|
||||||
|
except asyncio.TimeoutError:
|
||||||
|
_LOGGER.warning("Error fetching %s: timeout", alert.filename)
|
||||||
|
continue
|
||||||
|
|
||||||
|
alert_content = await response.text()
|
||||||
|
alert_parts = alert_content.split("---")
|
||||||
|
|
||||||
|
if len(alert_parts) != 3:
|
||||||
|
_LOGGER.warning(
|
||||||
|
"Error parsing %s: unexpected metadata format", alert.filename
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
alert_info = parse_yaml(alert_parts[1])
|
||||||
|
except ValueError as err:
|
||||||
|
_LOGGER.warning("Error parsing %s metadata: %s", alert.filename, err)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not isinstance(alert_info, dict) or "title" not in alert_info:
|
||||||
|
_LOGGER.warning("Error in %s metadata: title not found", alert.filename)
|
||||||
|
continue
|
||||||
|
|
||||||
|
alert_title = alert_info["title"]
|
||||||
|
alert_content = alert_parts[2].strip()
|
||||||
|
|
||||||
|
async_create_issue(
|
||||||
|
hass,
|
||||||
|
DOMAIN,
|
||||||
|
issue_id,
|
||||||
|
is_fixable=False,
|
||||||
|
learn_more_url=alert.alert_url,
|
||||||
|
severity=IssueSeverity.WARNING,
|
||||||
|
translation_key="alert",
|
||||||
|
translation_placeholders={
|
||||||
|
"title": alert_title,
|
||||||
|
"description": alert_content,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
active_alerts[issue_id] = alert.date_updated
|
||||||
|
|
||||||
|
inactive_alerts = last_alerts.keys() - active_alerts.keys()
|
||||||
|
for issue_id in inactive_alerts:
|
||||||
|
async_delete_issue(hass, DOMAIN, issue_id)
|
||||||
|
|
||||||
|
last_alerts = active_alerts
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def async_schedule_update_alerts() -> None:
|
||||||
|
if not coordinator.last_update_success:
|
||||||
|
return
|
||||||
|
|
||||||
|
hass.async_create_task(async_update_alerts())
|
||||||
|
|
||||||
|
coordinator = AlertUpdateCoordinator(hass)
|
||||||
|
coordinator.async_add_listener(async_schedule_update_alerts)
|
||||||
|
await coordinator.async_refresh()
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@dataclasses.dataclass(frozen=True)
|
||||||
|
class IntegrationAlert:
|
||||||
|
"""Issue Registry Entry."""
|
||||||
|
|
||||||
|
integration: str
|
||||||
|
filename: str
|
||||||
|
date_updated: str | None
|
||||||
|
alert_url: str | None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def issue_id(self) -> str:
|
||||||
|
"""Return the issue id."""
|
||||||
|
return f"{self.filename}_{self.integration}"
|
||||||
|
|
||||||
|
|
||||||
|
class AlertUpdateCoordinator(DataUpdateCoordinator[dict[str, IntegrationAlert]]):
|
||||||
|
"""Data fetcher for HA Alerts."""
|
||||||
|
|
||||||
|
def __init__(self, hass: HomeAssistant) -> None:
|
||||||
|
"""Initialize the data updater."""
|
||||||
|
super().__init__(
|
||||||
|
hass,
|
||||||
|
_LOGGER,
|
||||||
|
name=DOMAIN,
|
||||||
|
update_interval=UPDATE_INTERVAL,
|
||||||
|
)
|
||||||
|
self.ha_version = AwesomeVersion(
|
||||||
|
__version__,
|
||||||
|
ensure_strategy=AwesomeVersionStrategy.CALVER,
|
||||||
|
find_first_match=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def _async_update_data(self) -> dict[str, IntegrationAlert]:
|
||||||
|
response = await async_get_clientsession(self.hass).get(
|
||||||
|
"https://alerts.home-assistant.io/alerts.json",
|
||||||
|
timeout=aiohttp.ClientTimeout(total=10),
|
||||||
|
)
|
||||||
|
alerts = await response.json()
|
||||||
|
|
||||||
|
result = {}
|
||||||
|
|
||||||
|
for alert in alerts:
|
||||||
|
if "alert_url" not in alert or "integrations" not in alert:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if "homeassistant" in alert:
|
||||||
|
if "affected_from_version" in alert["homeassistant"]:
|
||||||
|
affected_from_version = AwesomeVersion(
|
||||||
|
alert["homeassistant"]["affected_from_version"],
|
||||||
|
find_first_match=False,
|
||||||
|
)
|
||||||
|
if self.ha_version < affected_from_version:
|
||||||
|
continue
|
||||||
|
if "resolved_in_version" in alert["homeassistant"]:
|
||||||
|
resolved_in_version = AwesomeVersion(
|
||||||
|
alert["homeassistant"]["resolved_in_version"],
|
||||||
|
find_first_match=False,
|
||||||
|
)
|
||||||
|
if self.ha_version >= resolved_in_version:
|
||||||
|
continue
|
||||||
|
|
||||||
|
for integration in alert["integrations"]:
|
||||||
|
if "package" not in integration:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if integration["package"] not in self.hass.config.components:
|
||||||
|
continue
|
||||||
|
|
||||||
|
integration_alert = IntegrationAlert(
|
||||||
|
integration=integration["package"],
|
||||||
|
filename=alert["filename"],
|
||||||
|
date_updated=alert.get("date_updated"),
|
||||||
|
alert_url=alert["alert_url"],
|
||||||
|
)
|
||||||
|
|
||||||
|
result[integration_alert.issue_id] = integration_alert
|
||||||
|
|
||||||
|
return result
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"domain": "homeassistant_alerts",
|
||||||
|
"name": "Home Assistant alerts",
|
||||||
|
"config_flow": false,
|
||||||
|
"documentation": "https://www.home-assistant.io/integrations/homeassistant_alerts",
|
||||||
|
"codeowners": ["@home-assistant/core"],
|
||||||
|
"dependencies": ["repairs"]
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"issues": {
|
||||||
|
"alert": {
|
||||||
|
"title": "{title}",
|
||||||
|
"description": "{description}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
mypy.ini
11
mypy.ini
|
@ -988,6 +988,17 @@ no_implicit_optional = true
|
||||||
warn_return_any = true
|
warn_return_any = true
|
||||||
warn_unreachable = true
|
warn_unreachable = true
|
||||||
|
|
||||||
|
[mypy-homeassistant.components.homeassistant_alerts.*]
|
||||||
|
check_untyped_defs = true
|
||||||
|
disallow_incomplete_defs = true
|
||||||
|
disallow_subclassing_any = true
|
||||||
|
disallow_untyped_calls = true
|
||||||
|
disallow_untyped_decorators = true
|
||||||
|
disallow_untyped_defs = true
|
||||||
|
no_implicit_optional = true
|
||||||
|
warn_return_any = true
|
||||||
|
warn_unreachable = true
|
||||||
|
|
||||||
[mypy-homeassistant.components.homekit]
|
[mypy-homeassistant.components.homekit]
|
||||||
check_untyped_defs = true
|
check_untyped_defs = true
|
||||||
disallow_incomplete_defs = true
|
disallow_incomplete_defs = true
|
||||||
|
|
|
@ -56,6 +56,7 @@ NO_IOT_CLASS = [
|
||||||
"hardware",
|
"hardware",
|
||||||
"history",
|
"history",
|
||||||
"homeassistant",
|
"homeassistant",
|
||||||
|
"homeassistant_alerts",
|
||||||
"homeassistant_yellow",
|
"homeassistant_yellow",
|
||||||
"image",
|
"image",
|
||||||
"input_boolean",
|
"input_boolean",
|
||||||
|
|
1
tests/components/homeassistant_alerts/__init__.py
Normal file
1
tests/components/homeassistant_alerts/__init__.py
Normal file
|
@ -0,0 +1 @@
|
||||||
|
"""Tests for the Home Assistant alerts integration."""
|
174
tests/components/homeassistant_alerts/fixtures/alerts_1.json
Normal file
174
tests/components/homeassistant_alerts/fixtures/alerts_1.json
Normal file
|
@ -0,0 +1,174 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"title": "Aladdin Connect is turning off their previous connection method",
|
||||||
|
"created": "2022-07-14T06:00:00.000Z",
|
||||||
|
"integrations": [
|
||||||
|
{
|
||||||
|
"package": "aladdin_connect"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"homeassistant": {
|
||||||
|
"package": "homeassistant",
|
||||||
|
"resolved_in_version": "2022.7"
|
||||||
|
},
|
||||||
|
"filename": "aladdin_connect.markdown",
|
||||||
|
"alert_url": "https://alerts.home-assistant.io/#aladdin_connect.markdown"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Dark Sky API closed for new users",
|
||||||
|
"created": "2020-03-31T14:40:00.000Z",
|
||||||
|
"integrations": [
|
||||||
|
{
|
||||||
|
"package": "darksky"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"github_issue": "https://github.com/home-assistant/home-assistant.io/pull/12591",
|
||||||
|
"homeassistant": {
|
||||||
|
"package": "homeassistant",
|
||||||
|
"affected_from_version": "0.30"
|
||||||
|
},
|
||||||
|
"filename": "dark_sky.markdown",
|
||||||
|
"alert_url": "https://alerts.home-assistant.io/#dark_sky.markdown"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Hikvision Security Vulnerability",
|
||||||
|
"created": "2021-09-20T22:08:00.000Z",
|
||||||
|
"integrations": [
|
||||||
|
{
|
||||||
|
"package": "hikvision"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"package": "hikvisioncam"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filename": "hikvision.markdown",
|
||||||
|
"alert_url": "https://alerts.home-assistant.io/#hikvision.markdown",
|
||||||
|
"homeassistant": {
|
||||||
|
"package": "homeassistant"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Hive shutting down North American Servers",
|
||||||
|
"created": "2021-11-13T13:58:00.000Z",
|
||||||
|
"integrations": [
|
||||||
|
{
|
||||||
|
"package": "hive"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"homeassistant": {
|
||||||
|
"package": "homeassistant",
|
||||||
|
"affected_from_version": "2021.11.0"
|
||||||
|
},
|
||||||
|
"filename": "hive_us.markdown",
|
||||||
|
"alert_url": "https://alerts.home-assistant.io/#hive_us.markdown"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "HomematicIP (EQ-3) blocks public IP addresses, if access to the Cloud is too frequent.",
|
||||||
|
"created": "2020-12-20T12:00:00.000Z",
|
||||||
|
"integrations": [
|
||||||
|
{
|
||||||
|
"package": "homematicip_cloud"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"packages": [
|
||||||
|
{
|
||||||
|
"package": "homematicip"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"homeassistant": {
|
||||||
|
"package": "homeassistant",
|
||||||
|
"affected_from_version": "0.7"
|
||||||
|
},
|
||||||
|
"filename": "homematicip_cloud.markdown",
|
||||||
|
"alert_url": "https://alerts.home-assistant.io/#homematicip_cloud.markdown"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Logitech no longer accepting API applications",
|
||||||
|
"created": "2022-05-16T12:00:00.000Z",
|
||||||
|
"integrations": [
|
||||||
|
{
|
||||||
|
"package": "logi_circle"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"github_issue": "https://github.com/home-assistant/core/issues/71945",
|
||||||
|
"homeassistant": {
|
||||||
|
"package": "homeassistant",
|
||||||
|
"affected_from_version": "0.92.0"
|
||||||
|
},
|
||||||
|
"filename": "logi_circle.markdown",
|
||||||
|
"alert_url": "https://alerts.home-assistant.io/#logi_circle.markdown"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "New Neato Botvacs Do Not Support Existing API",
|
||||||
|
"created": "2021-12-20T13:27:00.000Z",
|
||||||
|
"integrations": [
|
||||||
|
{
|
||||||
|
"package": "neato"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"homeassistant": {
|
||||||
|
"package": "homeassistant",
|
||||||
|
"affected_from_version": "0.30"
|
||||||
|
},
|
||||||
|
"filename": "neato.markdown",
|
||||||
|
"alert_url": "https://alerts.home-assistant.io/#neato.markdown"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Nest Desktop Auth Deprecation",
|
||||||
|
"created": "2022-05-12T14:04:00.000Z",
|
||||||
|
"integrations": [
|
||||||
|
{
|
||||||
|
"package": "nest"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"github_issue": "https://github.com/home-assistant/core/issues/67662#issuecomment-1144425848",
|
||||||
|
"filename": "nest.markdown",
|
||||||
|
"alert_url": "https://alerts.home-assistant.io/#nest.markdown",
|
||||||
|
"homeassistant": {
|
||||||
|
"package": "homeassistant"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Haiku Firmware Update Protocol Change",
|
||||||
|
"created": "2022-04-05T00:00:00.000Z",
|
||||||
|
"integrations": [
|
||||||
|
{
|
||||||
|
"package": "senseme"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filename": "senseme.markdown",
|
||||||
|
"alert_url": "https://alerts.home-assistant.io/#senseme.markdown",
|
||||||
|
"homeassistant": {
|
||||||
|
"package": "homeassistant"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "The SoChain integration is disabled due to a dependency conflict",
|
||||||
|
"created": "2022-02-01T00:00:00.000Z",
|
||||||
|
"integrations": [
|
||||||
|
{
|
||||||
|
"package": "sochain"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filename": "sochain.markdown",
|
||||||
|
"alert_url": "https://alerts.home-assistant.io/#sochain.markdown",
|
||||||
|
"homeassistant": {
|
||||||
|
"package": "homeassistant"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Yeelight-manufactured Xiaomi-branded devices removed Local Control",
|
||||||
|
"created": "2021-03-29T06:00:00.000Z",
|
||||||
|
"integrations": [
|
||||||
|
{
|
||||||
|
"package": "yeelight"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"homeassistant": {
|
||||||
|
"package": "homeassistant",
|
||||||
|
"affected_from_version": "0.89"
|
||||||
|
},
|
||||||
|
"filename": "yeelight.markdown",
|
||||||
|
"alert_url": "https://alerts.home-assistant.io/#yeelight.markdown"
|
||||||
|
}
|
||||||
|
]
|
159
tests/components/homeassistant_alerts/fixtures/alerts_2.json
Normal file
159
tests/components/homeassistant_alerts/fixtures/alerts_2.json
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"title": "Dark Sky API closed for new users",
|
||||||
|
"created": "2020-03-31T14:40:00.000Z",
|
||||||
|
"integrations": [
|
||||||
|
{
|
||||||
|
"package": "darksky"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"github_issue": "https://github.com/home-assistant/home-assistant.io/pull/12591",
|
||||||
|
"homeassistant": {
|
||||||
|
"package": "homeassistant",
|
||||||
|
"affected_from_version": "0.30"
|
||||||
|
},
|
||||||
|
"filename": "dark_sky.markdown",
|
||||||
|
"alert_url": "https://alerts.home-assistant.io/#dark_sky.markdown"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Hikvision Security Vulnerability",
|
||||||
|
"created": "2021-09-20T22:08:00.000Z",
|
||||||
|
"integrations": [
|
||||||
|
{
|
||||||
|
"package": "hikvision"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"package": "hikvisioncam"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filename": "hikvision.markdown",
|
||||||
|
"alert_url": "https://alerts.home-assistant.io/#hikvision.markdown",
|
||||||
|
"homeassistant": {
|
||||||
|
"package": "homeassistant"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Hive shutting down North American Servers",
|
||||||
|
"created": "2021-11-13T13:58:00.000Z",
|
||||||
|
"integrations": [
|
||||||
|
{
|
||||||
|
"package": "hive"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"homeassistant": {
|
||||||
|
"package": "homeassistant",
|
||||||
|
"affected_from_version": "2021.11.0"
|
||||||
|
},
|
||||||
|
"filename": "hive_us.markdown",
|
||||||
|
"alert_url": "https://alerts.home-assistant.io/#hive_us.markdown"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "HomematicIP (EQ-3) blocks public IP addresses, if access to the Cloud is too frequent.",
|
||||||
|
"created": "2020-12-20T12:00:00.000Z",
|
||||||
|
"integrations": [
|
||||||
|
{
|
||||||
|
"package": "homematicip_cloud"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"packages": [
|
||||||
|
{
|
||||||
|
"package": "homematicip"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"homeassistant": {
|
||||||
|
"package": "homeassistant",
|
||||||
|
"affected_from_version": "0.7"
|
||||||
|
},
|
||||||
|
"filename": "homematicip_cloud.markdown",
|
||||||
|
"alert_url": "https://alerts.home-assistant.io/#homematicip_cloud.markdown"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Logitech no longer accepting API applications",
|
||||||
|
"created": "2022-05-16T12:00:00.000Z",
|
||||||
|
"integrations": [
|
||||||
|
{
|
||||||
|
"package": "logi_circle"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"github_issue": "https://github.com/home-assistant/core/issues/71945",
|
||||||
|
"homeassistant": {
|
||||||
|
"package": "homeassistant",
|
||||||
|
"affected_from_version": "0.92.0"
|
||||||
|
},
|
||||||
|
"filename": "logi_circle.markdown",
|
||||||
|
"alert_url": "https://alerts.home-assistant.io/#logi_circle.markdown"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "New Neato Botvacs Do Not Support Existing API",
|
||||||
|
"created": "2021-12-20T13:27:00.000Z",
|
||||||
|
"integrations": [
|
||||||
|
{
|
||||||
|
"package": "neato"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"homeassistant": {
|
||||||
|
"package": "homeassistant",
|
||||||
|
"affected_from_version": "0.30"
|
||||||
|
},
|
||||||
|
"filename": "neato.markdown",
|
||||||
|
"alert_url": "https://alerts.home-assistant.io/#neato.markdown"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Nest Desktop Auth Deprecation",
|
||||||
|
"created": "2022-05-12T14:04:00.000Z",
|
||||||
|
"integrations": [
|
||||||
|
{
|
||||||
|
"package": "nest"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"github_issue": "https://github.com/home-assistant/core/issues/67662#issuecomment-1144425848",
|
||||||
|
"filename": "nest.markdown",
|
||||||
|
"alert_url": "https://alerts.home-assistant.io/#nest.markdown",
|
||||||
|
"homeassistant": {
|
||||||
|
"package": "homeassistant"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Haiku Firmware Update Protocol Change",
|
||||||
|
"created": "2022-04-05T00:00:00.000Z",
|
||||||
|
"integrations": [
|
||||||
|
{
|
||||||
|
"package": "senseme"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filename": "senseme.markdown",
|
||||||
|
"alert_url": "https://alerts.home-assistant.io/#senseme.markdown",
|
||||||
|
"homeassistant": {
|
||||||
|
"package": "homeassistant"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "The SoChain integration is disabled due to a dependency conflict",
|
||||||
|
"created": "2022-02-01T00:00:00.000Z",
|
||||||
|
"integrations": [
|
||||||
|
{
|
||||||
|
"package": "sochain"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filename": "sochain.markdown",
|
||||||
|
"alert_url": "https://alerts.home-assistant.io/#sochain.markdown",
|
||||||
|
"homeassistant": {
|
||||||
|
"package": "homeassistant"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Yeelight-manufactured Xiaomi-branded devices removed Local Control",
|
||||||
|
"created": "2021-03-29T06:00:00.000Z",
|
||||||
|
"integrations": [
|
||||||
|
{
|
||||||
|
"package": "yeelight"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"homeassistant": {
|
||||||
|
"package": "homeassistant",
|
||||||
|
"affected_from_version": "0.89"
|
||||||
|
},
|
||||||
|
"filename": "yeelight.markdown",
|
||||||
|
"alert_url": "https://alerts.home-assistant.io/#yeelight.markdown"
|
||||||
|
}
|
||||||
|
]
|
|
@ -0,0 +1,27 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"title": "Dark Sky API closed for new users",
|
||||||
|
"created": "2020-03-31T14:40:00.000Z",
|
||||||
|
"integrations": [
|
||||||
|
{
|
||||||
|
"package": "darksky"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"github_issue": "https://github.com/home-assistant/home-assistant.io/pull/12591",
|
||||||
|
"homeassistant": {
|
||||||
|
"package": "homeassistant",
|
||||||
|
"affected_from_version": "0.30"
|
||||||
|
},
|
||||||
|
"filename": "dark_sky.markdown",
|
||||||
|
"alert_url": "https://alerts.home-assistant.io/#dark_sky.markdown"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Hikvision Security Vulnerability",
|
||||||
|
"created": "2021-09-20T22:08:00.000Z",
|
||||||
|
"filename": "hikvision.markdown",
|
||||||
|
"alert_url": "https://alerts.home-assistant.io/#hikvision.markdown",
|
||||||
|
"homeassistant": {
|
||||||
|
"package": "homeassistant"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
|
@ -0,0 +1,33 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"title": "Dark Sky API closed for new users",
|
||||||
|
"created": "2020-03-31T14:40:00.000Z",
|
||||||
|
"integrations": [
|
||||||
|
{
|
||||||
|
"package": "darksky"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"github_issue": "https://github.com/home-assistant/home-assistant.io/pull/12591",
|
||||||
|
"homeassistant": {
|
||||||
|
"package": "homeassistant",
|
||||||
|
"affected_from_version": "0.30"
|
||||||
|
},
|
||||||
|
"filename": "dark_sky.markdown",
|
||||||
|
"alert_url": "https://alerts.home-assistant.io/#dark_sky.markdown"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Hikvision Security Vulnerability",
|
||||||
|
"created": "2021-09-20T22:08:00.000Z",
|
||||||
|
"integrations": [
|
||||||
|
{
|
||||||
|
"package": "hikvision"
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
],
|
||||||
|
"filename": "hikvision.markdown",
|
||||||
|
"alert_url": "https://alerts.home-assistant.io/#hikvision.markdown",
|
||||||
|
"homeassistant": {
|
||||||
|
"package": "homeassistant"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
|
@ -0,0 +1,34 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"title": "Dark Sky API closed for new users",
|
||||||
|
"created": "2020-03-31T14:40:00.000Z",
|
||||||
|
"integrations": [
|
||||||
|
{
|
||||||
|
"package": "darksky"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"github_issue": "https://github.com/home-assistant/home-assistant.io/pull/12591",
|
||||||
|
"homeassistant": {
|
||||||
|
"package": "homeassistant",
|
||||||
|
"affected_from_version": "0.30"
|
||||||
|
},
|
||||||
|
"filename": "dark_sky.markdown",
|
||||||
|
"alert_url": "https://alerts.home-assistant.io/#dark_sky.markdown"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Hikvision Security Vulnerability",
|
||||||
|
"created": "2021-09-20T22:08:00.000Z",
|
||||||
|
"integrations": [
|
||||||
|
{
|
||||||
|
"package": "hikvision"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"package": "hikvisioncam"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filename": "hikvision.markdown",
|
||||||
|
"homeassistant": {
|
||||||
|
"package": "homeassistant"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
433
tests/components/homeassistant_alerts/test_init.py
Normal file
433
tests/components/homeassistant_alerts/test_init.py
Normal file
|
@ -0,0 +1,433 @@
|
||||||
|
"""Test creating repairs from alerts."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from datetime import timedelta
|
||||||
|
import json
|
||||||
|
from unittest.mock import ANY, patch
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from homeassistant.components.homeassistant_alerts import DOMAIN, UPDATE_INTERVAL
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.setup import async_setup_component
|
||||||
|
from homeassistant.util import dt as dt_util
|
||||||
|
|
||||||
|
from tests.common import assert_lists_same, async_fire_time_changed, load_fixture
|
||||||
|
from tests.test_util.aiohttp import AiohttpClientMocker
|
||||||
|
|
||||||
|
|
||||||
|
def stub_alert(aioclient_mock, filename):
|
||||||
|
"""Stub an alert."""
|
||||||
|
aioclient_mock.get(
|
||||||
|
f"https://alerts.home-assistant.io/alerts/{filename}",
|
||||||
|
text=f"""---
|
||||||
|
title: Title for {filename}
|
||||||
|
---
|
||||||
|
Content for {filename}
|
||||||
|
""",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"ha_version, expected_alerts",
|
||||||
|
(
|
||||||
|
(
|
||||||
|
"2022.7.0",
|
||||||
|
[
|
||||||
|
("aladdin_connect.markdown", "aladdin_connect"),
|
||||||
|
("dark_sky.markdown", "darksky"),
|
||||||
|
("hikvision.markdown", "hikvision"),
|
||||||
|
("hikvision.markdown", "hikvisioncam"),
|
||||||
|
("hive_us.markdown", "hive"),
|
||||||
|
("homematicip_cloud.markdown", "homematicip_cloud"),
|
||||||
|
("logi_circle.markdown", "logi_circle"),
|
||||||
|
("neato.markdown", "neato"),
|
||||||
|
("nest.markdown", "nest"),
|
||||||
|
("senseme.markdown", "senseme"),
|
||||||
|
("sochain.markdown", "sochain"),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"2022.8.0",
|
||||||
|
[
|
||||||
|
("dark_sky.markdown", "darksky"),
|
||||||
|
("hikvision.markdown", "hikvision"),
|
||||||
|
("hikvision.markdown", "hikvisioncam"),
|
||||||
|
("hive_us.markdown", "hive"),
|
||||||
|
("homematicip_cloud.markdown", "homematicip_cloud"),
|
||||||
|
("logi_circle.markdown", "logi_circle"),
|
||||||
|
("neato.markdown", "neato"),
|
||||||
|
("nest.markdown", "nest"),
|
||||||
|
("senseme.markdown", "senseme"),
|
||||||
|
("sochain.markdown", "sochain"),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"2021.10.0",
|
||||||
|
[
|
||||||
|
("aladdin_connect.markdown", "aladdin_connect"),
|
||||||
|
("dark_sky.markdown", "darksky"),
|
||||||
|
("hikvision.markdown", "hikvision"),
|
||||||
|
("hikvision.markdown", "hikvisioncam"),
|
||||||
|
("homematicip_cloud.markdown", "homematicip_cloud"),
|
||||||
|
("logi_circle.markdown", "logi_circle"),
|
||||||
|
("neato.markdown", "neato"),
|
||||||
|
("nest.markdown", "nest"),
|
||||||
|
("senseme.markdown", "senseme"),
|
||||||
|
("sochain.markdown", "sochain"),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
async def test_alerts(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
hass_ws_client,
|
||||||
|
aioclient_mock: AiohttpClientMocker,
|
||||||
|
ha_version,
|
||||||
|
expected_alerts,
|
||||||
|
) -> None:
|
||||||
|
"""Test creating issues based on alerts."""
|
||||||
|
|
||||||
|
aioclient_mock.clear_requests()
|
||||||
|
aioclient_mock.get(
|
||||||
|
"https://alerts.home-assistant.io/alerts.json",
|
||||||
|
text=load_fixture("alerts_1.json", "homeassistant_alerts"),
|
||||||
|
)
|
||||||
|
for alert in expected_alerts:
|
||||||
|
stub_alert(aioclient_mock, alert[0])
|
||||||
|
|
||||||
|
activated_components = (
|
||||||
|
"aladdin_connect",
|
||||||
|
"darksky",
|
||||||
|
"hikvision",
|
||||||
|
"hikvisioncam",
|
||||||
|
"hive",
|
||||||
|
"homematicip_cloud",
|
||||||
|
"logi_circle",
|
||||||
|
"neato",
|
||||||
|
"nest",
|
||||||
|
"senseme",
|
||||||
|
"sochain",
|
||||||
|
)
|
||||||
|
for domain in activated_components:
|
||||||
|
hass.config.components.add(domain)
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.homeassistant_alerts.__version__",
|
||||||
|
ha_version,
|
||||||
|
):
|
||||||
|
assert await async_setup_component(hass, DOMAIN, {})
|
||||||
|
|
||||||
|
client = await hass_ws_client(hass)
|
||||||
|
|
||||||
|
await client.send_json({"id": 1, "type": "repairs/list_issues"})
|
||||||
|
msg = await client.receive_json()
|
||||||
|
assert msg["success"]
|
||||||
|
assert msg["result"] == {
|
||||||
|
"issues": [
|
||||||
|
{
|
||||||
|
"breaks_in_ha_version": None,
|
||||||
|
"created": ANY,
|
||||||
|
"dismissed_version": None,
|
||||||
|
"domain": "homeassistant_alerts",
|
||||||
|
"ignored": False,
|
||||||
|
"is_fixable": False,
|
||||||
|
"issue_id": f"{alert}_{integration}",
|
||||||
|
"learn_more_url": f"https://alerts.home-assistant.io/#{alert}",
|
||||||
|
"severity": "warning",
|
||||||
|
"translation_key": "alert",
|
||||||
|
"translation_placeholders": {
|
||||||
|
"title": f"Title for {alert}",
|
||||||
|
"description": f"Content for {alert}",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for alert, integration in expected_alerts
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"ha_version, fixture, expected_alerts",
|
||||||
|
(
|
||||||
|
(
|
||||||
|
"2022.7.0",
|
||||||
|
"alerts_no_url.json",
|
||||||
|
[
|
||||||
|
("dark_sky.markdown", "darksky"),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"2022.7.0",
|
||||||
|
"alerts_no_integrations.json",
|
||||||
|
[
|
||||||
|
("dark_sky.markdown", "darksky"),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"2022.7.0",
|
||||||
|
"alerts_no_package.json",
|
||||||
|
[
|
||||||
|
("dark_sky.markdown", "darksky"),
|
||||||
|
("hikvision.markdown", "hikvision"),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
async def test_bad_alerts(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
hass_ws_client,
|
||||||
|
aioclient_mock: AiohttpClientMocker,
|
||||||
|
ha_version,
|
||||||
|
fixture,
|
||||||
|
expected_alerts,
|
||||||
|
) -> None:
|
||||||
|
"""Test creating issues based on alerts."""
|
||||||
|
fixture_content = load_fixture(fixture, "homeassistant_alerts")
|
||||||
|
aioclient_mock.clear_requests()
|
||||||
|
aioclient_mock.get(
|
||||||
|
"https://alerts.home-assistant.io/alerts.json",
|
||||||
|
text=fixture_content,
|
||||||
|
)
|
||||||
|
for alert in json.loads(fixture_content):
|
||||||
|
stub_alert(aioclient_mock, alert["filename"])
|
||||||
|
|
||||||
|
activated_components = (
|
||||||
|
"darksky",
|
||||||
|
"hikvision",
|
||||||
|
"hikvisioncam",
|
||||||
|
)
|
||||||
|
for domain in activated_components:
|
||||||
|
hass.config.components.add(domain)
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.homeassistant_alerts.__version__",
|
||||||
|
ha_version,
|
||||||
|
):
|
||||||
|
assert await async_setup_component(hass, DOMAIN, {})
|
||||||
|
|
||||||
|
client = await hass_ws_client(hass)
|
||||||
|
|
||||||
|
await client.send_json({"id": 1, "type": "repairs/list_issues"})
|
||||||
|
msg = await client.receive_json()
|
||||||
|
assert msg["success"]
|
||||||
|
assert msg["result"] == {
|
||||||
|
"issues": [
|
||||||
|
{
|
||||||
|
"breaks_in_ha_version": None,
|
||||||
|
"created": ANY,
|
||||||
|
"dismissed_version": None,
|
||||||
|
"domain": "homeassistant_alerts",
|
||||||
|
"ignored": False,
|
||||||
|
"is_fixable": False,
|
||||||
|
"issue_id": f"{alert}_{integration}",
|
||||||
|
"learn_more_url": f"https://alerts.home-assistant.io/#{alert}",
|
||||||
|
"severity": "warning",
|
||||||
|
"translation_key": "alert",
|
||||||
|
"translation_placeholders": {
|
||||||
|
"title": f"Title for {alert}",
|
||||||
|
"description": f"Content for {alert}",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for alert, integration in expected_alerts
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def test_no_alerts(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
hass_ws_client,
|
||||||
|
aioclient_mock: AiohttpClientMocker,
|
||||||
|
) -> None:
|
||||||
|
"""Test creating issues based on alerts."""
|
||||||
|
|
||||||
|
aioclient_mock.clear_requests()
|
||||||
|
aioclient_mock.get(
|
||||||
|
"https://alerts.home-assistant.io/alerts.json",
|
||||||
|
text="",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert await async_setup_component(hass, DOMAIN, {})
|
||||||
|
|
||||||
|
client = await hass_ws_client(hass)
|
||||||
|
|
||||||
|
await client.send_json({"id": 1, "type": "repairs/list_issues"})
|
||||||
|
msg = await client.receive_json()
|
||||||
|
assert msg["success"]
|
||||||
|
assert msg["result"] == {"issues": []}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"ha_version, fixture_1, expected_alerts_1, fixture_2, expected_alerts_2",
|
||||||
|
(
|
||||||
|
(
|
||||||
|
"2022.7.0",
|
||||||
|
"alerts_1.json",
|
||||||
|
[
|
||||||
|
("aladdin_connect.markdown", "aladdin_connect"),
|
||||||
|
("dark_sky.markdown", "darksky"),
|
||||||
|
("hikvision.markdown", "hikvision"),
|
||||||
|
("hikvision.markdown", "hikvisioncam"),
|
||||||
|
("hive_us.markdown", "hive"),
|
||||||
|
("homematicip_cloud.markdown", "homematicip_cloud"),
|
||||||
|
("logi_circle.markdown", "logi_circle"),
|
||||||
|
("neato.markdown", "neato"),
|
||||||
|
("nest.markdown", "nest"),
|
||||||
|
("senseme.markdown", "senseme"),
|
||||||
|
("sochain.markdown", "sochain"),
|
||||||
|
],
|
||||||
|
"alerts_2.json",
|
||||||
|
[
|
||||||
|
("dark_sky.markdown", "darksky"),
|
||||||
|
("hikvision.markdown", "hikvision"),
|
||||||
|
("hikvision.markdown", "hikvisioncam"),
|
||||||
|
("hive_us.markdown", "hive"),
|
||||||
|
("homematicip_cloud.markdown", "homematicip_cloud"),
|
||||||
|
("logi_circle.markdown", "logi_circle"),
|
||||||
|
("neato.markdown", "neato"),
|
||||||
|
("nest.markdown", "nest"),
|
||||||
|
("senseme.markdown", "senseme"),
|
||||||
|
("sochain.markdown", "sochain"),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"2022.7.0",
|
||||||
|
"alerts_2.json",
|
||||||
|
[
|
||||||
|
("dark_sky.markdown", "darksky"),
|
||||||
|
("hikvision.markdown", "hikvision"),
|
||||||
|
("hikvision.markdown", "hikvisioncam"),
|
||||||
|
("hive_us.markdown", "hive"),
|
||||||
|
("homematicip_cloud.markdown", "homematicip_cloud"),
|
||||||
|
("logi_circle.markdown", "logi_circle"),
|
||||||
|
("neato.markdown", "neato"),
|
||||||
|
("nest.markdown", "nest"),
|
||||||
|
("senseme.markdown", "senseme"),
|
||||||
|
("sochain.markdown", "sochain"),
|
||||||
|
],
|
||||||
|
"alerts_1.json",
|
||||||
|
[
|
||||||
|
("aladdin_connect.markdown", "aladdin_connect"),
|
||||||
|
("dark_sky.markdown", "darksky"),
|
||||||
|
("hikvision.markdown", "hikvision"),
|
||||||
|
("hikvision.markdown", "hikvisioncam"),
|
||||||
|
("hive_us.markdown", "hive"),
|
||||||
|
("homematicip_cloud.markdown", "homematicip_cloud"),
|
||||||
|
("logi_circle.markdown", "logi_circle"),
|
||||||
|
("neato.markdown", "neato"),
|
||||||
|
("nest.markdown", "nest"),
|
||||||
|
("senseme.markdown", "senseme"),
|
||||||
|
("sochain.markdown", "sochain"),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
async def test_alerts_change(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
hass_ws_client,
|
||||||
|
aioclient_mock: AiohttpClientMocker,
|
||||||
|
ha_version: str,
|
||||||
|
fixture_1: str,
|
||||||
|
expected_alerts_1: list[tuple(str, str)],
|
||||||
|
fixture_2: str,
|
||||||
|
expected_alerts_2: list[tuple(str, str)],
|
||||||
|
) -> None:
|
||||||
|
"""Test creating issues based on alerts."""
|
||||||
|
fixture_1_content = load_fixture(fixture_1, "homeassistant_alerts")
|
||||||
|
aioclient_mock.clear_requests()
|
||||||
|
aioclient_mock.get(
|
||||||
|
"https://alerts.home-assistant.io/alerts.json",
|
||||||
|
text=fixture_1_content,
|
||||||
|
)
|
||||||
|
for alert in json.loads(fixture_1_content):
|
||||||
|
stub_alert(aioclient_mock, alert["filename"])
|
||||||
|
|
||||||
|
activated_components = (
|
||||||
|
"aladdin_connect",
|
||||||
|
"darksky",
|
||||||
|
"hikvision",
|
||||||
|
"hikvisioncam",
|
||||||
|
"hive",
|
||||||
|
"homematicip_cloud",
|
||||||
|
"logi_circle",
|
||||||
|
"neato",
|
||||||
|
"nest",
|
||||||
|
"senseme",
|
||||||
|
"sochain",
|
||||||
|
)
|
||||||
|
for domain in activated_components:
|
||||||
|
hass.config.components.add(domain)
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.homeassistant_alerts.__version__",
|
||||||
|
ha_version,
|
||||||
|
):
|
||||||
|
assert await async_setup_component(hass, DOMAIN, {})
|
||||||
|
|
||||||
|
now = dt_util.utcnow()
|
||||||
|
|
||||||
|
client = await hass_ws_client(hass)
|
||||||
|
|
||||||
|
await client.send_json({"id": 1, "type": "repairs/list_issues"})
|
||||||
|
msg = await client.receive_json()
|
||||||
|
assert msg["success"]
|
||||||
|
assert_lists_same(
|
||||||
|
msg["result"]["issues"],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"breaks_in_ha_version": None,
|
||||||
|
"created": ANY,
|
||||||
|
"dismissed_version": None,
|
||||||
|
"domain": "homeassistant_alerts",
|
||||||
|
"ignored": False,
|
||||||
|
"is_fixable": False,
|
||||||
|
"issue_id": f"{alert}_{integration}",
|
||||||
|
"learn_more_url": f"https://alerts.home-assistant.io/#{alert}",
|
||||||
|
"severity": "warning",
|
||||||
|
"translation_key": "alert",
|
||||||
|
"translation_placeholders": {
|
||||||
|
"title": f"Title for {alert}",
|
||||||
|
"description": f"Content for {alert}",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for alert, integration in expected_alerts_1
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
fixture_2_content = load_fixture(fixture_2, "homeassistant_alerts")
|
||||||
|
aioclient_mock.clear_requests()
|
||||||
|
aioclient_mock.get(
|
||||||
|
"https://alerts.home-assistant.io/alerts.json",
|
||||||
|
text=fixture_2_content,
|
||||||
|
)
|
||||||
|
for alert in json.loads(fixture_2_content):
|
||||||
|
stub_alert(aioclient_mock, alert["filename"])
|
||||||
|
|
||||||
|
future = now + UPDATE_INTERVAL + timedelta(seconds=1)
|
||||||
|
async_fire_time_changed(hass, future)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
await client.send_json({"id": 2, "type": "repairs/list_issues"})
|
||||||
|
msg = await client.receive_json()
|
||||||
|
assert msg["success"]
|
||||||
|
assert_lists_same(
|
||||||
|
msg["result"]["issues"],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"breaks_in_ha_version": None,
|
||||||
|
"created": ANY,
|
||||||
|
"dismissed_version": None,
|
||||||
|
"domain": "homeassistant_alerts",
|
||||||
|
"ignored": False,
|
||||||
|
"is_fixable": False,
|
||||||
|
"issue_id": f"{alert}_{integration}",
|
||||||
|
"learn_more_url": f"https://alerts.home-assistant.io/#{alert}",
|
||||||
|
"severity": "warning",
|
||||||
|
"translation_key": "alert",
|
||||||
|
"translation_placeholders": {
|
||||||
|
"title": f"Title for {alert}",
|
||||||
|
"description": f"Content for {alert}",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for alert, integration in expected_alerts_2
|
||||||
|
],
|
||||||
|
)
|
Loading…
Add table
Add a link
Reference in a new issue