Use fixtures in deCONZ service tests (#121108)
* Use fixtures in deCONZ service tests * Update tests/components/deconz/test_services.py Co-authored-by: J. Nick Koston <nick@koston.org> --------- Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
parent
ece8b74967
commit
f78933235d
1 changed files with 98 additions and 89 deletions
|
@ -1,6 +1,7 @@
|
|||
"""deCONZ service tests."""
|
||||
|
||||
from unittest.mock import patch
|
||||
from collections.abc import Callable
|
||||
from typing import Any
|
||||
|
||||
import pytest
|
||||
import voluptuous as vol
|
||||
|
@ -20,34 +21,29 @@ from homeassistant.components.deconz.services import (
|
|||
SERVICE_REMOVE_ORPHANED_ENTRIES,
|
||||
)
|
||||
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||
|
||||
from .test_gateway import (
|
||||
BRIDGEID,
|
||||
DECONZ_WEB_REQUEST,
|
||||
mock_deconz_put_request,
|
||||
mock_deconz_request,
|
||||
setup_deconz_integration,
|
||||
)
|
||||
from .test_gateway import BRIDGEID
|
||||
|
||||
from tests.common import async_capture_events
|
||||
from tests.test_util.aiohttp import AiohttpClientMocker
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("config_entry_setup")
|
||||
async def test_configure_service_with_field(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant,
|
||||
mock_put_request: Callable[[str, str], AiohttpClientMocker],
|
||||
) -> None:
|
||||
"""Test that service invokes pydeconz with the correct path and data."""
|
||||
config_entry = await setup_deconz_integration(hass, aioclient_mock)
|
||||
|
||||
data = {
|
||||
SERVICE_FIELD: "/lights/2",
|
||||
CONF_BRIDGE_ID: BRIDGEID,
|
||||
SERVICE_DATA: {"on": True, "attr1": 10, "attr2": 20},
|
||||
}
|
||||
|
||||
mock_deconz_put_request(aioclient_mock, config_entry.data, "/lights/2")
|
||||
aioclient_mock = mock_put_request("/lights/2")
|
||||
|
||||
await hass.services.async_call(
|
||||
DECONZ_DOMAIN, SERVICE_CONFIGURE_DEVICE, service_data=data, blocking=True
|
||||
|
@ -55,12 +51,10 @@ async def test_configure_service_with_field(
|
|||
assert aioclient_mock.mock_calls[1][2] == {"on": True, "attr1": 10, "attr2": 20}
|
||||
|
||||
|
||||
async def test_configure_service_with_entity(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
) -> None:
|
||||
"""Test that service invokes pydeconz with the correct path and data."""
|
||||
data = {
|
||||
"lights": {
|
||||
@pytest.mark.parametrize(
|
||||
"light_payload",
|
||||
[
|
||||
{
|
||||
"1": {
|
||||
"name": "Test",
|
||||
"state": {"reachable": True},
|
||||
|
@ -68,16 +62,19 @@ async def test_configure_service_with_entity(
|
|||
"uniqueid": "00:00:00:00:00:00:00:01-00",
|
||||
}
|
||||
}
|
||||
}
|
||||
with patch.dict(DECONZ_WEB_REQUEST, data):
|
||||
config_entry = await setup_deconz_integration(hass, aioclient_mock)
|
||||
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("config_entry_setup")
|
||||
async def test_configure_service_with_entity(
|
||||
hass: HomeAssistant,
|
||||
mock_put_request: Callable[[str, str], AiohttpClientMocker],
|
||||
) -> None:
|
||||
"""Test that service invokes pydeconz with the correct path and data."""
|
||||
data = {
|
||||
SERVICE_ENTITY: "light.test",
|
||||
SERVICE_DATA: {"on": True, "attr1": 10, "attr2": 20},
|
||||
}
|
||||
|
||||
mock_deconz_put_request(aioclient_mock, config_entry.data, "/lights/1")
|
||||
aioclient_mock = mock_put_request("/lights/1")
|
||||
|
||||
await hass.services.async_call(
|
||||
DECONZ_DOMAIN, SERVICE_CONFIGURE_DEVICE, service_data=data, blocking=True
|
||||
|
@ -85,12 +82,10 @@ async def test_configure_service_with_entity(
|
|||
assert aioclient_mock.mock_calls[1][2] == {"on": True, "attr1": 10, "attr2": 20}
|
||||
|
||||
|
||||
async def test_configure_service_with_entity_and_field(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
) -> None:
|
||||
"""Test that service invokes pydeconz with the correct path and data."""
|
||||
data = {
|
||||
"lights": {
|
||||
@pytest.mark.parametrize(
|
||||
"light_payload",
|
||||
[
|
||||
{
|
||||
"1": {
|
||||
"name": "Test",
|
||||
"state": {"reachable": True},
|
||||
|
@ -98,17 +93,20 @@ async def test_configure_service_with_entity_and_field(
|
|||
"uniqueid": "00:00:00:00:00:00:00:01-00",
|
||||
}
|
||||
}
|
||||
}
|
||||
with patch.dict(DECONZ_WEB_REQUEST, data):
|
||||
config_entry = await setup_deconz_integration(hass, aioclient_mock)
|
||||
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("config_entry_setup")
|
||||
async def test_configure_service_with_entity_and_field(
|
||||
hass: HomeAssistant,
|
||||
mock_put_request: Callable[[str, str], AiohttpClientMocker],
|
||||
) -> None:
|
||||
"""Test that service invokes pydeconz with the correct path and data."""
|
||||
data = {
|
||||
SERVICE_ENTITY: "light.test",
|
||||
SERVICE_FIELD: "/state",
|
||||
SERVICE_DATA: {"on": True, "attr1": 10, "attr2": 20},
|
||||
}
|
||||
|
||||
mock_deconz_put_request(aioclient_mock, config_entry.data, "/lights/1/state")
|
||||
aioclient_mock = mock_put_request("/lights/1/state")
|
||||
|
||||
await hass.services.async_call(
|
||||
DECONZ_DOMAIN, SERVICE_CONFIGURE_DEVICE, service_data=data, blocking=True
|
||||
|
@ -116,11 +114,11 @@ async def test_configure_service_with_entity_and_field(
|
|||
assert aioclient_mock.mock_calls[1][2] == {"on": True, "attr1": 10, "attr2": 20}
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("config_entry_setup")
|
||||
async def test_configure_service_with_faulty_bridgeid(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
) -> None:
|
||||
"""Test that service fails on a bad bridge id."""
|
||||
await setup_deconz_integration(hass, aioclient_mock)
|
||||
aioclient_mock.clear_requests()
|
||||
|
||||
data = {
|
||||
|
@ -137,12 +135,9 @@ async def test_configure_service_with_faulty_bridgeid(
|
|||
assert len(aioclient_mock.mock_calls) == 0
|
||||
|
||||
|
||||
async def test_configure_service_with_faulty_field(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
) -> None:
|
||||
@pytest.mark.usefixtures("config_entry_setup")
|
||||
async def test_configure_service_with_faulty_field(hass: HomeAssistant) -> None:
|
||||
"""Test that service fails on a bad field."""
|
||||
await setup_deconz_integration(hass, aioclient_mock)
|
||||
|
||||
data = {SERVICE_FIELD: "light/2", SERVICE_DATA: {}}
|
||||
|
||||
with pytest.raises(vol.Invalid):
|
||||
|
@ -151,11 +146,11 @@ async def test_configure_service_with_faulty_field(
|
|||
)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("config_entry_setup")
|
||||
async def test_configure_service_with_faulty_entity(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
) -> None:
|
||||
"""Test that service on a non existing entity."""
|
||||
await setup_deconz_integration(hass, aioclient_mock)
|
||||
aioclient_mock.clear_requests()
|
||||
|
||||
data = {
|
||||
|
@ -171,13 +166,12 @@ async def test_configure_service_with_faulty_entity(
|
|||
assert len(aioclient_mock.mock_calls) == 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize("config_entry_options", [{CONF_MASTER_GATEWAY: False}])
|
||||
@pytest.mark.usefixtures("config_entry_setup")
|
||||
async def test_calling_service_with_no_master_gateway_fails(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
) -> None:
|
||||
"""Test that service call fails when no master gateway exist."""
|
||||
await setup_deconz_integration(
|
||||
hass, aioclient_mock, options={CONF_MASTER_GATEWAY: False}
|
||||
)
|
||||
aioclient_mock.clear_requests()
|
||||
|
||||
data = {
|
||||
|
@ -193,18 +187,19 @@ async def test_calling_service_with_no_master_gateway_fails(
|
|||
assert len(aioclient_mock.mock_calls) == 0
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("config_entry_setup")
|
||||
async def test_service_refresh_devices(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant,
|
||||
aioclient_mock: AiohttpClientMocker,
|
||||
deconz_payload: dict[str, Any],
|
||||
mock_requests: Callable[[], None],
|
||||
) -> None:
|
||||
"""Test that service can refresh devices."""
|
||||
config_entry = await setup_deconz_integration(hass, aioclient_mock)
|
||||
|
||||
assert len(hass.states.async_all()) == 0
|
||||
|
||||
aioclient_mock.clear_requests()
|
||||
|
||||
data = {
|
||||
"config": {},
|
||||
deconz_payload |= {
|
||||
"groups": {
|
||||
"1": {
|
||||
"id": "Group 1 id",
|
||||
|
@ -234,8 +229,7 @@ async def test_service_refresh_devices(
|
|||
}
|
||||
},
|
||||
}
|
||||
|
||||
mock_deconz_request(aioclient_mock, config_entry.data, data)
|
||||
mock_requests()
|
||||
|
||||
await hass.services.async_call(
|
||||
DECONZ_DOMAIN, SERVICE_DEVICE_REFRESH, service_data={CONF_BRIDGE_ID: BRIDGEID}
|
||||
|
@ -245,12 +239,10 @@ async def test_service_refresh_devices(
|
|||
assert len(hass.states.async_all()) == 5
|
||||
|
||||
|
||||
async def test_service_refresh_devices_trigger_no_state_update(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
) -> None:
|
||||
"""Verify that gateway.ignore_state_updates are honored."""
|
||||
data = {
|
||||
"sensors": {
|
||||
@pytest.mark.parametrize(
|
||||
"sensor_payload",
|
||||
[
|
||||
{
|
||||
"1": {
|
||||
"name": "Switch 1",
|
||||
"type": "ZHASwitch",
|
||||
|
@ -259,18 +251,23 @@ async def test_service_refresh_devices_trigger_no_state_update(
|
|||
"uniqueid": "00:00:00:00:00:00:00:01-00",
|
||||
}
|
||||
}
|
||||
}
|
||||
with patch.dict(DECONZ_WEB_REQUEST, data):
|
||||
config_entry = await setup_deconz_integration(hass, aioclient_mock)
|
||||
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("config_entry_setup")
|
||||
async def test_service_refresh_devices_trigger_no_state_update(
|
||||
hass: HomeAssistant,
|
||||
aioclient_mock: AiohttpClientMocker,
|
||||
deconz_payload: dict[str, Any],
|
||||
mock_requests,
|
||||
) -> None:
|
||||
"""Verify that gateway.ignore_state_updates are honored."""
|
||||
assert len(hass.states.async_all()) == 1
|
||||
|
||||
captured_events = async_capture_events(hass, CONF_DECONZ_EVENT)
|
||||
|
||||
aioclient_mock.clear_requests()
|
||||
|
||||
data = {
|
||||
"config": {},
|
||||
deconz_payload |= {
|
||||
"groups": {
|
||||
"1": {
|
||||
"id": "Group 1 id",
|
||||
|
@ -300,8 +297,7 @@ async def test_service_refresh_devices_trigger_no_state_update(
|
|||
}
|
||||
},
|
||||
}
|
||||
|
||||
mock_deconz_request(aioclient_mock, config_entry.data, data)
|
||||
mock_requests()
|
||||
|
||||
await hass.services.async_call(
|
||||
DECONZ_DOMAIN, SERVICE_DEVICE_REFRESH, service_data={CONF_BRIDGE_ID: BRIDGEID}
|
||||
|
@ -312,23 +308,23 @@ async def test_service_refresh_devices_trigger_no_state_update(
|
|||
assert len(captured_events) == 0
|
||||
|
||||
|
||||
async def test_remove_orphaned_entries_service(
|
||||
hass: HomeAssistant,
|
||||
device_registry: dr.DeviceRegistry,
|
||||
entity_registry: er.EntityRegistry,
|
||||
aioclient_mock: AiohttpClientMocker,
|
||||
) -> None:
|
||||
"""Test service works and also don't remove more than expected."""
|
||||
data = {
|
||||
"lights": {
|
||||
@pytest.mark.parametrize(
|
||||
"light_payload",
|
||||
[
|
||||
{
|
||||
"1": {
|
||||
"name": "Light 1 name",
|
||||
"state": {"reachable": True},
|
||||
"type": "Light",
|
||||
"uniqueid": "00:00:00:00:00:00:00:01-00",
|
||||
}
|
||||
},
|
||||
"sensors": {
|
||||
}
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
"sensor_payload",
|
||||
[
|
||||
{
|
||||
"1": {
|
||||
"name": "Switch 1",
|
||||
"type": "ZHASwitch",
|
||||
|
@ -336,13 +332,18 @@ async def test_remove_orphaned_entries_service(
|
|||
"config": {"battery": 100},
|
||||
"uniqueid": "00:00:00:00:00:00:00:03-00",
|
||||
},
|
||||
},
|
||||
}
|
||||
with patch.dict(DECONZ_WEB_REQUEST, data):
|
||||
config_entry = await setup_deconz_integration(hass, aioclient_mock)
|
||||
|
||||
}
|
||||
],
|
||||
)
|
||||
async def test_remove_orphaned_entries_service(
|
||||
hass: HomeAssistant,
|
||||
device_registry: dr.DeviceRegistry,
|
||||
entity_registry: er.EntityRegistry,
|
||||
config_entry_setup: ConfigEntry,
|
||||
) -> None:
|
||||
"""Test service works and also don't remove more than expected."""
|
||||
device = device_registry.async_get_or_create(
|
||||
config_entry_id=config_entry.entry_id,
|
||||
config_entry_id=config_entry_setup.entry_id,
|
||||
connections={(dr.CONNECTION_NETWORK_MAC, "123")},
|
||||
)
|
||||
|
||||
|
@ -351,7 +352,7 @@ async def test_remove_orphaned_entries_service(
|
|||
[
|
||||
entry
|
||||
for entry in device_registry.devices.values()
|
||||
if config_entry.entry_id in entry.config_entries
|
||||
if config_entry_setup.entry_id in entry.config_entries
|
||||
]
|
||||
)
|
||||
== 5 # Host, gateway, light, switch and orphan
|
||||
|
@ -362,12 +363,16 @@ async def test_remove_orphaned_entries_service(
|
|||
DECONZ_DOMAIN,
|
||||
"12345",
|
||||
suggested_object_id="Orphaned sensor",
|
||||
config_entry=config_entry,
|
||||
config_entry=config_entry_setup,
|
||||
device_id=device.id,
|
||||
)
|
||||
|
||||
assert (
|
||||
len(er.async_entries_for_config_entry(entity_registry, config_entry.entry_id))
|
||||
len(
|
||||
er.async_entries_for_config_entry(
|
||||
entity_registry, config_entry_setup.entry_id
|
||||
)
|
||||
)
|
||||
== 3 # Light, switch battery and orphan
|
||||
)
|
||||
|
||||
|
@ -383,13 +388,17 @@ async def test_remove_orphaned_entries_service(
|
|||
[
|
||||
entry
|
||||
for entry in device_registry.devices.values()
|
||||
if config_entry.entry_id in entry.config_entries
|
||||
if config_entry_setup.entry_id in entry.config_entries
|
||||
]
|
||||
)
|
||||
== 4 # Host, gateway, light and switch
|
||||
)
|
||||
|
||||
assert (
|
||||
len(er.async_entries_for_config_entry(entity_registry, config_entry.entry_id))
|
||||
len(
|
||||
er.async_entries_for_config_entry(
|
||||
entity_registry, config_entry_setup.entry_id
|
||||
)
|
||||
)
|
||||
== 2 # Light and switch battery
|
||||
)
|
||||
|
|
Loading…
Add table
Reference in a new issue