Cleanups in device registry tests (#110786)

This commit is contained in:
Franck Nijhof 2024-02-17 14:06:53 +01:00 committed by GitHub
parent 42cf081582
commit 0fbadc274a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 212 additions and 183 deletions

View file

@ -7,7 +7,7 @@ from homeassistant.helpers import device_registry as dr
from homeassistant.setup import async_setup_component
from tests.common import MockConfigEntry, MockModule, mock_integration
from tests.typing import WebSocketGenerator
from tests.typing import MockHAClientWebSocket, WebSocketGenerator
@pytest.fixture(autouse=True, name="stub_blueprint_populate")
@ -15,15 +15,19 @@ def stub_blueprint_populate_autouse(stub_blueprint_populate: None) -> None:
"""Stub copying the blueprints to the config folder."""
@pytest.fixture
async def client(hass, hass_ws_client):
@pytest.fixture(name="client")
async def client_fixture(
hass: HomeAssistant, hass_ws_client: WebSocketGenerator
) -> MockHAClientWebSocket:
"""Fixture that can interact with the config manager API."""
device_registry.async_setup(hass)
return await hass_ws_client(hass)
async def test_list_devices(
hass: HomeAssistant, client, device_registry: dr.DeviceRegistry
hass: HomeAssistant,
client: MockHAClientWebSocket,
device_registry: dr.DeviceRegistry,
) -> None:
"""Test list entries."""
entry = MockConfigEntry(title=None)
@ -44,10 +48,10 @@ async def test_list_devices(
entry_type=dr.DeviceEntryType.SERVICE,
)
await client.send_json({"id": 5, "type": "config/device_registry/list"})
await client.send_json_auto_id({"type": "config/device_registry/list"})
msg = await client.receive_json()
dev1, dev2 = (entry.pop("id") for entry in msg["result"])
dev1, _ = (entry.pop("id") for entry in msg["result"])
assert msg["result"] == [
{
@ -92,7 +96,7 @@ async def test_list_devices(
device_registry.async_update_device(device2.id, name=Unserializable())
await hass.async_block_till_done()
await client.send_json({"id": 6, "type": "config/device_registry/list"})
await client.send_json_auto_id({"type": "config/device_registry/list"})
msg = await client.receive_json()
assert msg["result"] == [
@ -134,10 +138,10 @@ async def test_list_devices(
)
async def test_update_device(
hass: HomeAssistant,
client,
client: MockHAClientWebSocket,
device_registry: dr.DeviceRegistry,
payload_key,
payload_value,
payload_key: str,
payload_value: str | None | dr.DeviceEntryDisabler,
) -> None:
"""Test update entry."""
entry = MockConfigEntry(title=None)
@ -152,9 +156,8 @@ async def test_update_device(
assert not getattr(device, payload_key)
await client.send_json(
await client.send_json_auto_id(
{
"id": 1,
"type": "config/device_registry/update",
"device_id": device.id,
payload_key: payload_value,
@ -231,9 +234,8 @@ async def test_remove_config_entry_from_device(
# Try removing a config entry from the device, it should fail because
# async_remove_config_entry_device returns False
await ws_client.send_json(
await ws_client.send_json_auto_id(
{
"id": 5,
"type": "config/device_registry/remove_config_entry",
"config_entry_id": entry_1.entry_id,
"device_id": device_entry.id,
@ -248,9 +250,8 @@ async def test_remove_config_entry_from_device(
can_remove = True
# Remove the 1st config entry
await ws_client.send_json(
await ws_client.send_json_auto_id(
{
"id": 6,
"type": "config/device_registry/remove_config_entry",
"config_entry_id": entry_1.entry_id,
"device_id": device_entry.id,
@ -267,9 +268,8 @@ async def test_remove_config_entry_from_device(
}
# Remove the 2nd config entry
await ws_client.send_json(
await ws_client.send_json_auto_id(
{
"id": 7,
"type": "config/device_registry/remove_config_entry",
"config_entry_id": entry_2.entry_id,
"device_id": device_entry.id,
@ -354,9 +354,8 @@ async def test_remove_config_entry_from_device_fails(
assert device_entry.id != fake_device_id
# Try removing a non existing config entry from the device
await ws_client.send_json(
await ws_client.send_json_auto_id(
{
"id": 5,
"type": "config/device_registry/remove_config_entry",
"config_entry_id": fake_entry_id,
"device_id": device_entry.id,
@ -369,9 +368,8 @@ async def test_remove_config_entry_from_device_fails(
assert response["error"]["message"] == "Unknown config entry"
# Try removing a config entry which does not support removal from the device
await ws_client.send_json(
await ws_client.send_json_auto_id(
{
"id": 6,
"type": "config/device_registry/remove_config_entry",
"config_entry_id": entry_1.entry_id,
"device_id": device_entry.id,
@ -386,9 +384,8 @@ async def test_remove_config_entry_from_device_fails(
)
# Try removing a config entry from a device which does not exist
await ws_client.send_json(
await ws_client.send_json_auto_id(
{
"id": 7,
"type": "config/device_registry/remove_config_entry",
"config_entry_id": entry_2.entry_id,
"device_id": fake_device_id,
@ -401,9 +398,8 @@ async def test_remove_config_entry_from_device_fails(
assert response["error"]["message"] == "Unknown device"
# Try removing a config entry from a device which it's not connected to
await ws_client.send_json(
await ws_client.send_json_auto_id(
{
"id": 8,
"type": "config/device_registry/remove_config_entry",
"config_entry_id": entry_2.entry_id,
"device_id": device_entry.id,
@ -417,9 +413,8 @@ async def test_remove_config_entry_from_device_fails(
entry_3.entry_id,
}
await ws_client.send_json(
await ws_client.send_json_auto_id(
{
"id": 9,
"type": "config/device_registry/remove_config_entry",
"config_entry_id": entry_2.entry_id,
"device_id": device_entry.id,
@ -432,9 +427,8 @@ async def test_remove_config_entry_from_device_fails(
assert response["error"]["message"] == "Config entry not in device"
# Try removing a config entry which can't be loaded from a device - allowed
await ws_client.send_json(
await ws_client.send_json_auto_id(
{
"id": 10,
"type": "config/device_registry/remove_config_entry",
"config_entry_id": entry_3.entry_id,
"device_id": device_entry.id,

View file

@ -9,7 +9,7 @@ from yarl import URL
from homeassistant import config_entries
from homeassistant.const import EVENT_HOMEASSISTANT_STARTED
from homeassistant.core import CoreState, HomeAssistant, callback
from homeassistant.core import CoreState, HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import (
area_registry as ar,
@ -19,26 +19,13 @@ from homeassistant.helpers import (
from tests.common import (
MockConfigEntry,
async_capture_events,
flush_store,
help_test_all,
import_and_test_deprecated_constant_enum,
)
@pytest.fixture
def update_events(hass):
"""Capture update events."""
events = []
@callback
def async_capture(event):
events.append(event.data)
hass.bus.async_listen(dr.EVENT_DEVICE_REGISTRY_UPDATED, async_capture)
return events
@pytest.fixture
def mock_config_entry(hass: HomeAssistant) -> MockConfigEntry:
"""Create a mock config entry and add it to hass."""
@ -52,9 +39,9 @@ async def test_get_or_create_returns_same_entry(
device_registry: dr.DeviceRegistry,
area_registry: ar.AreaRegistry,
mock_config_entry: MockConfigEntry,
update_events,
) -> None:
"""Make sure we do not duplicate entries."""
update_events = async_capture_events(hass, dr.EVENT_DEVICE_REGISTRY_UPDATED)
entry = device_registry.async_get_or_create(
config_entry_id=mock_config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
@ -101,13 +88,14 @@ async def test_get_or_create_returns_same_entry(
# Only 2 update events. The third entry did not generate any changes.
assert len(update_events) == 2
assert update_events[0]["action"] == "create"
assert update_events[0]["device_id"] == entry.id
assert "changes" not in update_events[0]
assert update_events[1]["action"] == "update"
assert update_events[1]["device_id"] == entry.id
assert update_events[1]["changes"] == {
"connections": {("mac", "12:34:56:ab:cd:ef")}
assert update_events[0].data == {
"action": "create",
"device_id": entry.id,
}
assert update_events[1].data == {
"action": "update",
"device_id": entry.id,
"changes": {"connections": {("mac", "12:34:56:ab:cd:ef")}},
}
@ -656,9 +644,10 @@ async def test_migration_1_3_to_1_4(
async def test_removing_config_entries(
hass: HomeAssistant, device_registry: dr.DeviceRegistry, update_events
hass: HomeAssistant, device_registry: dr.DeviceRegistry
) -> None:
"""Make sure we do not get duplicate entries."""
update_events = async_capture_events(hass, dr.EVENT_DEVICE_REGISTRY_UPDATED)
config_entry_1 = MockConfigEntry()
config_entry_1.add_to_hass(hass)
config_entry_2 = MockConfigEntry()
@ -703,29 +692,37 @@ async def test_removing_config_entries(
await hass.async_block_till_done()
assert len(update_events) == 5
assert update_events[0]["action"] == "create"
assert update_events[0]["device_id"] == entry.id
assert "changes" not in update_events[0]
assert update_events[1]["action"] == "update"
assert update_events[1]["device_id"] == entry2.id
assert update_events[1]["changes"] == {"config_entries": {config_entry_1.entry_id}}
assert update_events[2]["action"] == "create"
assert update_events[2]["device_id"] == entry3.id
assert "changes" not in update_events[2]
assert update_events[3]["action"] == "update"
assert update_events[3]["device_id"] == entry.id
assert update_events[3]["changes"] == {
"config_entries": {config_entry_1.entry_id, config_entry_2.entry_id}
assert update_events[0].data == {
"action": "create",
"device_id": entry.id,
}
assert update_events[1].data == {
"action": "update",
"device_id": entry.id,
"changes": {"config_entries": {config_entry_1.entry_id}},
}
assert update_events[2].data == {
"action": "create",
"device_id": entry3.id,
}
assert update_events[3].data == {
"action": "update",
"device_id": entry.id,
"changes": {
"config_entries": {config_entry_1.entry_id, config_entry_2.entry_id}
},
}
assert update_events[4].data == {
"action": "remove",
"device_id": entry3.id,
}
assert update_events[4]["action"] == "remove"
assert update_events[4]["device_id"] == entry3.id
assert "changes" not in update_events[4]
async def test_deleted_device_removing_config_entries(
hass: HomeAssistant, device_registry: dr.DeviceRegistry, update_events
hass: HomeAssistant, device_registry: dr.DeviceRegistry
) -> None:
"""Make sure we do not get duplicate entries."""
update_events = async_capture_events(hass, dr.EVENT_DEVICE_REGISTRY_UPDATED)
config_entry_1 = MockConfigEntry()
config_entry_1.add_to_hass(hass)
config_entry_2 = MockConfigEntry()
@ -767,21 +764,27 @@ async def test_deleted_device_removing_config_entries(
await hass.async_block_till_done()
assert len(update_events) == 5
assert update_events[0]["action"] == "create"
assert update_events[0]["device_id"] == entry.id
assert "changes" not in update_events[0]
assert update_events[1]["action"] == "update"
assert update_events[1]["device_id"] == entry2.id
assert update_events[1]["changes"] == {"config_entries": {config_entry_1.entry_id}}
assert update_events[2]["action"] == "create"
assert update_events[2]["device_id"] == entry3.id
assert "changes" not in update_events[2]["device_id"]
assert update_events[3]["action"] == "remove"
assert update_events[3]["device_id"] == entry.id
assert "changes" not in update_events[3]
assert update_events[4]["action"] == "remove"
assert update_events[4]["device_id"] == entry3.id
assert "changes" not in update_events[4]
assert update_events[0].data == {
"action": "create",
"device_id": entry.id,
}
assert update_events[1].data == {
"action": "update",
"device_id": entry2.id,
"changes": {"config_entries": {config_entry_1.entry_id}},
}
assert update_events[2].data == {
"action": "create",
"device_id": entry3.id,
}
assert update_events[3].data == {
"action": "remove",
"device_id": entry.id,
}
assert update_events[4].data == {
"action": "remove",
"device_id": entry3.id,
}
device_registry.async_clear_config_entry(config_entry_1.entry_id)
assert len(device_registry.devices) == 0
@ -1105,9 +1108,9 @@ async def test_update(
hass: HomeAssistant,
device_registry: dr.DeviceRegistry,
mock_config_entry: MockConfigEntry,
update_events,
) -> None:
"""Verify that we can update some attributes of a device."""
update_events = async_capture_events(hass, dr.EVENT_DEVICE_REGISTRY_UPDATED)
entry = device_registry.async_get_or_create(
config_entry_id=mock_config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
@ -1180,33 +1183,37 @@ async def test_update(
await hass.async_block_till_done()
assert len(update_events) == 2
assert update_events[0]["action"] == "create"
assert update_events[0]["device_id"] == entry.id
assert "changes" not in update_events[0]
assert update_events[1]["action"] == "update"
assert update_events[1]["device_id"] == entry.id
assert update_events[1]["changes"] == {
"area_id": None,
"configuration_url": None,
"disabled_by": None,
"entry_type": None,
"hw_version": None,
"identifiers": {("bla", "123"), ("hue", "456")},
"manufacturer": None,
"model": None,
"name": None,
"name_by_user": None,
"serial_number": None,
"suggested_area": None,
"sw_version": None,
"via_device_id": None,
assert update_events[0].data == {
"action": "create",
"device_id": entry.id,
}
assert update_events[1].data == {
"action": "update",
"device_id": entry.id,
"changes": {
"area_id": None,
"configuration_url": None,
"disabled_by": None,
"entry_type": None,
"hw_version": None,
"identifiers": {("bla", "123"), ("hue", "456")},
"manufacturer": None,
"model": None,
"name": None,
"name_by_user": None,
"serial_number": None,
"suggested_area": None,
"sw_version": None,
"via_device_id": None,
},
}
async def test_update_remove_config_entries(
hass: HomeAssistant, device_registry: dr.DeviceRegistry, update_events
hass: HomeAssistant, device_registry: dr.DeviceRegistry
) -> None:
"""Make sure we do not get duplicate entries."""
update_events = async_capture_events(hass, dr.EVENT_DEVICE_REGISTRY_UPDATED)
config_entry_1 = MockConfigEntry()
config_entry_1.add_to_hass(hass)
config_entry_2 = MockConfigEntry()
@ -1256,23 +1263,30 @@ async def test_update_remove_config_entries(
await hass.async_block_till_done()
assert len(update_events) == 5
assert update_events[0]["action"] == "create"
assert update_events[0]["device_id"] == entry.id
assert "changes" not in update_events[0]
assert update_events[1]["action"] == "update"
assert update_events[1]["device_id"] == entry2.id
assert update_events[1]["changes"] == {"config_entries": {config_entry_1.entry_id}}
assert update_events[2]["action"] == "create"
assert update_events[2]["device_id"] == entry3.id
assert "changes" not in update_events[2]
assert update_events[3]["action"] == "update"
assert update_events[3]["device_id"] == entry.id
assert update_events[3]["changes"] == {
"config_entries": {config_entry_1.entry_id, config_entry_2.entry_id}
assert update_events[0].data == {
"action": "create",
"device_id": entry.id,
}
assert update_events[1].data == {
"action": "update",
"device_id": entry2.id,
"changes": {"config_entries": {config_entry_1.entry_id}},
}
assert update_events[2].data == {
"action": "create",
"device_id": entry3.id,
}
assert update_events[3].data == {
"action": "update",
"device_id": entry.id,
"changes": {
"config_entries": {config_entry_1.entry_id, config_entry_2.entry_id}
},
}
assert update_events[4].data == {
"action": "remove",
"device_id": entry3.id,
}
assert update_events[4]["action"] == "remove"
assert update_events[4]["device_id"] == entry3.id
assert "changes" not in update_events[4]
async def test_update_suggested_area(
@ -1280,9 +1294,9 @@ async def test_update_suggested_area(
device_registry: dr.DeviceRegistry,
area_registry: ar.AreaRegistry,
mock_config_entry: MockConfigEntry,
update_events,
) -> None:
"""Verify that we can update the suggested area version of a device."""
update_events = async_capture_events(hass, dr.EVENT_DEVICE_REGISTRY_UPDATED)
entry = device_registry.async_get_or_create(
config_entry_id=mock_config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
@ -1310,12 +1324,15 @@ async def test_update_suggested_area(
await hass.async_block_till_done()
assert len(update_events) == 2
assert update_events[0]["action"] == "create"
assert update_events[0]["device_id"] == entry.id
assert "changes" not in update_events[0]
assert update_events[1]["action"] == "update"
assert update_events[1]["device_id"] == entry.id
assert update_events[1]["changes"] == {"area_id": None, "suggested_area": None}
assert update_events[0].data == {
"action": "create",
"device_id": entry.id,
}
assert update_events[1].data == {
"action": "update",
"device_id": entry.id,
"changes": {"area_id": None, "suggested_area": None},
}
# Do not save or fire the event if the suggested
# area does not result in a change of area
@ -1457,9 +1474,9 @@ async def test_restore_device(
hass: HomeAssistant,
device_registry: dr.DeviceRegistry,
mock_config_entry: MockConfigEntry,
update_events,
) -> None:
"""Make sure device id is stable."""
update_events = async_capture_events(hass, dr.EVENT_DEVICE_REGISTRY_UPDATED)
entry = device_registry.async_get_or_create(
config_entry_id=mock_config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
@ -1503,27 +1520,31 @@ async def test_restore_device(
await hass.async_block_till_done()
assert len(update_events) == 4
assert update_events[0]["action"] == "create"
assert update_events[0]["device_id"] == entry.id
assert "changes" not in update_events[0]
assert update_events[1]["action"] == "remove"
assert update_events[1]["device_id"] == entry.id
assert "changes" not in update_events[1]
assert update_events[2]["action"] == "create"
assert update_events[2]["device_id"] == entry2.id
assert "changes" not in update_events[2]
assert update_events[3]["action"] == "create"
assert update_events[3]["device_id"] == entry3.id
assert "changes" not in update_events[3]
assert update_events[0].data == {
"action": "create",
"device_id": entry.id,
}
assert update_events[1].data == {
"action": "remove",
"device_id": entry.id,
}
assert update_events[2].data == {
"action": "create",
"device_id": entry2.id,
}
assert update_events[3].data == {
"action": "create",
"device_id": entry3.id,
}
async def test_restore_simple_device(
hass: HomeAssistant,
device_registry: dr.DeviceRegistry,
mock_config_entry: MockConfigEntry,
update_events,
) -> None:
"""Make sure device id is stable."""
update_events = async_capture_events(hass, dr.EVENT_DEVICE_REGISTRY_UPDATED)
entry = device_registry.async_get_or_create(
config_entry_id=mock_config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
@ -1557,24 +1578,29 @@ async def test_restore_simple_device(
await hass.async_block_till_done()
assert len(update_events) == 4
assert update_events[0]["action"] == "create"
assert update_events[0]["device_id"] == entry.id
assert "changes" not in update_events[0]
assert update_events[1]["action"] == "remove"
assert update_events[1]["device_id"] == entry.id
assert "changes" not in update_events[1]
assert update_events[2]["action"] == "create"
assert update_events[2]["device_id"] == entry2.id
assert "changes" not in update_events[2]
assert update_events[3]["action"] == "create"
assert update_events[3]["device_id"] == entry3.id
assert "changes" not in update_events[3]
assert update_events[0].data == {
"action": "create",
"device_id": entry.id,
}
assert update_events[1].data == {
"action": "remove",
"device_id": entry.id,
}
assert update_events[2].data == {
"action": "create",
"device_id": entry2.id,
}
assert update_events[3].data == {
"action": "create",
"device_id": entry3.id,
}
async def test_restore_shared_device(
hass: HomeAssistant, device_registry: dr.DeviceRegistry, update_events
hass: HomeAssistant, device_registry: dr.DeviceRegistry
) -> None:
"""Make sure device id is stable for shared devices."""
update_events = async_capture_events(hass, dr.EVENT_DEVICE_REGISTRY_UPDATED)
config_entry_1 = MockConfigEntry()
config_entry_1.add_to_hass(hass)
config_entry_2 = MockConfigEntry()
@ -1660,32 +1686,41 @@ async def test_restore_shared_device(
await hass.async_block_till_done()
assert len(update_events) == 7
assert update_events[0]["action"] == "create"
assert update_events[0]["device_id"] == entry.id
assert "changes" not in update_events[0]
assert update_events[1]["action"] == "update"
assert update_events[1]["device_id"] == entry.id
assert update_events[1]["changes"] == {
"config_entries": {config_entry_1.entry_id},
"identifiers": {("entry_123", "0123")},
assert update_events[0].data == {
"action": "create",
"device_id": entry.id,
}
assert update_events[2]["action"] == "remove"
assert update_events[2]["device_id"] == entry.id
assert "changes" not in update_events[2]
assert update_events[3]["action"] == "create"
assert update_events[3]["device_id"] == entry.id
assert "changes" not in update_events[3]
assert update_events[4]["action"] == "remove"
assert update_events[4]["device_id"] == entry.id
assert "changes" not in update_events[4]
assert update_events[5]["action"] == "create"
assert update_events[5]["device_id"] == entry.id
assert "changes" not in update_events[5]
assert update_events[6]["action"] == "update"
assert update_events[6]["device_id"] == entry.id
assert update_events[6]["changes"] == {
"config_entries": {config_entry_2.entry_id},
"identifiers": {("entry_234", "2345")},
assert update_events[1].data == {
"action": "update",
"device_id": entry.id,
"changes": {
"config_entries": {config_entry_1.entry_id},
"identifiers": {("entry_123", "0123")},
},
}
assert update_events[2].data == {
"action": "remove",
"device_id": entry.id,
}
assert update_events[3].data == {
"action": "create",
"device_id": entry.id,
}
assert update_events[4].data == {
"action": "remove",
"device_id": entry.id,
}
assert update_events[5].data == {
"action": "create",
"device_id": entry.id,
}
assert update_events[6].data == {
"action": "update",
"device_id": entry.id,
"changes": {
"config_entries": {config_entry_2.entry_id},
"identifiers": {("entry_234", "2345")},
},
}