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, ConfigEntryNotReady,
HomeAssistantError, HomeAssistantError,
) )
from homeassistant.helpers import device_registry as dr
from .activity import ActivityStream from .activity import ActivityStream
from .const import DOMAIN, MIN_TIME_BETWEEN_DETAIL_UPDATES, PLATFORMS from .const import DOMAIN, MIN_TIME_BETWEEN_DETAIL_UPDATES, PLATFORMS
@ -283,12 +284,15 @@ class AugustData(AugustSubscriberMixin):
device.device_id, 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.""" """Return doorbell or lock name as August has it stored."""
if device_id in self._locks_by_id: if device := self.get_device(device_id):
return self._locks_by_id[device_id].device_name return device.device_name
if device_id in self._doorbells_by_id: return None
return self._doorbells_by_id[device_id].device_name
async def async_lock(self, device_id): async def async_lock(self, device_id):
"""Lock the device.""" """Lock the device."""
@ -403,3 +407,15 @@ def _restore_live_attrs(lock_detail, attrs):
"""Restore the non-cache attributes after a cached update.""" """Restore the non-cache attributes after a cached update."""
for attr, value in attrs.items(): for attr, value in attrs.items():
setattr(lock_detail, attr, value) 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.""" """Mocks for the august component."""
from __future__ import annotations
import json import json
import os import os
import time import time
from typing import Any, Iterable
from unittest.mock import AsyncMock, MagicMock, PropertyMock, patch from unittest.mock import AsyncMock, MagicMock, PropertyMock, patch
from yalexs.activity import ( from yalexs.activity import (
@ -26,7 +29,9 @@ from yalexs.lock import Lock, LockDetail
from yalexs.pubnub_async import AugustPubNub from yalexs.pubnub_async import AugustPubNub
from homeassistant.components.august.const import CONF_LOGIN_METHOD, DOMAIN 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.const import CONF_PASSWORD, CONF_USERNAME
from homeassistant.core import HomeAssistant
from tests.common import MockConfigEntry, load_fixture from tests.common import MockConfigEntry, load_fixture
@ -76,9 +81,13 @@ async def _mock_setup_august(
async def _create_august_with_devices( async def _create_august_with_devices(
hass, devices, api_call_side_effects=None, activities=None, pubnub=None hass: HomeAssistant,
): devices: Iterable[LockDetail | DoorbellDetail],
entry, api_instance = await _create_august_api_with_devices( 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 hass, devices, api_call_side_effects, activities, pubnub
) )
return entry return entry

View File

@ -17,6 +17,9 @@ from homeassistant.const import (
STATE_ON, STATE_ON,
) )
from homeassistant.exceptions import HomeAssistantError 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.common import MockConfigEntry
from tests.components.august.mocks import ( 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.config_entries.async_unload(config_entry.entry_id)
await hass.async_block_till_done() 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
)