Add support for async_remove_config_entry_device to august (#72627)

This commit is contained in:
J. Nick Koston 2022-06-09 21:53:42 -10:00 committed by GitHub
parent f4d339119f
commit 06ebc1fa14
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 79 additions and 8 deletions

View file

@ -21,6 +21,7 @@ from homeassistant.exceptions import (
ConfigEntryNotReady,
HomeAssistantError,
)
from homeassistant.helpers import device_registry as dr
from .activity import ActivityStream
from .const import DOMAIN, MIN_TIME_BETWEEN_DETAIL_UPDATES, PLATFORMS
@ -283,12 +284,15 @@ class AugustData(AugustSubscriberMixin):
device.device_id,
)
def _get_device_name(self, device_id):
def get_device(self, device_id: str) -> Doorbell | Lock | None:
"""Get a device by id."""
return self._locks_by_id.get(device_id) or self._doorbells_by_id.get(device_id)
def _get_device_name(self, device_id: str) -> str | None:
"""Return doorbell or lock name as August has it stored."""
if device_id in self._locks_by_id:
return self._locks_by_id[device_id].device_name
if device_id in self._doorbells_by_id:
return self._doorbells_by_id[device_id].device_name
if device := self.get_device(device_id):
return device.device_name
return None
async def async_lock(self, device_id):
"""Lock the device."""
@ -403,3 +407,15 @@ def _restore_live_attrs(lock_detail, attrs):
"""Restore the non-cache attributes after a cached update."""
for attr, value in attrs.items():
setattr(lock_detail, attr, value)
async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: ConfigEntry, device_entry: dr.DeviceEntry
) -> bool:
"""Remove august config entry from a device if its no longer present."""
data: AugustData = hass.data[DOMAIN][config_entry.entry_id]
return not any(
identifier
for identifier in device_entry.identifiers
if identifier[0] == DOMAIN and data.get_device(identifier[1])
)

View file

@ -1,7 +1,10 @@
"""Mocks for the august component."""
from __future__ import annotations
import json
import os
import time
from typing import Any, Iterable
from unittest.mock import AsyncMock, MagicMock, PropertyMock, patch
from yalexs.activity import (
@ -26,7 +29,9 @@ from yalexs.lock import Lock, LockDetail
from yalexs.pubnub_async import AugustPubNub
from homeassistant.components.august.const import CONF_LOGIN_METHOD, DOMAIN
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
from homeassistant.core import HomeAssistant
from tests.common import MockConfigEntry, load_fixture
@ -76,9 +81,13 @@ async def _mock_setup_august(
async def _create_august_with_devices(
hass, devices, api_call_side_effects=None, activities=None, pubnub=None
):
entry, api_instance = await _create_august_api_with_devices(
hass: HomeAssistant,
devices: Iterable[LockDetail | DoorbellDetail],
api_call_side_effects: dict[str, Any] | None = None,
activities: list[Any] | None = None,
pubnub: AugustPubNub | None = None,
) -> ConfigEntry:
entry, _ = await _create_august_api_with_devices(
hass, devices, api_call_side_effects, activities, pubnub
)
return entry

View file

@ -17,6 +17,9 @@ from homeassistant.const import (
STATE_ON,
)
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.helpers.entity_registry import EntityRegistry
from homeassistant.setup import async_setup_component
from tests.common import MockConfigEntry
from tests.components.august.mocks import (
@ -318,3 +321,46 @@ async def test_load_unload(hass):
await hass.config_entries.async_unload(config_entry.entry_id)
await hass.async_block_till_done()
async def remove_device(ws_client, device_id, config_entry_id):
"""Remove config entry from a device."""
await ws_client.send_json(
{
"id": 5,
"type": "config/device_registry/remove_config_entry",
"config_entry_id": config_entry_id,
"device_id": device_id,
}
)
response = await ws_client.receive_json()
return response["success"]
async def test_device_remove_devices(hass, hass_ws_client):
"""Test we can only remove a device that no longer exists."""
assert await async_setup_component(hass, "config", {})
august_operative_lock = await _mock_operative_august_lock_detail(hass)
config_entry = await _create_august_with_devices(hass, [august_operative_lock])
registry: EntityRegistry = er.async_get(hass)
entity = registry.entities["lock.a6697750d607098bae8d6baa11ef8063_name"]
device_registry = dr.async_get(hass)
device_entry = device_registry.async_get(entity.device_id)
assert (
await remove_device(
await hass_ws_client(hass), device_entry.id, config_entry.entry_id
)
is False
)
dead_device_entry = device_registry.async_get_or_create(
config_entry_id=config_entry.entry_id,
identifiers={(DOMAIN, "remove-device-id")},
)
assert (
await remove_device(
await hass_ws_client(hass), dead_device_entry.id, config_entry.entry_id
)
is True
)