Add shared notify service migration repair helper (#117213)
* Add shared notifiy service migration repair helper * Delete ecobee repairs.py * Update dependency * Fix file test * Fix homematic tests * Improve tests for file and homematic
This commit is contained in:
parent
d1525b1edf
commit
7eb8f265fe
16 changed files with 133 additions and 89 deletions
|
@ -3,7 +3,6 @@
|
|||
"name": "ecobee",
|
||||
"codeowners": [],
|
||||
"config_flow": true,
|
||||
"dependencies": ["http", "repairs"],
|
||||
"documentation": "https://www.home-assistant.io/integrations/ecobee",
|
||||
"homekit": {
|
||||
"models": ["EB", "ecobee*"]
|
||||
|
|
|
@ -9,6 +9,7 @@ from homeassistant.components.notify import (
|
|||
ATTR_TARGET,
|
||||
BaseNotificationService,
|
||||
NotifyEntity,
|
||||
migrate_notify_issue,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
@ -18,7 +19,6 @@ from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
|||
from . import Ecobee, EcobeeData
|
||||
from .const import DOMAIN
|
||||
from .entity import EcobeeBaseEntity
|
||||
from .repairs import migrate_notify_issue
|
||||
|
||||
|
||||
def get_service(
|
||||
|
@ -43,7 +43,7 @@ class EcobeeNotificationService(BaseNotificationService):
|
|||
|
||||
async def async_send_message(self, message: str = "", **kwargs: Any) -> None:
|
||||
"""Send a message and raise issue."""
|
||||
migrate_notify_issue(self.hass)
|
||||
migrate_notify_issue(self.hass, DOMAIN, "Ecobee", "2024.11.0")
|
||||
await self.hass.async_add_executor_job(
|
||||
partial(self.send_message, message, **kwargs)
|
||||
)
|
||||
|
|
|
@ -163,18 +163,5 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"issues": {
|
||||
"migrate_notify": {
|
||||
"title": "Migration of Ecobee notify service",
|
||||
"fix_flow": {
|
||||
"step": {
|
||||
"confirm": {
|
||||
"description": "The Ecobee `notify` service has been migrated. A new `notify` entity per Thermostat is available now.\n\nUpdate any automations to use the new `notify.send_message` exposed by these new entities. When this is done, fix this issue and restart Home Assistant.",
|
||||
"title": "Disable legacy Ecobee notify service"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"after_dependencies": ["panel_custom"],
|
||||
"codeowners": ["@Julius2342", "@farmio", "@marvin-w"],
|
||||
"config_flow": true,
|
||||
"dependencies": ["file_upload", "repairs", "websocket_api"],
|
||||
"dependencies": ["file_upload", "websocket_api"],
|
||||
"documentation": "https://www.home-assistant.io/integrations/knx",
|
||||
"integration_type": "hub",
|
||||
"iot_class": "local_push",
|
||||
|
|
|
@ -8,7 +8,11 @@ from xknx import XKNX
|
|||
from xknx.devices import Notification as XknxNotification
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.components.notify import BaseNotificationService, NotifyEntity
|
||||
from homeassistant.components.notify import (
|
||||
BaseNotificationService,
|
||||
NotifyEntity,
|
||||
migrate_notify_issue,
|
||||
)
|
||||
from homeassistant.const import CONF_ENTITY_CATEGORY, CONF_NAME, CONF_TYPE, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
@ -16,7 +20,6 @@ from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
|||
|
||||
from .const import DATA_KNX_CONFIG, DOMAIN, KNX_ADDRESS
|
||||
from .knx_entity import KnxEntity
|
||||
from .repairs import migrate_notify_issue
|
||||
|
||||
|
||||
async def async_get_service(
|
||||
|
@ -57,7 +60,7 @@ class KNXNotificationService(BaseNotificationService):
|
|||
|
||||
async def async_send_message(self, message: str = "", **kwargs: Any) -> None:
|
||||
"""Send a notification to knx bus."""
|
||||
migrate_notify_issue(self.hass)
|
||||
migrate_notify_issue(self.hass, DOMAIN, "KNX", "2024.11.0")
|
||||
if "target" in kwargs:
|
||||
await self._async_send_to_device(message, kwargs["target"])
|
||||
else:
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
"""Repairs support for KNX."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from homeassistant.components.repairs import ConfirmRepairFlow, RepairsFlow
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers import issue_registry as ir
|
||||
|
||||
from .const import DOMAIN
|
||||
|
||||
|
||||
@callback
|
||||
def migrate_notify_issue(hass: HomeAssistant) -> None:
|
||||
"""Create issue for notify service deprecation."""
|
||||
ir.async_create_issue(
|
||||
hass,
|
||||
DOMAIN,
|
||||
"migrate_notify",
|
||||
breaks_in_ha_version="2024.11.0",
|
||||
issue_domain=Platform.NOTIFY.value,
|
||||
is_fixable=True,
|
||||
is_persistent=True,
|
||||
translation_key="migrate_notify",
|
||||
severity=ir.IssueSeverity.WARNING,
|
||||
)
|
||||
|
||||
|
||||
async def async_create_fix_flow(
|
||||
hass: HomeAssistant,
|
||||
issue_id: str,
|
||||
data: dict[str, str | int | float | None] | None,
|
||||
) -> RepairsFlow:
|
||||
"""Create flow."""
|
||||
assert issue_id == "migrate_notify"
|
||||
return ConfirmRepairFlow()
|
|
@ -384,18 +384,5 @@
|
|||
"name": "[%key:common::action::reload%]",
|
||||
"description": "Reloads the KNX integration."
|
||||
}
|
||||
},
|
||||
"issues": {
|
||||
"migrate_notify": {
|
||||
"title": "Migration of KNX notify service",
|
||||
"fix_flow": {
|
||||
"step": {
|
||||
"confirm": {
|
||||
"description": "The KNX `notify` service has been migrated. New `notify` entities are available now.\n\nUpdate any automations to use the new `notify.send_message` exposed by these new entities. When this is done, fix this issue and restart Home Assistant.",
|
||||
"title": "Disable legacy KNX notify service"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ from .legacy import ( # noqa: F401
|
|||
async_setup_legacy,
|
||||
check_templates_warn,
|
||||
)
|
||||
from .repairs import migrate_notify_issue # noqa: F401
|
||||
|
||||
# mypy: disallow-any-generics
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
"domain": "notify",
|
||||
"name": "Notifications",
|
||||
"codeowners": ["@home-assistant/core"],
|
||||
"dependencies": ["repairs"],
|
||||
"documentation": "https://www.home-assistant.io/integrations/notify",
|
||||
"integration_type": "entity",
|
||||
"quality_scale": "internal"
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
"""Repairs support for Ecobee."""
|
||||
"""Repairs support for notify integration."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from homeassistant.components.notify import DOMAIN as NOTIFY_DOMAIN
|
||||
from homeassistant.components.repairs import RepairsFlow
|
||||
from homeassistant.components.repairs.issue_handler import ConfirmRepairFlow
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
|
@ -12,17 +11,23 @@ from .const import DOMAIN
|
|||
|
||||
|
||||
@callback
|
||||
def migrate_notify_issue(hass: HomeAssistant) -> None:
|
||||
def migrate_notify_issue(
|
||||
hass: HomeAssistant, domain: str, integration_title: str, breaks_in_ha_version: str
|
||||
) -> None:
|
||||
"""Ensure an issue is registered."""
|
||||
ir.async_create_issue(
|
||||
hass,
|
||||
DOMAIN,
|
||||
"migrate_notify",
|
||||
breaks_in_ha_version="2024.11.0",
|
||||
issue_domain=NOTIFY_DOMAIN,
|
||||
f"migrate_notify_{domain}",
|
||||
breaks_in_ha_version=breaks_in_ha_version,
|
||||
issue_domain=domain,
|
||||
is_fixable=True,
|
||||
is_persistent=True,
|
||||
translation_key="migrate_notify",
|
||||
translation_placeholders={
|
||||
"domain": domain,
|
||||
"integration_title": integration_title,
|
||||
},
|
||||
severity=ir.IssueSeverity.WARNING,
|
||||
)
|
||||
|
||||
|
@ -33,5 +38,5 @@ async def async_create_fix_flow(
|
|||
data: dict[str, str | int | float | None] | None,
|
||||
) -> RepairsFlow:
|
||||
"""Create flow."""
|
||||
assert issue_id == "migrate_notify"
|
||||
assert issue_id.startswith("migrate_notify_")
|
||||
return ConfirmRepairFlow()
|
|
@ -60,5 +60,18 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"issues": {
|
||||
"migrate_notify": {
|
||||
"title": "Migration of {integration_title} notify service",
|
||||
"fix_flow": {
|
||||
"step": {
|
||||
"confirm": {
|
||||
"description": "The {integration_title} `notify` service(s) are migrated. A new `notify` entity is available now to replace each legacy `notify` service.\n\nUpdate any automations to use the new `notify.send_message` service exposed with this new entity. When this is done, fix this issue and restart Home Assistant.",
|
||||
"title": "Migrate legacy {integration_title} notify service for domain `{domain}`"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,14 +48,14 @@ async def test_ecobee_repair_flow(
|
|||
|
||||
# Assert the issue is present
|
||||
assert issue_registry.async_get_issue(
|
||||
domain=DOMAIN,
|
||||
issue_id="migrate_notify",
|
||||
domain="notify",
|
||||
issue_id=f"migrate_notify_{DOMAIN}",
|
||||
)
|
||||
assert len(issue_registry.issues) == 1
|
||||
|
||||
url = RepairsFlowIndexView.url
|
||||
resp = await http_client.post(
|
||||
url, json={"handler": DOMAIN, "issue_id": "migrate_notify"}
|
||||
url, json={"handler": "notify", "issue_id": f"migrate_notify_{DOMAIN}"}
|
||||
)
|
||||
assert resp.status == HTTPStatus.OK
|
||||
data = await resp.json()
|
||||
|
@ -73,7 +73,7 @@ async def test_ecobee_repair_flow(
|
|||
|
||||
# Assert the issue is no longer present
|
||||
assert not issue_registry.async_get_issue(
|
||||
domain=DOMAIN,
|
||||
domain="notify",
|
||||
issue_id="migrate_notify",
|
||||
)
|
||||
assert len(issue_registry.issues) == 0
|
||||
|
|
|
@ -22,7 +22,7 @@ from tests.common import MockConfigEntry, assert_setup_component
|
|||
async def test_bad_config(hass: HomeAssistant) -> None:
|
||||
"""Test set up the platform with bad/missing config."""
|
||||
config = {notify.DOMAIN: {"name": "test", "platform": "file"}}
|
||||
with assert_setup_component(0) as handle_config:
|
||||
with assert_setup_component(0, domain="notify") as handle_config:
|
||||
assert await async_setup_component(hass, notify.DOMAIN, config)
|
||||
await hass.async_block_till_done()
|
||||
assert not handle_config[notify.DOMAIN]
|
||||
|
|
|
@ -14,7 +14,7 @@ async def test_setup_full(hass: HomeAssistant) -> None:
|
|||
"homematic",
|
||||
{"homematic": {"hosts": {"ccu2": {"host": "127.0.0.1"}}}},
|
||||
)
|
||||
with assert_setup_component(1) as handle_config:
|
||||
with assert_setup_component(1, domain="notify") as handle_config:
|
||||
assert await async_setup_component(
|
||||
hass,
|
||||
"notify",
|
||||
|
@ -40,7 +40,7 @@ async def test_setup_without_optional(hass: HomeAssistant) -> None:
|
|||
"homematic",
|
||||
{"homematic": {"hosts": {"ccu2": {"host": "127.0.0.1"}}}},
|
||||
)
|
||||
with assert_setup_component(1) as handle_config:
|
||||
with assert_setup_component(1, domain="notify") as handle_config:
|
||||
assert await async_setup_component(
|
||||
hass,
|
||||
"notify",
|
||||
|
@ -61,6 +61,6 @@ async def test_setup_without_optional(hass: HomeAssistant) -> None:
|
|||
async def test_bad_config(hass: HomeAssistant) -> None:
|
||||
"""Test invalid configuration."""
|
||||
config = {notify_comp.DOMAIN: {"name": "test", "platform": "homematic"}}
|
||||
with assert_setup_component(0) as handle_config:
|
||||
with assert_setup_component(0, domain="notify") as handle_config:
|
||||
assert await async_setup_component(hass, notify_comp.DOMAIN, config)
|
||||
assert not handle_config[notify_comp.DOMAIN]
|
||||
|
|
|
@ -54,14 +54,14 @@ async def test_knx_notify_service_issue(
|
|||
# Assert the issue is present
|
||||
assert len(issue_registry.issues) == 1
|
||||
assert issue_registry.async_get_issue(
|
||||
domain=DOMAIN,
|
||||
issue_id="migrate_notify",
|
||||
domain="notify",
|
||||
issue_id=f"migrate_notify_{DOMAIN}",
|
||||
)
|
||||
|
||||
# Test confirm step in repair flow
|
||||
resp = await http_client.post(
|
||||
RepairsFlowIndexView.url,
|
||||
json={"handler": DOMAIN, "issue_id": "migrate_notify"},
|
||||
json={"handler": "notify", "issue_id": f"migrate_notify_{DOMAIN}"},
|
||||
)
|
||||
assert resp.status == HTTPStatus.OK
|
||||
data = await resp.json()
|
||||
|
@ -78,7 +78,7 @@ async def test_knx_notify_service_issue(
|
|||
|
||||
# Assert the issue is no longer present
|
||||
assert not issue_registry.async_get_issue(
|
||||
domain=DOMAIN,
|
||||
issue_id="migrate_notify",
|
||||
domain="notify",
|
||||
issue_id=f"migrate_notify_{DOMAIN}",
|
||||
)
|
||||
assert len(issue_registry.issues) == 0
|
||||
|
|
84
tests/components/notify/test_repairs.py
Normal file
84
tests/components/notify/test_repairs.py
Normal file
|
@ -0,0 +1,84 @@
|
|||
"""Test repairs for notify entity component."""
|
||||
|
||||
from http import HTTPStatus
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
from homeassistant.components.notify import (
|
||||
DOMAIN as NOTIFY_DOMAIN,
|
||||
migrate_notify_issue,
|
||||
)
|
||||
from homeassistant.components.repairs.issue_handler import (
|
||||
async_process_repairs_platforms,
|
||||
)
|
||||
from homeassistant.components.repairs.websocket_api import (
|
||||
RepairsFlowIndexView,
|
||||
RepairsFlowResourceView,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import issue_registry as ir
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from tests.common import MockConfigEntry, MockModule, mock_integration
|
||||
from tests.typing import ClientSessionGenerator
|
||||
|
||||
THERMOSTAT_ID = 0
|
||||
|
||||
|
||||
async def test_notify_migration_repair_flow(
|
||||
hass: HomeAssistant,
|
||||
hass_client: ClientSessionGenerator,
|
||||
issue_registry: ir.IssueRegistry,
|
||||
config_flow_fixture: None,
|
||||
) -> None:
|
||||
"""Test the notify service repair flow is triggered."""
|
||||
await async_setup_component(hass, NOTIFY_DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
await async_process_repairs_platforms(hass)
|
||||
|
||||
http_client = await hass_client()
|
||||
await hass.async_block_till_done()
|
||||
config_entry = MockConfigEntry(domain="test")
|
||||
config_entry.add_to_hass(hass)
|
||||
mock_integration(
|
||||
hass,
|
||||
MockModule(
|
||||
"test",
|
||||
async_setup_entry=AsyncMock(return_value=True),
|
||||
),
|
||||
)
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
|
||||
# Simulate legacy service being used and issue being registered
|
||||
migrate_notify_issue(hass, "test", "Test", "2024.12.0")
|
||||
await hass.async_block_till_done()
|
||||
# Assert the issue is present
|
||||
assert issue_registry.async_get_issue(
|
||||
domain=NOTIFY_DOMAIN,
|
||||
issue_id="migrate_notify_test",
|
||||
)
|
||||
assert len(issue_registry.issues) == 1
|
||||
|
||||
url = RepairsFlowIndexView.url
|
||||
resp = await http_client.post(
|
||||
url, json={"handler": NOTIFY_DOMAIN, "issue_id": "migrate_notify_test"}
|
||||
)
|
||||
assert resp.status == HTTPStatus.OK
|
||||
data = await resp.json()
|
||||
|
||||
flow_id = data["flow_id"]
|
||||
assert data["step_id"] == "confirm"
|
||||
|
||||
url = RepairsFlowResourceView.url.format(flow_id=flow_id)
|
||||
resp = await http_client.post(url)
|
||||
assert resp.status == HTTPStatus.OK
|
||||
data = await resp.json()
|
||||
assert data["type"] == "create_entry"
|
||||
# Test confirm step in repair flow
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Assert the issue is no longer present
|
||||
assert not issue_registry.async_get_issue(
|
||||
domain=NOTIFY_DOMAIN,
|
||||
issue_id="migrate_notify_test",
|
||||
)
|
||||
assert len(issue_registry.issues) == 0
|
Loading…
Add table
Reference in a new issue