Add issue asking users to disable VoIP call_in_progress binary sensor (#126504)
* Add issue asking users to disable VoIP call_in_progress binary sensor * Add tests * Add files * Update homeassistant/components/voip/binary_sensor.py Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com> * Fix test --------- Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
parent
58eccc1ed6
commit
c96d4991b9
6 changed files with 201 additions and 3 deletions
|
@ -24,11 +24,11 @@
|
|||
},
|
||||
"issues": {
|
||||
"assist_in_progress_deprecated": {
|
||||
"title": "{integration_name} assist in progress binary sensors are deprecated",
|
||||
"title": "{integration_name} in progress binary sensors are deprecated",
|
||||
"fix_flow": {
|
||||
"step": {
|
||||
"confirm_disable_entity": {
|
||||
"description": "The {integration_name} assist in progress binary sensor `{entity_id}` is deprecated.\n\nMigrate your configuration to use the corresponding `{assist_satellite_domain}` entity and then click SUBMIT to disable the assist in progress binary sensor and fix this issue."
|
||||
"description": "The {integration_name} in progress binary sensor `{entity_id}` is deprecated.\n\nMigrate your configuration to use the corresponding `{assist_satellite_domain}` entity and then click SUBMIT to disable the in progress binary sensor and fix this issue."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ from homeassistant.components.binary_sensor import (
|
|||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers import issue_registry as ir
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import DOMAIN
|
||||
|
@ -56,6 +57,38 @@ class VoIPCallInProgress(VoIPEntity, BinarySensorEntity):
|
|||
self.voip_device.async_listen_update(self._is_active_changed)
|
||||
)
|
||||
|
||||
await super().async_added_to_hass()
|
||||
if TYPE_CHECKING:
|
||||
assert self.registry_entry is not None
|
||||
ir.async_create_issue(
|
||||
self.hass,
|
||||
DOMAIN,
|
||||
f"assist_in_progress_deprecated_{self.registry_entry.id}",
|
||||
breaks_in_ha_version="2025.4",
|
||||
data={
|
||||
"entity_id": self.entity_id,
|
||||
"entity_uuid": self.registry_entry.id,
|
||||
"integration_name": "VoIP",
|
||||
},
|
||||
is_fixable=True,
|
||||
severity=ir.IssueSeverity.WARNING,
|
||||
translation_key="assist_in_progress_deprecated",
|
||||
translation_placeholders={
|
||||
"integration_name": "VoIP",
|
||||
},
|
||||
)
|
||||
|
||||
async def async_will_remove_from_hass(self) -> None:
|
||||
"""Remove issue."""
|
||||
await super().async_will_remove_from_hass()
|
||||
if TYPE_CHECKING:
|
||||
assert self.registry_entry is not None
|
||||
ir.async_delete_issue(
|
||||
self.hass,
|
||||
DOMAIN,
|
||||
f"assist_in_progress_deprecated_{self.registry_entry.id}",
|
||||
)
|
||||
|
||||
@callback
|
||||
def _is_active_changed(self, device: VoIPDevice) -> None:
|
||||
"""Call when active state changed."""
|
||||
|
|
22
homeassistant/components/voip/repairs.py
Normal file
22
homeassistant/components/voip/repairs.py
Normal file
|
@ -0,0 +1,22 @@
|
|||
"""Repairs implementation for the VoIP integration."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from homeassistant.components.assist_pipeline.repair_flows import (
|
||||
AssistInProgressDeprecatedRepairFlow,
|
||||
)
|
||||
from homeassistant.components.repairs import RepairsFlow
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
|
||||
async def async_create_fix_flow(
|
||||
hass: HomeAssistant,
|
||||
issue_id: str,
|
||||
data: dict[str, str | int | float | None] | None,
|
||||
) -> RepairsFlow:
|
||||
"""Create flow."""
|
||||
if issue_id.startswith("assist_in_progress_deprecated"):
|
||||
return AssistInProgressDeprecatedRepairFlow(data)
|
||||
# If VoIP adds confirm-only repairs in the future, this should be changed
|
||||
# to return a ConfirmRepairFlow instead of raising a ValueError
|
||||
raise ValueError(f"unknown repair {issue_id}")
|
|
@ -47,6 +47,18 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"issues": {
|
||||
"assist_in_progress_deprecated": {
|
||||
"title": "[%key:component::assist_pipeline::issues::assist_in_progress_deprecated::title%]",
|
||||
"fix_flow": {
|
||||
"step": {
|
||||
"confirm_disable_entity": {
|
||||
"description": "[%key:component::assist_pipeline::issues::assist_in_progress_deprecated::fix_flow::step::confirm_disable_entity::description%]"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
|
|
|
@ -1,11 +1,18 @@
|
|||
"""Test VoIP binary sensor devices."""
|
||||
|
||||
from http import HTTPStatus
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.repairs import DOMAIN as REPAIRS_DOMAIN
|
||||
from homeassistant.components.voip import DOMAIN
|
||||
from homeassistant.components.voip.devices import VoIPDevice
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.helpers import entity_registry as er, issue_registry as ir
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from tests.typing import ClientSessionGenerator
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
|
@ -45,3 +52,114 @@ async def test_assist_in_progress_disabled_by_default(
|
|||
assert entity_entry
|
||||
assert entity_entry.disabled
|
||||
assert entity_entry.disabled_by is er.RegistryEntryDisabler.INTEGRATION
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
async def test_assist_in_progress_issue(
|
||||
hass: HomeAssistant,
|
||||
entity_registry: er.EntityRegistry,
|
||||
issue_registry: ir.IssueRegistry,
|
||||
voip_device: VoIPDevice,
|
||||
) -> None:
|
||||
"""Test assist in progress binary sensor."""
|
||||
|
||||
call_in_progress_entity_id = "binary_sensor.192_168_1_210_call_in_progress"
|
||||
|
||||
state = hass.states.get(call_in_progress_entity_id)
|
||||
assert state is not None
|
||||
|
||||
entity_entry = entity_registry.async_get(call_in_progress_entity_id)
|
||||
issue = issue_registry.async_get_issue(
|
||||
DOMAIN, f"assist_in_progress_deprecated_{entity_entry.id}"
|
||||
)
|
||||
assert issue is not None
|
||||
|
||||
# Test issue goes away after disabling the entity
|
||||
entity_registry.async_update_entity(
|
||||
call_in_progress_entity_id,
|
||||
disabled_by=er.RegistryEntryDisabler.USER,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
issue = issue_registry.async_get_issue(
|
||||
DOMAIN, f"assist_in_progress_deprecated_{entity_entry.id}"
|
||||
)
|
||||
assert issue is None
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
async def test_assist_in_progress_repair_flow(
|
||||
hass: HomeAssistant,
|
||||
hass_client: ClientSessionGenerator,
|
||||
entity_registry: er.EntityRegistry,
|
||||
issue_registry: ir.IssueRegistry,
|
||||
voip_device: VoIPDevice,
|
||||
) -> None:
|
||||
"""Test assist in progress binary sensor deprecation issue flow."""
|
||||
|
||||
call_in_progress_entity_id = "binary_sensor.192_168_1_210_call_in_progress"
|
||||
|
||||
state = hass.states.get(call_in_progress_entity_id)
|
||||
assert state is not None
|
||||
|
||||
entity_entry = entity_registry.async_get(call_in_progress_entity_id)
|
||||
assert entity_entry.disabled_by is None
|
||||
issue = issue_registry.async_get_issue(
|
||||
DOMAIN, f"assist_in_progress_deprecated_{entity_entry.id}"
|
||||
)
|
||||
assert issue is not None
|
||||
assert issue.data == {
|
||||
"entity_id": call_in_progress_entity_id,
|
||||
"entity_uuid": entity_entry.id,
|
||||
"integration_name": "VoIP",
|
||||
}
|
||||
assert issue.translation_key == "assist_in_progress_deprecated"
|
||||
assert issue.translation_placeholders == {"integration_name": "VoIP"}
|
||||
|
||||
assert await async_setup_component(hass, REPAIRS_DOMAIN, {REPAIRS_DOMAIN: {}})
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_start()
|
||||
|
||||
client = await hass_client()
|
||||
|
||||
resp = await client.post(
|
||||
"/api/repairs/issues/fix",
|
||||
json={"handler": DOMAIN, "issue_id": issue.issue_id},
|
||||
)
|
||||
|
||||
assert resp.status == HTTPStatus.OK
|
||||
data = await resp.json()
|
||||
|
||||
flow_id = data["flow_id"]
|
||||
assert data == {
|
||||
"data_schema": [],
|
||||
"description_placeholders": {
|
||||
"assist_satellite_domain": "assist_satellite",
|
||||
"entity_id": call_in_progress_entity_id,
|
||||
"integration_name": "VoIP",
|
||||
},
|
||||
"errors": None,
|
||||
"flow_id": flow_id,
|
||||
"handler": DOMAIN,
|
||||
"last_step": None,
|
||||
"preview": None,
|
||||
"step_id": "confirm_disable_entity",
|
||||
"type": "form",
|
||||
}
|
||||
|
||||
resp = await client.post(f"/api/repairs/issues/fix/{flow_id}")
|
||||
|
||||
assert resp.status == HTTPStatus.OK
|
||||
data = await resp.json()
|
||||
|
||||
flow_id = data["flow_id"]
|
||||
assert data == {
|
||||
"description": None,
|
||||
"description_placeholders": None,
|
||||
"flow_id": flow_id,
|
||||
"handler": DOMAIN,
|
||||
"type": "create_entry",
|
||||
}
|
||||
|
||||
# Test the entity is disabled
|
||||
entity_entry = entity_registry.async_get(call_in_progress_entity_id)
|
||||
assert entity_entry.disabled_by is er.RegistryEntryDisabler.USER
|
||||
|
|
13
tests/components/voip/test_repairs.py
Normal file
13
tests/components/voip/test_repairs.py
Normal file
|
@ -0,0 +1,13 @@
|
|||
"""Test VoIP repairs."""
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.voip import repairs
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
|
||||
async def test_create_fix_flow_raises_on_unknown_issue_id(hass: HomeAssistant) -> None:
|
||||
"""Test reate_fix_flow raises on unknown issue_id."""
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
await repairs.async_create_fix_flow(hass, "no_such_issue", None)
|
Loading…
Add table
Reference in a new issue