1
mirror of https://github.com/home-assistant/core synced 2024-09-28 03:04:04 +02:00

Improve deCONZ tests by using aioclient_mock rather than patching web requests (#45927)

* Don't patch web requests, use aioclient_mock instead

* Remove stale prints

* Remove tests for old way of loading platforms

* Remove unused imports
This commit is contained in:
Robert Svensson 2021-02-09 08:31:29 +01:00 committed by GitHub
parent b33753f334
commit 20f45f8ab9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 700 additions and 857 deletions

View File

@ -1,12 +1,10 @@
"""deCONZ binary sensor platform tests."""
from copy import deepcopy
from unittest.mock import patch
from homeassistant.components.binary_sensor import (
DEVICE_CLASS_MOTION,
DEVICE_CLASS_VIBRATION,
DOMAIN as BINARY_SENSOR_DOMAIN,
)
from homeassistant.components.deconz.const import (
CONF_ALLOW_CLIP_SENSOR,
@ -18,9 +16,12 @@ from homeassistant.components.deconz.gateway import get_gateway_from_config_entr
from homeassistant.components.deconz.services import SERVICE_DEVICE_REFRESH
from homeassistant.const import STATE_OFF, STATE_ON, STATE_UNAVAILABLE
from homeassistant.helpers.entity_registry import async_entries_for_config_entry
from homeassistant.setup import async_setup_component
from .test_gateway import DECONZ_WEB_REQUEST, setup_deconz_integration
from .test_gateway import (
DECONZ_WEB_REQUEST,
mock_deconz_request,
setup_deconz_integration,
)
SENSORS = {
"1": {
@ -63,28 +64,19 @@ SENSORS = {
}
async def test_platform_manually_configured(hass):
"""Test that we do not discover anything or try to set up a gateway."""
assert (
await async_setup_component(
hass, BINARY_SENSOR_DOMAIN, {"binary_sensor": {"platform": DECONZ_DOMAIN}}
)
is True
)
assert DECONZ_DOMAIN not in hass.data
async def test_no_binary_sensors(hass):
async def test_no_binary_sensors(hass, aioclient_mock):
"""Test that no sensors in deconz results in no sensor entities."""
await setup_deconz_integration(hass)
await setup_deconz_integration(hass, aioclient_mock)
assert len(hass.states.async_all()) == 0
async def test_binary_sensors(hass):
async def test_binary_sensors(hass, aioclient_mock):
"""Test successful creation of binary sensor entities."""
data = deepcopy(DECONZ_WEB_REQUEST)
data["sensors"] = deepcopy(SENSORS)
config_entry = await setup_deconz_integration(hass, get_state_response=data)
config_entry = await setup_deconz_integration(
hass, aioclient_mock, get_state_response=data
)
gateway = get_gateway_from_config_entry(hass, config_entry)
assert len(hass.states.async_all()) == 3
@ -118,12 +110,13 @@ async def test_binary_sensors(hass):
assert len(hass.states.async_all()) == 0
async def test_allow_clip_sensor(hass):
async def test_allow_clip_sensor(hass, aioclient_mock):
"""Test that CLIP sensors can be allowed."""
data = deepcopy(DECONZ_WEB_REQUEST)
data["sensors"] = deepcopy(SENSORS)
config_entry = await setup_deconz_integration(
hass,
aioclient_mock,
options={CONF_ALLOW_CLIP_SENSOR: True},
get_state_response=data,
)
@ -155,9 +148,9 @@ async def test_allow_clip_sensor(hass):
assert hass.states.get("binary_sensor.clip_presence_sensor").state == STATE_OFF
async def test_add_new_binary_sensor(hass):
async def test_add_new_binary_sensor(hass, aioclient_mock):
"""Test that adding a new binary sensor works."""
config_entry = await setup_deconz_integration(hass)
config_entry = await setup_deconz_integration(hass, aioclient_mock)
gateway = get_gateway_from_config_entry(hass, config_entry)
assert len(hass.states.async_all()) == 0
@ -175,10 +168,11 @@ async def test_add_new_binary_sensor(hass):
assert hass.states.get("binary_sensor.presence_sensor").state == STATE_OFF
async def test_add_new_binary_sensor_ignored(hass):
async def test_add_new_binary_sensor_ignored(hass, aioclient_mock):
"""Test that adding a new binary sensor is not allowed."""
config_entry = await setup_deconz_integration(
hass,
aioclient_mock,
options={CONF_MASTER_GATEWAY: True, CONF_ALLOW_NEW_DEVICES: False},
)
gateway = get_gateway_from_config_entry(hass, config_entry)
@ -202,16 +196,16 @@ async def test_add_new_binary_sensor_ignored(hass):
len(async_entries_for_config_entry(entity_registry, config_entry.entry_id)) == 0
)
with patch(
"pydeconz.DeconzSession.request",
return_value={
"groups": {},
"lights": {},
"sensors": {"1": deepcopy(SENSORS["1"])},
},
):
await hass.services.async_call(DECONZ_DOMAIN, SERVICE_DEVICE_REFRESH)
await hass.async_block_till_done()
aioclient_mock.clear_requests()
data = {
"groups": {},
"lights": {},
"sensors": {"1": deepcopy(SENSORS["1"])},
}
mock_deconz_request(aioclient_mock, config_entry.data, data)
await hass.services.async_call(DECONZ_DOMAIN, SERVICE_DEVICE_REFRESH)
await hass.async_block_till_done()
assert len(hass.states.async_all()) == 1
assert hass.states.get("binary_sensor.presence_sensor")

View File

@ -1,7 +1,6 @@
"""deCONZ climate platform tests."""
from copy import deepcopy
from unittest.mock import patch
import pytest
@ -34,10 +33,7 @@ from homeassistant.components.deconz.climate import (
DECONZ_FAN_SMART,
DECONZ_PRESET_MANUAL,
)
from homeassistant.components.deconz.const import (
CONF_ALLOW_CLIP_SENSOR,
DOMAIN as DECONZ_DOMAIN,
)
from homeassistant.components.deconz.const import CONF_ALLOW_CLIP_SENSOR
from homeassistant.components.deconz.gateway import get_gateway_from_config_entry
from homeassistant.const import (
ATTR_ENTITY_ID,
@ -45,9 +41,12 @@ from homeassistant.const import (
STATE_OFF,
STATE_UNAVAILABLE,
)
from homeassistant.setup import async_setup_component
from .test_gateway import DECONZ_WEB_REQUEST, setup_deconz_integration
from .test_gateway import (
DECONZ_WEB_REQUEST,
mock_deconz_put_request,
setup_deconz_integration,
)
SENSORS = {
"1": {
@ -75,24 +74,13 @@ SENSORS = {
}
async def test_platform_manually_configured(hass):
"""Test that we do not discover anything or try to set up a gateway."""
assert (
await async_setup_component(
hass, CLIMATE_DOMAIN, {"climate": {"platform": DECONZ_DOMAIN}}
)
is True
)
assert DECONZ_DOMAIN not in hass.data
async def test_no_sensors(hass):
async def test_no_sensors(hass, aioclient_mock):
"""Test that no sensors in deconz results in no climate entities."""
await setup_deconz_integration(hass)
await setup_deconz_integration(hass, aioclient_mock)
assert len(hass.states.async_all()) == 0
async def test_simple_climate_device(hass):
async def test_simple_climate_device(hass, aioclient_mock):
"""Test successful creation of climate entities.
This is a simple water heater that only supports setting temperature and on and off.
@ -130,7 +118,9 @@ async def test_simple_climate_device(hass):
"uniqueid": "14:b4:57:ff:fe:d5:4e:77-01-0201",
}
}
config_entry = await setup_deconz_integration(hass, get_state_response=data)
config_entry = await setup_deconz_integration(
hass, aioclient_mock, get_state_response=data
)
gateway = get_gateway_from_config_entry(hass, config_entry)
assert len(hass.states.async_all()) == 2
@ -174,37 +164,31 @@ async def test_simple_climate_device(hass):
# Verify service calls
thermostat_device = gateway.api.sensors["0"]
mock_deconz_put_request(aioclient_mock, config_entry.data, "/sensors/0/config")
# Service turn on thermostat
with patch.object(thermostat_device, "_request", return_value=True) as set_callback:
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_HVAC_MODE,
{ATTR_ENTITY_ID: "climate.thermostat", ATTR_HVAC_MODE: HVAC_MODE_HEAT},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with("put", "/sensors/0/config", json={"on": True})
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_HVAC_MODE,
{ATTR_ENTITY_ID: "climate.thermostat", ATTR_HVAC_MODE: HVAC_MODE_HEAT},
blocking=True,
)
assert aioclient_mock.mock_calls[1][2] == {"on": True}
# Service turn on thermostat
with patch.object(thermostat_device, "_request", return_value=True) as set_callback:
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_HVAC_MODE,
{ATTR_ENTITY_ID: "climate.thermostat", ATTR_HVAC_MODE: HVAC_MODE_OFF},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with("put", "/sensors/0/config", json={"on": False})
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_HVAC_MODE,
{ATTR_ENTITY_ID: "climate.thermostat", ATTR_HVAC_MODE: HVAC_MODE_OFF},
blocking=True,
)
assert aioclient_mock.mock_calls[2][2] == {"on": False}
# Service set HVAC mode to unsupported value
with patch.object(
thermostat_device, "_request", return_value=True
) as set_callback, pytest.raises(ValueError):
with pytest.raises(ValueError):
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_HVAC_MODE,
@ -213,11 +197,13 @@ async def test_simple_climate_device(hass):
)
async def test_climate_device_without_cooling_support(hass):
async def test_climate_device_without_cooling_support(hass, aioclient_mock):
"""Test successful creation of sensor entities."""
data = deepcopy(DECONZ_WEB_REQUEST)
data["sensors"] = deepcopy(SENSORS)
config_entry = await setup_deconz_integration(hass, get_state_response=data)
config_entry = await setup_deconz_integration(
hass, aioclient_mock, get_state_response=data
)
gateway = get_gateway_from_config_entry(hass, config_entry)
assert len(hass.states.async_all()) == 2
@ -280,54 +266,41 @@ async def test_climate_device_without_cooling_support(hass):
# Verify service calls
thermostat_device = gateway.api.sensors["1"]
mock_deconz_put_request(aioclient_mock, config_entry.data, "/sensors/1/config")
# Service set HVAC mode to auto
with patch.object(thermostat_device, "_request", return_value=True) as set_callback:
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_HVAC_MODE,
{ATTR_ENTITY_ID: "climate.thermostat", ATTR_HVAC_MODE: HVAC_MODE_AUTO},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with(
"put", "/sensors/1/config", json={"mode": "auto"}
)
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_HVAC_MODE,
{ATTR_ENTITY_ID: "climate.thermostat", ATTR_HVAC_MODE: HVAC_MODE_AUTO},
blocking=True,
)
assert aioclient_mock.mock_calls[1][2] == {"mode": "auto"}
# Service set HVAC mode to heat
with patch.object(thermostat_device, "_request", return_value=True) as set_callback:
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_HVAC_MODE,
{ATTR_ENTITY_ID: "climate.thermostat", ATTR_HVAC_MODE: HVAC_MODE_HEAT},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with(
"put", "/sensors/1/config", json={"mode": "heat"}
)
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_HVAC_MODE,
{ATTR_ENTITY_ID: "climate.thermostat", ATTR_HVAC_MODE: HVAC_MODE_HEAT},
blocking=True,
)
assert aioclient_mock.mock_calls[2][2] == {"mode": "heat"}
# Service set HVAC mode to off
with patch.object(thermostat_device, "_request", return_value=True) as set_callback:
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_HVAC_MODE,
{ATTR_ENTITY_ID: "climate.thermostat", ATTR_HVAC_MODE: HVAC_MODE_OFF},
blocking=True,
)
set_callback.assert_called_with(
"put", "/sensors/1/config", json={"mode": "off"}
)
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_HVAC_MODE,
{ATTR_ENTITY_ID: "climate.thermostat", ATTR_HVAC_MODE: HVAC_MODE_OFF},
blocking=True,
)
assert aioclient_mock.mock_calls[3][2] == {"mode": "off"}
# Service set HVAC mode to unsupported value
with patch.object(
thermostat_device, "_request", return_value=True
) as set_callback, pytest.raises(ValueError):
with pytest.raises(ValueError):
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_HVAC_MODE,
@ -337,22 +310,17 @@ async def test_climate_device_without_cooling_support(hass):
# Service set temperature to 20
with patch.object(thermostat_device, "_request", return_value=True) as set_callback:
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_TEMPERATURE,
{ATTR_ENTITY_ID: "climate.thermostat", ATTR_TEMPERATURE: 20},
blocking=True,
)
set_callback.assert_called_with(
"put", "/sensors/1/config", json={"heatsetpoint": 2000.0}
)
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_TEMPERATURE,
{ATTR_ENTITY_ID: "climate.thermostat", ATTR_TEMPERATURE: 20},
blocking=True,
)
assert aioclient_mock.mock_calls[4][2] == {"heatsetpoint": 2000.0}
# Service set temperature without providing temperature attribute
with patch.object(
thermostat_device, "_request", return_value=True
) as set_callback, pytest.raises(ValueError):
with pytest.raises(ValueError):
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_TEMPERATURE,
@ -376,7 +344,7 @@ async def test_climate_device_without_cooling_support(hass):
assert len(hass.states.async_all()) == 0
async def test_climate_device_with_cooling_support(hass):
async def test_climate_device_with_cooling_support(hass, aioclient_mock):
"""Test successful creation of sensor entities."""
data = deepcopy(DECONZ_WEB_REQUEST)
data["sensors"] = {
@ -406,7 +374,9 @@ async def test_climate_device_with_cooling_support(hass):
"uniqueid": "00:24:46:00:00:11:6f:56-01-0201",
}
}
config_entry = await setup_deconz_integration(hass, get_state_response=data)
config_entry = await setup_deconz_integration(
hass, aioclient_mock, get_state_response=data
)
gateway = get_gateway_from_config_entry(hass, config_entry)
assert len(hass.states.async_all()) == 2
@ -438,23 +408,20 @@ async def test_climate_device_with_cooling_support(hass):
# Verify service calls
thermostat_device = gateway.api.sensors["0"]
mock_deconz_put_request(aioclient_mock, config_entry.data, "/sensors/0/config")
# Service set temperature to 20
with patch.object(thermostat_device, "_request", return_value=True) as set_callback:
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_TEMPERATURE,
{ATTR_ENTITY_ID: "climate.zen_01", ATTR_TEMPERATURE: 20},
blocking=True,
)
set_callback.assert_called_with(
"put", "/sensors/0/config", json={"coolsetpoint": 2000.0}
)
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_TEMPERATURE,
{ATTR_ENTITY_ID: "climate.zen_01", ATTR_TEMPERATURE: 20},
blocking=True,
)
assert aioclient_mock.mock_calls[1][2] == {"coolsetpoint": 2000.0}
async def test_climate_device_with_fan_support(hass):
async def test_climate_device_with_fan_support(hass, aioclient_mock):
"""Test successful creation of sensor entities."""
data = deepcopy(DECONZ_WEB_REQUEST)
data["sensors"] = {
@ -484,7 +451,9 @@ async def test_climate_device_with_fan_support(hass):
"uniqueid": "00:24:46:00:00:11:6f:56-01-0201",
}
}
config_entry = await setup_deconz_integration(hass, get_state_response=data)
config_entry = await setup_deconz_integration(
hass, aioclient_mock, get_state_response=data
)
gateway = get_gateway_from_config_entry(hass, config_entry)
assert len(hass.states.async_all()) == 2
@ -546,39 +515,31 @@ async def test_climate_device_with_fan_support(hass):
# Verify service calls
thermostat_device = gateway.api.sensors["0"]
mock_deconz_put_request(aioclient_mock, config_entry.data, "/sensors/0/config")
# Service set fan mode to off
with patch.object(thermostat_device, "_request", return_value=True) as set_callback:
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_FAN_MODE,
{ATTR_ENTITY_ID: "climate.zen_01", ATTR_FAN_MODE: FAN_OFF},
blocking=True,
)
set_callback.assert_called_with(
"put", "/sensors/0/config", json={"fanmode": "off"}
)
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_FAN_MODE,
{ATTR_ENTITY_ID: "climate.zen_01", ATTR_FAN_MODE: FAN_OFF},
blocking=True,
)
assert aioclient_mock.mock_calls[1][2] == {"fanmode": "off"}
# Service set fan mode to custom deCONZ mode smart
with patch.object(thermostat_device, "_request", return_value=True) as set_callback:
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_FAN_MODE,
{ATTR_ENTITY_ID: "climate.zen_01", ATTR_FAN_MODE: DECONZ_FAN_SMART},
blocking=True,
)
set_callback.assert_called_with(
"put", "/sensors/0/config", json={"fanmode": "smart"}
)
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_FAN_MODE,
{ATTR_ENTITY_ID: "climate.zen_01", ATTR_FAN_MODE: DECONZ_FAN_SMART},
blocking=True,
)
assert aioclient_mock.mock_calls[2][2] == {"fanmode": "smart"}
# Service set fan mode to unsupported value
with patch.object(
thermostat_device, "_request", return_value=True
) as set_callback, pytest.raises(ValueError):
with pytest.raises(ValueError):
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_FAN_MODE,
@ -587,7 +548,7 @@ async def test_climate_device_with_fan_support(hass):
)
async def test_climate_device_with_preset(hass):
async def test_climate_device_with_preset(hass, aioclient_mock):
"""Test successful creation of sensor entities."""
data = deepcopy(DECONZ_WEB_REQUEST)
data["sensors"] = {
@ -618,7 +579,9 @@ async def test_climate_device_with_preset(hass):
"uniqueid": "00:24:46:00:00:11:6f:56-01-0201",
}
}
config_entry = await setup_deconz_integration(hass, get_state_response=data)
config_entry = await setup_deconz_integration(
hass, aioclient_mock, get_state_response=data
)
gateway = get_gateway_from_config_entry(hass, config_entry)
assert len(hass.states.async_all()) == 2
@ -671,41 +634,31 @@ async def test_climate_device_with_preset(hass):
# Verify service calls
thermostat_device = gateway.api.sensors["0"]
mock_deconz_put_request(aioclient_mock, config_entry.data, "/sensors/0/config")
# Service set preset to HASS preset
with patch.object(thermostat_device, "_request", return_value=True) as set_callback:
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_PRESET_MODE,
{ATTR_ENTITY_ID: "climate.zen_01", ATTR_PRESET_MODE: PRESET_COMFORT},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with(
"put", "/sensors/0/config", json={"preset": "comfort"}
)
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_PRESET_MODE,
{ATTR_ENTITY_ID: "climate.zen_01", ATTR_PRESET_MODE: PRESET_COMFORT},
blocking=True,
)
assert aioclient_mock.mock_calls[1][2] == {"preset": "comfort"}
# Service set preset to custom deCONZ preset
with patch.object(thermostat_device, "_request", return_value=True) as set_callback:
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_PRESET_MODE,
{ATTR_ENTITY_ID: "climate.zen_01", ATTR_PRESET_MODE: DECONZ_PRESET_MANUAL},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with(
"put", "/sensors/0/config", json={"preset": "manual"}
)
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_PRESET_MODE,
{ATTR_ENTITY_ID: "climate.zen_01", ATTR_PRESET_MODE: DECONZ_PRESET_MANUAL},
blocking=True,
)
assert aioclient_mock.mock_calls[2][2] == {"preset": "manual"}
# Service set preset to unsupported value
with patch.object(
thermostat_device, "_request", return_value=True
) as set_callback, pytest.raises(ValueError):
with pytest.raises(ValueError):
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_PRESET_MODE,
@ -714,12 +667,13 @@ async def test_climate_device_with_preset(hass):
)
async def test_clip_climate_device(hass):
async def test_clip_climate_device(hass, aioclient_mock):
"""Test successful creation of sensor entities."""
data = deepcopy(DECONZ_WEB_REQUEST)
data["sensors"] = deepcopy(SENSORS)
config_entry = await setup_deconz_integration(
hass,
aioclient_mock,
options={CONF_ALLOW_CLIP_SENSOR: True},
get_state_response=data,
)
@ -751,11 +705,13 @@ async def test_clip_climate_device(hass):
assert hass.states.get("climate.clip_thermostat").state == HVAC_MODE_HEAT
async def test_verify_state_update(hass):
async def test_verify_state_update(hass, aioclient_mock):
"""Test that state update properly."""
data = deepcopy(DECONZ_WEB_REQUEST)
data["sensors"] = deepcopy(SENSORS)
config_entry = await setup_deconz_integration(hass, get_state_response=data)
config_entry = await setup_deconz_integration(
hass, aioclient_mock, get_state_response=data
)
gateway = get_gateway_from_config_entry(hass, config_entry)
assert hass.states.get("climate.thermostat").state == HVAC_MODE_AUTO
@ -774,9 +730,9 @@ async def test_verify_state_update(hass):
assert gateway.api.sensors["1"].changed_keys == {"state", "r", "t", "on", "e", "id"}
async def test_add_new_climate_device(hass):
async def test_add_new_climate_device(hass, aioclient_mock):
"""Test that adding a new climate device works."""
config_entry = await setup_deconz_integration(hass)
config_entry = await setup_deconz_integration(hass, aioclient_mock)
gateway = get_gateway_from_config_entry(hass, config_entry)
assert len(hass.states.async_all()) == 0

View File

@ -212,7 +212,7 @@ async def test_manual_configuration_after_discovery_ResponseError(hass, aioclien
async def test_manual_configuration_update_configuration(hass, aioclient_mock):
"""Test that manual configuration can update existing config entry."""
config_entry = await setup_deconz_integration(hass)
config_entry = await setup_deconz_integration(hass, aioclient_mock)
aioclient_mock.get(
pydeconz.utils.URL_DISCOVER,
@ -258,7 +258,7 @@ async def test_manual_configuration_update_configuration(hass, aioclient_mock):
async def test_manual_configuration_dont_update_configuration(hass, aioclient_mock):
"""Test that _create_entry work and that bridgeid can be requested."""
await setup_deconz_integration(hass)
await setup_deconz_integration(hass, aioclient_mock)
aioclient_mock.get(
pydeconz.utils.URL_DISCOVER,
@ -374,7 +374,7 @@ async def test_link_get_api_key_ResponseError(hass, aioclient_mock):
async def test_reauth_flow_update_configuration(hass, aioclient_mock):
"""Verify reauth flow can update gateway API key."""
config_entry = await setup_deconz_integration(hass)
config_entry = await setup_deconz_integration(hass, aioclient_mock)
result = await hass.config_entries.flow.async_init(
DECONZ_DOMAIN,
@ -442,9 +442,9 @@ async def test_flow_ssdp_discovery(hass, aioclient_mock):
}
async def test_ssdp_discovery_update_configuration(hass):
async def test_ssdp_discovery_update_configuration(hass, aioclient_mock):
"""Test if a discovered bridge is configured but updates with new attributes."""
config_entry = await setup_deconz_integration(hass)
config_entry = await setup_deconz_integration(hass, aioclient_mock)
with patch(
"homeassistant.components.deconz.async_setup_entry",
@ -467,9 +467,9 @@ async def test_ssdp_discovery_update_configuration(hass):
assert len(mock_setup_entry.mock_calls) == 1
async def test_ssdp_discovery_dont_update_configuration(hass):
async def test_ssdp_discovery_dont_update_configuration(hass, aioclient_mock):
"""Test if a discovered bridge has already been configured."""
config_entry = await setup_deconz_integration(hass)
config_entry = await setup_deconz_integration(hass, aioclient_mock)
result = await hass.config_entries.flow.async_init(
DECONZ_DOMAIN,
@ -486,9 +486,13 @@ async def test_ssdp_discovery_dont_update_configuration(hass):
assert config_entry.data[CONF_HOST] == "1.2.3.4"
async def test_ssdp_discovery_dont_update_existing_hassio_configuration(hass):
async def test_ssdp_discovery_dont_update_existing_hassio_configuration(
hass, aioclient_mock
):
"""Test to ensure the SSDP discovery does not update an Hass.io entry."""
config_entry = await setup_deconz_integration(hass, source=SOURCE_HASSIO)
config_entry = await setup_deconz_integration(
hass, aioclient_mock, source=SOURCE_HASSIO
)
result = await hass.config_entries.flow.async_init(
DECONZ_DOMAIN,
@ -543,9 +547,9 @@ async def test_flow_hassio_discovery(hass):
assert len(mock_setup_entry.mock_calls) == 1
async def test_hassio_discovery_update_configuration(hass):
async def test_hassio_discovery_update_configuration(hass, aioclient_mock):
"""Test we can update an existing config entry."""
config_entry = await setup_deconz_integration(hass)
config_entry = await setup_deconz_integration(hass, aioclient_mock)
with patch(
"homeassistant.components.deconz.async_setup_entry",
@ -571,9 +575,9 @@ async def test_hassio_discovery_update_configuration(hass):
assert len(mock_setup_entry.mock_calls) == 1
async def test_hassio_discovery_dont_update_configuration(hass):
async def test_hassio_discovery_dont_update_configuration(hass, aioclient_mock):
"""Test we can update an existing config entry."""
await setup_deconz_integration(hass)
await setup_deconz_integration(hass, aioclient_mock)
result = await hass.config_entries.flow.async_init(
DECONZ_DOMAIN,
@ -590,9 +594,9 @@ async def test_hassio_discovery_dont_update_configuration(hass):
assert result["reason"] == "already_configured"
async def test_option_flow(hass):
async def test_option_flow(hass, aioclient_mock):
"""Test config flow options."""
config_entry = await setup_deconz_integration(hass)
config_entry = await setup_deconz_integration(hass, aioclient_mock)
result = await hass.config_entries.options.async_init(config_entry.entry_id)

View File

@ -1,7 +1,6 @@
"""deCONZ cover platform tests."""
from copy import deepcopy
from unittest.mock import patch
from homeassistant.components.cover import (
ATTR_CURRENT_TILT_POSITION,
@ -17,7 +16,6 @@ from homeassistant.components.cover import (
SERVICE_STOP_COVER,
SERVICE_STOP_COVER_TILT,
)
from homeassistant.components.deconz.const import DOMAIN as DECONZ_DOMAIN
from homeassistant.components.deconz.gateway import get_gateway_from_config_entry
from homeassistant.const import (
ATTR_ENTITY_ID,
@ -25,9 +23,12 @@ from homeassistant.const import (
STATE_OPEN,
STATE_UNAVAILABLE,
)
from homeassistant.setup import async_setup_component
from .test_gateway import DECONZ_WEB_REQUEST, setup_deconz_integration
from .test_gateway import (
DECONZ_WEB_REQUEST,
mock_deconz_put_request,
setup_deconz_integration,
)
COVERS = {
"1": {
@ -72,28 +73,19 @@ COVERS = {
}
async def test_platform_manually_configured(hass):
"""Test that we do not discover anything or try to set up a gateway."""
assert (
await async_setup_component(
hass, COVER_DOMAIN, {"cover": {"platform": DECONZ_DOMAIN}}
)
is True
)
assert DECONZ_DOMAIN not in hass.data
async def test_no_covers(hass):
async def test_no_covers(hass, aioclient_mock):
"""Test that no cover entities are created."""
await setup_deconz_integration(hass)
await setup_deconz_integration(hass, aioclient_mock)
assert len(hass.states.async_all()) == 0
async def test_cover(hass):
async def test_cover(hass, aioclient_mock):
"""Test that all supported cover entities are created."""
data = deepcopy(DECONZ_WEB_REQUEST)
data["lights"] = deepcopy(COVERS)
config_entry = await setup_deconz_integration(hass, get_state_response=data)
config_entry = await setup_deconz_integration(
hass, aioclient_mock, get_state_response=data
)
gateway = get_gateway_from_config_entry(hass, config_entry)
assert len(hass.states.async_all()) == 5
@ -119,123 +111,91 @@ async def test_cover(hass):
# Verify service calls for cover
windows_covering_device = gateway.api.lights["2"]
mock_deconz_put_request(aioclient_mock, config_entry.data, "/lights/2/state")
# Service open cover
with patch.object(
windows_covering_device, "_request", return_value=True
) as set_callback:
await hass.services.async_call(
COVER_DOMAIN,
SERVICE_OPEN_COVER,
{ATTR_ENTITY_ID: "cover.window_covering_device"},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with("put", "/lights/2/state", json={"open": True})
await hass.services.async_call(
COVER_DOMAIN,
SERVICE_OPEN_COVER,
{ATTR_ENTITY_ID: "cover.window_covering_device"},
blocking=True,
)
assert aioclient_mock.mock_calls[1][2] == {"open": True}
# Service close cover
with patch.object(
windows_covering_device, "_request", return_value=True
) as set_callback:
await hass.services.async_call(
COVER_DOMAIN,
SERVICE_CLOSE_COVER,
{ATTR_ENTITY_ID: "cover.window_covering_device"},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with("put", "/lights/2/state", json={"open": False})
await hass.services.async_call(
COVER_DOMAIN,
SERVICE_CLOSE_COVER,
{ATTR_ENTITY_ID: "cover.window_covering_device"},
blocking=True,
)
assert aioclient_mock.mock_calls[2][2] == {"open": False}
# Service set cover position
with patch.object(
windows_covering_device, "_request", return_value=True
) as set_callback:
await hass.services.async_call(
COVER_DOMAIN,
SERVICE_SET_COVER_POSITION,
{ATTR_ENTITY_ID: "cover.window_covering_device", ATTR_POSITION: 40},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with("put", "/lights/2/state", json={"lift": 60})
await hass.services.async_call(
COVER_DOMAIN,
SERVICE_SET_COVER_POSITION,
{ATTR_ENTITY_ID: "cover.window_covering_device", ATTR_POSITION: 40},
blocking=True,
)
assert aioclient_mock.mock_calls[3][2] == {"lift": 60}
# Service stop cover movement
with patch.object(
windows_covering_device, "_request", return_value=True
) as set_callback:
await hass.services.async_call(
COVER_DOMAIN,
SERVICE_STOP_COVER,
{ATTR_ENTITY_ID: "cover.window_covering_device"},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with("put", "/lights/2/state", json={"stop": True})
await hass.services.async_call(
COVER_DOMAIN,
SERVICE_STOP_COVER,
{ATTR_ENTITY_ID: "cover.window_covering_device"},
blocking=True,
)
assert aioclient_mock.mock_calls[4][2] == {"stop": True}
# Verify service calls for legacy cover
level_controllable_cover_device = gateway.api.lights["1"]
mock_deconz_put_request(aioclient_mock, config_entry.data, "/lights/1/state")
# Service open cover
with patch.object(
level_controllable_cover_device, "_request", return_value=True
) as set_callback:
await hass.services.async_call(
COVER_DOMAIN,
SERVICE_OPEN_COVER,
{ATTR_ENTITY_ID: "cover.level_controllable_cover"},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with("put", "/lights/1/state", json={"on": False})
await hass.services.async_call(
COVER_DOMAIN,
SERVICE_OPEN_COVER,
{ATTR_ENTITY_ID: "cover.level_controllable_cover"},
blocking=True,
)
assert aioclient_mock.mock_calls[5][2] == {"on": False}
# Service close cover
with patch.object(
level_controllable_cover_device, "_request", return_value=True
) as set_callback:
await hass.services.async_call(
COVER_DOMAIN,
SERVICE_CLOSE_COVER,
{ATTR_ENTITY_ID: "cover.level_controllable_cover"},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with("put", "/lights/1/state", json={"on": True})
await hass.services.async_call(
COVER_DOMAIN,
SERVICE_CLOSE_COVER,
{ATTR_ENTITY_ID: "cover.level_controllable_cover"},
blocking=True,
)
assert aioclient_mock.mock_calls[6][2] == {"on": True}
# Service set cover position
with patch.object(
level_controllable_cover_device, "_request", return_value=True
) as set_callback:
await hass.services.async_call(
COVER_DOMAIN,
SERVICE_SET_COVER_POSITION,
{ATTR_ENTITY_ID: "cover.level_controllable_cover", ATTR_POSITION: 40},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with("put", "/lights/1/state", json={"bri": 152})
await hass.services.async_call(
COVER_DOMAIN,
SERVICE_SET_COVER_POSITION,
{ATTR_ENTITY_ID: "cover.level_controllable_cover", ATTR_POSITION: 40},
blocking=True,
)
assert aioclient_mock.mock_calls[7][2] == {"bri": 152}
# Service stop cover movement
with patch.object(
level_controllable_cover_device, "_request", return_value=True
) as set_callback:
await hass.services.async_call(
COVER_DOMAIN,
SERVICE_STOP_COVER,
{ATTR_ENTITY_ID: "cover.level_controllable_cover"},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with("put", "/lights/1/state", json={"bri_inc": 0})
await hass.services.async_call(
COVER_DOMAIN,
SERVICE_STOP_COVER,
{ATTR_ENTITY_ID: "cover.level_controllable_cover"},
blocking=True,
)
assert aioclient_mock.mock_calls[8][2] == {"bri_inc": 0}
# Test that a reported cover position of 255 (deconz-rest-api < 2.05.73) is interpreted correctly.
assert hass.states.get("cover.deconz_old_brightness_cover").state == STATE_OPEN
@ -266,7 +226,7 @@ async def test_cover(hass):
assert len(hass.states.async_all()) == 0
async def test_tilt_cover(hass):
async def test_tilt_cover(hass, aioclient_mock):
"""Test that tilting a cover works."""
data = deepcopy(DECONZ_WEB_REQUEST)
data["lights"] = {
@ -290,54 +250,55 @@ async def test_tilt_cover(hass):
"uniqueid": "00:24:46:00:00:12:34:56-01",
}
}
config_entry = await setup_deconz_integration(hass, get_state_response=data)
gateway = get_gateway_from_config_entry(hass, config_entry)
config_entry = await setup_deconz_integration(
hass, aioclient_mock, get_state_response=data
)
assert len(hass.states.async_all()) == 1
entity = hass.states.get("cover.covering_device")
assert entity.state == STATE_OPEN
assert entity.attributes[ATTR_CURRENT_TILT_POSITION] == 100
covering_device = gateway.api.lights["0"]
# Verify service calls for tilting cover
with patch.object(covering_device, "_request", return_value=True) as set_callback:
await hass.services.async_call(
COVER_DOMAIN,
SERVICE_SET_COVER_TILT_POSITION,
{ATTR_ENTITY_ID: "cover.covering_device", ATTR_TILT_POSITION: 40},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with("put", "/lights/0/state", json={"tilt": 60})
mock_deconz_put_request(aioclient_mock, config_entry.data, "/lights/0/state")
with patch.object(covering_device, "_request", return_value=True) as set_callback:
await hass.services.async_call(
COVER_DOMAIN,
SERVICE_OPEN_COVER_TILT,
{ATTR_ENTITY_ID: "cover.covering_device"},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with("put", "/lights/0/state", json={"tilt": 0})
# Service set tilt cover
with patch.object(covering_device, "_request", return_value=True) as set_callback:
await hass.services.async_call(
COVER_DOMAIN,
SERVICE_CLOSE_COVER_TILT,
{ATTR_ENTITY_ID: "cover.covering_device"},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with("put", "/lights/0/state", json={"tilt": 100})
await hass.services.async_call(
COVER_DOMAIN,
SERVICE_SET_COVER_TILT_POSITION,
{ATTR_ENTITY_ID: "cover.covering_device", ATTR_TILT_POSITION: 40},
blocking=True,
)
assert aioclient_mock.mock_calls[1][2] == {"tilt": 60}
# Service open tilt cover
await hass.services.async_call(
COVER_DOMAIN,
SERVICE_OPEN_COVER_TILT,
{ATTR_ENTITY_ID: "cover.covering_device"},
blocking=True,
)
assert aioclient_mock.mock_calls[2][2] == {"tilt": 0}
# Service close tilt cover
await hass.services.async_call(
COVER_DOMAIN,
SERVICE_CLOSE_COVER_TILT,
{ATTR_ENTITY_ID: "cover.covering_device"},
blocking=True,
)
assert aioclient_mock.mock_calls[3][2] == {"tilt": 100}
# Service stop cover movement
with patch.object(covering_device, "_request", return_value=True) as set_callback:
await hass.services.async_call(
COVER_DOMAIN,
SERVICE_STOP_COVER_TILT,
{ATTR_ENTITY_ID: "cover.covering_device"},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with("put", "/lights/0/state", json={"stop": True})
await hass.services.async_call(
COVER_DOMAIN,
SERVICE_STOP_COVER_TILT,
{ATTR_ENTITY_ID: "cover.covering_device"},
blocking=True,
)
assert aioclient_mock.mock_calls[4][2] == {"stop": True}

View File

@ -54,11 +54,13 @@ SENSORS = {
}
async def test_deconz_events(hass):
async def test_deconz_events(hass, aioclient_mock):
"""Test successful creation of deconz events."""
data = deepcopy(DECONZ_WEB_REQUEST)
data["sensors"] = deepcopy(SENSORS)
config_entry = await setup_deconz_integration(hass, get_state_response=data)
config_entry = await setup_deconz_integration(
hass, aioclient_mock, get_state_response=data
)
gateway = get_gateway_from_config_entry(hass, config_entry)
assert len(hass.states.async_all()) == 3

View File

@ -44,11 +44,13 @@ SENSORS = {
}
async def test_get_triggers(hass):
async def test_get_triggers(hass, aioclient_mock):
"""Test triggers work."""
data = deepcopy(DECONZ_WEB_REQUEST)
data["sensors"] = deepcopy(SENSORS)
config_entry = await setup_deconz_integration(hass, get_state_response=data)
config_entry = await setup_deconz_integration(
hass, aioclient_mock, get_state_response=data
)
gateway = get_gateway_from_config_entry(hass, config_entry)
device_id = gateway.events[0].device_id
triggers = await async_get_device_automations(hass, "trigger", device_id)
@ -108,20 +110,22 @@ async def test_get_triggers(hass):
assert_lists_same(triggers, expected_triggers)
async def test_helper_successful(hass):
async def test_helper_successful(hass, aioclient_mock):
"""Verify trigger helper."""
data = deepcopy(DECONZ_WEB_REQUEST)
data["sensors"] = deepcopy(SENSORS)
config_entry = await setup_deconz_integration(hass, get_state_response=data)
config_entry = await setup_deconz_integration(
hass, aioclient_mock, get_state_response=data
)
gateway = get_gateway_from_config_entry(hass, config_entry)
device_id = gateway.events[0].device_id
deconz_event = device_trigger._get_deconz_event_from_device_id(hass, device_id)
assert deconz_event == gateway.events[0]
async def test_helper_no_match(hass):
async def test_helper_no_match(hass, aioclient_mock):
"""Verify trigger helper returns None when no event could be matched."""
await setup_deconz_integration(hass)
await setup_deconz_integration(hass, aioclient_mock)
deconz_event = device_trigger._get_deconz_event_from_device_id(hass, "mock-id")
assert deconz_event is None

View File

@ -1,11 +1,9 @@
"""deCONZ fan platform tests."""
from copy import deepcopy
from unittest.mock import patch
import pytest
from homeassistant.components.deconz.const import DOMAIN as DECONZ_DOMAIN
from homeassistant.components.deconz.gateway import get_gateway_from_config_entry
from homeassistant.components.fan import (
ATTR_SPEED,
@ -19,9 +17,12 @@ from homeassistant.components.fan import (
SPEED_OFF,
)
from homeassistant.const import ATTR_ENTITY_ID, STATE_OFF, STATE_ON, STATE_UNAVAILABLE
from homeassistant.setup import async_setup_component
from .test_gateway import DECONZ_WEB_REQUEST, setup_deconz_integration
from .test_gateway import (
DECONZ_WEB_REQUEST,
mock_deconz_put_request,
setup_deconz_integration,
)
FANS = {
"1": {
@ -44,28 +45,19 @@ FANS = {
}
async def test_platform_manually_configured(hass):
"""Test that we do not discover anything or try to set up a gateway."""
assert (
await async_setup_component(
hass, FAN_DOMAIN, {"fan": {"platform": DECONZ_DOMAIN}}
)
is True
)
assert DECONZ_DOMAIN not in hass.data
async def test_no_fans(hass):
async def test_no_fans(hass, aioclient_mock):
"""Test that no fan entities are created."""
await setup_deconz_integration(hass)
await setup_deconz_integration(hass, aioclient_mock)
assert len(hass.states.async_all()) == 0
async def test_fans(hass):
async def test_fans(hass, aioclient_mock):
"""Test that all supported fan entities are created."""
data = deepcopy(DECONZ_WEB_REQUEST)
data["lights"] = deepcopy(FANS)
config_entry = await setup_deconz_integration(hass, get_state_response=data)
config_entry = await setup_deconz_integration(
hass, aioclient_mock, get_state_response=data
)
gateway = get_gateway_from_config_entry(hass, config_entry)
assert len(hass.states.async_all()) == 2 # Light and fan
@ -91,104 +83,77 @@ async def test_fans(hass):
# Test service calls
ceiling_fan_device = gateway.api.lights["1"]
mock_deconz_put_request(aioclient_mock, config_entry.data, "/lights/1/state")
# Service turn on fan
with patch.object(
ceiling_fan_device, "_request", return_value=True
) as set_callback:
await hass.services.async_call(
FAN_DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: "fan.ceiling_fan"},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with("put", "/lights/1/state", json={"speed": 4})
await hass.services.async_call(
FAN_DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: "fan.ceiling_fan"},
blocking=True,
)
assert aioclient_mock.mock_calls[1][2] == {"speed": 4}
# Service turn off fan
with patch.object(
ceiling_fan_device, "_request", return_value=True
) as set_callback:
await hass.services.async_call(
FAN_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: "fan.ceiling_fan"},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with("put", "/lights/1/state", json={"speed": 0})
await hass.services.async_call(
FAN_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: "fan.ceiling_fan"},
blocking=True,
)
assert aioclient_mock.mock_calls[2][2] == {"speed": 0}
# Service set fan speed to low
with patch.object(
ceiling_fan_device, "_request", return_value=True
) as set_callback:
await hass.services.async_call(
FAN_DOMAIN,
SERVICE_SET_SPEED,
{ATTR_ENTITY_ID: "fan.ceiling_fan", ATTR_SPEED: SPEED_LOW},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with("put", "/lights/1/state", json={"speed": 1})
await hass.services.async_call(
FAN_DOMAIN,
SERVICE_SET_SPEED,
{ATTR_ENTITY_ID: "fan.ceiling_fan", ATTR_SPEED: SPEED_LOW},
blocking=True,
)
assert aioclient_mock.mock_calls[3][2] == {"speed": 1}
# Service set fan speed to medium
with patch.object(
ceiling_fan_device, "_request", return_value=True
) as set_callback:
await hass.services.async_call(
FAN_DOMAIN,
SERVICE_SET_SPEED,
{ATTR_ENTITY_ID: "fan.ceiling_fan", ATTR_SPEED: SPEED_MEDIUM},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with("put", "/lights/1/state", json={"speed": 2})
await hass.services.async_call(
FAN_DOMAIN,
SERVICE_SET_SPEED,
{ATTR_ENTITY_ID: "fan.ceiling_fan", ATTR_SPEED: SPEED_MEDIUM},
blocking=True,
)
assert aioclient_mock.mock_calls[4][2] == {"speed": 2}
# Service set fan speed to high
with patch.object(
ceiling_fan_device, "_request", return_value=True
) as set_callback:
await hass.services.async_call(
FAN_DOMAIN,
SERVICE_SET_SPEED,
{ATTR_ENTITY_ID: "fan.ceiling_fan", ATTR_SPEED: SPEED_HIGH},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with("put", "/lights/1/state", json={"speed": 4})
await hass.services.async_call(
FAN_DOMAIN,
SERVICE_SET_SPEED,
{ATTR_ENTITY_ID: "fan.ceiling_fan", ATTR_SPEED: SPEED_HIGH},
blocking=True,
)
assert aioclient_mock.mock_calls[5][2] == {"speed": 4}
# Service set fan speed to off
with patch.object(
ceiling_fan_device, "_request", return_value=True
) as set_callback:
await hass.services.async_call(
FAN_DOMAIN,
SERVICE_SET_SPEED,
{ATTR_ENTITY_ID: "fan.ceiling_fan", ATTR_SPEED: SPEED_OFF},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with("put", "/lights/1/state", json={"speed": 0})
await hass.services.async_call(
FAN_DOMAIN,
SERVICE_SET_SPEED,
{ATTR_ENTITY_ID: "fan.ceiling_fan", ATTR_SPEED: SPEED_OFF},
blocking=True,
)
assert aioclient_mock.mock_calls[6][2] == {"speed": 0}
# Service set fan speed to unsupported value
with patch.object(
ceiling_fan_device, "_request", return_value=True
) as set_callback, pytest.raises(ValueError):
with pytest.raises(ValueError):
await hass.services.async_call(
FAN_DOMAIN,
SERVICE_SET_SPEED,
{ATTR_ENTITY_ID: "fan.ceiling_fan", ATTR_SPEED: "bad value"},
blocking=True,
)
await hass.async_block_till_done()
# Events with an unsupported speed gets converted to default speed "medium"

View File

@ -29,21 +29,25 @@ from homeassistant.components.ssdp import (
)
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
from homeassistant.config_entries import CONN_CLASS_LOCAL_PUSH, SOURCE_SSDP
from homeassistant.const import CONF_API_KEY, CONF_HOST, CONF_PORT
from homeassistant.const import CONF_API_KEY, CONF_HOST, CONF_PORT, CONTENT_TYPE_JSON
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from tests.common import MockConfigEntry
API_KEY = "1234567890ABCDEF"
BRIDGEID = "01234E56789A"
HOST = "1.2.3.4"
PORT = 80
ENTRY_CONFIG = {CONF_API_KEY: API_KEY, CONF_HOST: "1.2.3.4", CONF_PORT: 80}
DEFAULT_URL = f"http://{HOST}:{PORT}/api/{API_KEY}"
ENTRY_CONFIG = {CONF_API_KEY: API_KEY, CONF_HOST: HOST, CONF_PORT: PORT}
ENTRY_OPTIONS = {}
DECONZ_CONFIG = {
"bridgeid": BRIDGEID,
"ipaddress": "1.2.3.4",
"ipaddress": HOST,
"mac": "00:11:22:33:44:55",
"modelid": "deCONZ",
"name": "deCONZ mock gateway",
@ -60,8 +64,36 @@ DECONZ_WEB_REQUEST = {
}
def mock_deconz_request(aioclient_mock, config, data):
"""Mock a deCONZ get request."""
host = config[CONF_HOST]
port = config[CONF_PORT]
api_key = config[CONF_API_KEY]
aioclient_mock.get(
f"http://{host}:{port}/api/{api_key}",
json=deepcopy(data),
headers={"content-type": CONTENT_TYPE_JSON},
)
def mock_deconz_put_request(aioclient_mock, config, path):
"""Mock a deCONZ put request."""
host = config[CONF_HOST]
port = config[CONF_PORT]
api_key = config[CONF_API_KEY]
aioclient_mock.put(
f"http://{host}:{port}/api/{api_key}{path}",
json={},
headers={"content-type": CONTENT_TYPE_JSON},
)
async def setup_deconz_integration(
hass,
aioclient_mock=None,
*,
config=ENTRY_CONFIG,
options=ENTRY_OPTIONS,
get_state_response=DECONZ_WEB_REQUEST,
@ -81,22 +113,23 @@ async def setup_deconz_integration(
)
config_entry.add_to_hass(hass)
with patch(
"pydeconz.DeconzSession.request", return_value=deepcopy(get_state_response)
), patch("pydeconz.DeconzSession.start", return_value=True):
if aioclient_mock:
mock_deconz_request(aioclient_mock, config, get_state_response)
with patch("pydeconz.DeconzSession.start", return_value=True):
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
return config_entry
async def test_gateway_setup(hass):
async def test_gateway_setup(hass, aioclient_mock):
"""Successful setup."""
with patch(
"homeassistant.config_entries.ConfigEntries.async_forward_entry_setup",
return_value=True,
) as forward_entry_setup:
config_entry = await setup_deconz_integration(hass)
config_entry = await setup_deconz_integration(hass, aioclient_mock)
gateway = get_gateway_from_config_entry(hass, config_entry)
assert gateway.bridgeid == BRIDGEID
assert gateway.master is True
@ -140,9 +173,9 @@ async def test_gateway_setup_fails(hass):
assert not hass.data[DECONZ_DOMAIN]
async def test_connection_status_signalling(hass):
async def test_connection_status_signalling(hass, aioclient_mock):
"""Make sure that connection status triggers a dispatcher send."""
config_entry = await setup_deconz_integration(hass)
config_entry = await setup_deconz_integration(hass, aioclient_mock)
gateway = get_gateway_from_config_entry(hass, config_entry)
event_call = Mock()
@ -157,9 +190,9 @@ async def test_connection_status_signalling(hass):
unsub()
async def test_update_address(hass):
async def test_update_address(hass, aioclient_mock):
"""Make sure that connection status triggers a dispatcher send."""
config_entry = await setup_deconz_integration(hass)
config_entry = await setup_deconz_integration(hass, aioclient_mock)
gateway = get_gateway_from_config_entry(hass, config_entry)
assert gateway.api.host == "1.2.3.4"
@ -195,9 +228,9 @@ async def test_gateway_trigger_reauth_flow(hass):
assert hass.data[DECONZ_DOMAIN] == {}
async def test_reset_after_successful_setup(hass):
async def test_reset_after_successful_setup(hass, aioclient_mock):
"""Make sure that connection status triggers a dispatcher send."""
config_entry = await setup_deconz_integration(hass)
config_entry = await setup_deconz_integration(hass, aioclient_mock)
gateway = get_gateway_from_config_entry(hass, config_entry)
result = await gateway.async_reset()

View File

@ -14,7 +14,6 @@ from homeassistant.components.deconz.const import (
CONF_GROUP_ID_BASE,
DOMAIN as DECONZ_DOMAIN,
)
from homeassistant.components.deconz.gateway import get_gateway_from_config_entry
from homeassistant.components.light import DOMAIN as LIGHT_DOMAIN
from homeassistant.const import CONF_API_KEY, CONF_HOST, CONF_PORT
from homeassistant.helpers import entity_registry
@ -58,59 +57,65 @@ async def test_setup_entry_no_available_bridge(hass):
assert not hass.data[DECONZ_DOMAIN]
async def test_setup_entry_successful(hass):
async def test_setup_entry_successful(hass, aioclient_mock):
"""Test setup entry is successful."""
config_entry = await setup_deconz_integration(hass)
gateway = get_gateway_from_config_entry(hass, config_entry)
config_entry = await setup_deconz_integration(hass, aioclient_mock)
assert hass.data[DECONZ_DOMAIN]
assert gateway.bridgeid in hass.data[DECONZ_DOMAIN]
assert hass.data[DECONZ_DOMAIN][gateway.bridgeid].master
assert config_entry.unique_id in hass.data[DECONZ_DOMAIN]
assert hass.data[DECONZ_DOMAIN][config_entry.unique_id].master
async def test_setup_entry_multiple_gateways(hass):
async def test_setup_entry_multiple_gateways(hass, aioclient_mock):
"""Test setup entry is successful with multiple gateways."""
config_entry = await setup_deconz_integration(hass)
gateway = get_gateway_from_config_entry(hass, config_entry)
config_entry = await setup_deconz_integration(hass, aioclient_mock)
aioclient_mock.clear_requests()
data = deepcopy(DECONZ_WEB_REQUEST)
data["config"]["bridgeid"] = "01234E56789B"
config_entry2 = await setup_deconz_integration(
hass, get_state_response=data, entry_id="2", unique_id="01234E56789B"
hass,
aioclient_mock,
get_state_response=data,
entry_id="2",
unique_id="01234E56789B",
)
gateway2 = get_gateway_from_config_entry(hass, config_entry2)
assert len(hass.data[DECONZ_DOMAIN]) == 2
assert hass.data[DECONZ_DOMAIN][gateway.bridgeid].master
assert not hass.data[DECONZ_DOMAIN][gateway2.bridgeid].master
assert hass.data[DECONZ_DOMAIN][config_entry.unique_id].master
assert not hass.data[DECONZ_DOMAIN][config_entry2.unique_id].master
async def test_unload_entry(hass):
async def test_unload_entry(hass, aioclient_mock):
"""Test being able to unload an entry."""
config_entry = await setup_deconz_integration(hass)
config_entry = await setup_deconz_integration(hass, aioclient_mock)
assert hass.data[DECONZ_DOMAIN]
assert await async_unload_entry(hass, config_entry)
assert not hass.data[DECONZ_DOMAIN]
async def test_unload_entry_multiple_gateways(hass):
async def test_unload_entry_multiple_gateways(hass, aioclient_mock):
"""Test being able to unload an entry and master gateway gets moved."""
config_entry = await setup_deconz_integration(hass)
config_entry = await setup_deconz_integration(hass, aioclient_mock)
aioclient_mock.clear_requests()
data = deepcopy(DECONZ_WEB_REQUEST)
data["config"]["bridgeid"] = "01234E56789B"
config_entry2 = await setup_deconz_integration(
hass, get_state_response=data, entry_id="2", unique_id="01234E56789B"
hass,
aioclient_mock,
get_state_response=data,
entry_id="2",
unique_id="01234E56789B",
)
gateway2 = get_gateway_from_config_entry(hass, config_entry2)
assert len(hass.data[DECONZ_DOMAIN]) == 2
assert await async_unload_entry(hass, config_entry)
assert len(hass.data[DECONZ_DOMAIN]) == 1
assert hass.data[DECONZ_DOMAIN][gateway2.bridgeid].master
assert hass.data[DECONZ_DOMAIN][config_entry2.unique_id].master
async def test_update_group_unique_id(hass):

View File

@ -1,14 +1,10 @@
"""deCONZ light platform tests."""
from copy import deepcopy
from unittest.mock import patch
import pytest
from homeassistant.components.deconz.const import (
CONF_ALLOW_DECONZ_GROUPS,
DOMAIN as DECONZ_DOMAIN,
)
from homeassistant.components.deconz.const import CONF_ALLOW_DECONZ_GROUPS
from homeassistant.components.deconz.gateway import get_gateway_from_config_entry
from homeassistant.components.light import (
ATTR_BRIGHTNESS,
@ -33,9 +29,12 @@ from homeassistant.const import (
STATE_ON,
STATE_UNAVAILABLE,
)
from homeassistant.setup import async_setup_component
from .test_gateway import DECONZ_WEB_REQUEST, setup_deconz_integration
from .test_gateway import (
DECONZ_WEB_REQUEST,
mock_deconz_put_request,
setup_deconz_integration,
)
GROUPS = {
"1": {
@ -107,29 +106,20 @@ LIGHTS = {
}
async def test_platform_manually_configured(hass):
"""Test that we do not discover anything or try to set up a gateway."""
assert (
await async_setup_component(
hass, LIGHT_DOMAIN, {"light": {"platform": DECONZ_DOMAIN}}
)
is True
)
assert DECONZ_DOMAIN not in hass.data
async def test_no_lights_or_groups(hass):
async def test_no_lights_or_groups(hass, aioclient_mock):
"""Test that no lights or groups entities are created."""
await setup_deconz_integration(hass)
await setup_deconz_integration(hass, aioclient_mock)
assert len(hass.states.async_all()) == 0
async def test_lights_and_groups(hass):
async def test_lights_and_groups(hass, aioclient_mock):
"""Test that lights or groups entities are created."""
data = deepcopy(DECONZ_WEB_REQUEST)
data["groups"] = deepcopy(GROUPS)
data["lights"] = deepcopy(LIGHTS)
config_entry = await setup_deconz_integration(hass, get_state_response=data)
config_entry = await setup_deconz_integration(
hass, aioclient_mock, get_state_response=data
)
gateway = get_gateway_from_config_entry(hass, config_entry)
assert len(hass.states.async_all()) == 6
@ -183,73 +173,63 @@ async def test_lights_and_groups(hass):
# Verify service calls
rgb_light_device = gateway.api.lights["1"]
mock_deconz_put_request(aioclient_mock, config_entry.data, "/lights/1/state")
# Service turn on light with short color loop
with patch.object(rgb_light_device, "_request", return_value=True) as set_callback:
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_ON,
{
ATTR_ENTITY_ID: "light.rgb_light",
ATTR_COLOR_TEMP: 2500,
ATTR_BRIGHTNESS: 200,
ATTR_TRANSITION: 5,
ATTR_FLASH: FLASH_SHORT,
ATTR_EFFECT: EFFECT_COLORLOOP,
},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with(
"put",
"/lights/1/state",
json={
"ct": 2500,
"bri": 200,
"transitiontime": 50,
"alert": "select",
"effect": "colorloop",
},
)
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_ON,
{
ATTR_ENTITY_ID: "light.rgb_light",
ATTR_COLOR_TEMP: 2500,
ATTR_BRIGHTNESS: 200,
ATTR_TRANSITION: 5,
ATTR_FLASH: FLASH_SHORT,
ATTR_EFFECT: EFFECT_COLORLOOP,
},
blocking=True,
)
assert aioclient_mock.mock_calls[1][2] == {
"ct": 2500,
"bri": 200,
"transitiontime": 50,
"alert": "select",
"effect": "colorloop",
}
# Service turn on light disabling color loop with long flashing
with patch.object(rgb_light_device, "_request", return_value=True) as set_callback:
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_ON,
{
ATTR_ENTITY_ID: "light.rgb_light",
ATTR_HS_COLOR: (20, 30),
ATTR_FLASH: FLASH_LONG,
ATTR_EFFECT: "None",
},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with(
"put",
"/lights/1/state",
json={"xy": (0.411, 0.351), "alert": "lselect", "effect": "none"},
)
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_ON,
{
ATTR_ENTITY_ID: "light.rgb_light",
ATTR_HS_COLOR: (20, 30),
ATTR_FLASH: FLASH_LONG,
ATTR_EFFECT: "None",
},
blocking=True,
)
assert aioclient_mock.mock_calls[2][2] == {
"xy": (0.411, 0.351),
"alert": "lselect",
"effect": "none",
}
# Service turn on light with short flashing
# Service turn on light with short flashing not supported
with patch.object(rgb_light_device, "_request", return_value=True) as set_callback:
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_OFF,
{
ATTR_ENTITY_ID: "light.rgb_light",
ATTR_TRANSITION: 5,
ATTR_FLASH: FLASH_SHORT,
},
blocking=True,
)
await hass.async_block_till_done()
assert not set_callback.called
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_OFF,
{
ATTR_ENTITY_ID: "light.rgb_light",
ATTR_TRANSITION: 5,
ATTR_FLASH: FLASH_SHORT,
},
blocking=True,
)
assert len(aioclient_mock.mock_calls) == 3 # Not called
state_changed_event = {
"t": "event",
@ -263,37 +243,31 @@ async def test_lights_and_groups(hass):
# Service turn off light with short flashing
with patch.object(rgb_light_device, "_request", return_value=True) as set_callback:
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_OFF,
{
ATTR_ENTITY_ID: "light.rgb_light",
ATTR_TRANSITION: 5,
ATTR_FLASH: FLASH_SHORT,
},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with(
"put",
"/lights/1/state",
json={"bri": 0, "transitiontime": 50, "alert": "select"},
)
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_OFF,
{
ATTR_ENTITY_ID: "light.rgb_light",
ATTR_TRANSITION: 5,
ATTR_FLASH: FLASH_SHORT,
},
blocking=True,
)
assert aioclient_mock.mock_calls[3][2] == {
"bri": 0,
"transitiontime": 50,
"alert": "select",
}
# Service turn off light with long flashing
with patch.object(rgb_light_device, "_request", return_value=True) as set_callback:
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: "light.rgb_light", ATTR_FLASH: FLASH_LONG},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with(
"put", "/lights/1/state", json={"alert": "lselect"}
)
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: "light.rgb_light", ATTR_FLASH: FLASH_LONG},
blocking=True,
)
assert aioclient_mock.mock_calls[4][2] == {"alert": "lselect"}
await hass.config_entries.async_unload(config_entry.entry_id)
@ -307,13 +281,14 @@ async def test_lights_and_groups(hass):
assert len(hass.states.async_all()) == 0
async def test_disable_light_groups(hass):
async def test_disable_light_groups(hass, aioclient_mock):
"""Test disallowing light groups work."""
data = deepcopy(DECONZ_WEB_REQUEST)
data["groups"] = deepcopy(GROUPS)
data["lights"] = deepcopy(LIGHTS)
config_entry = await setup_deconz_integration(
hass,
aioclient_mock,
options={CONF_ALLOW_DECONZ_GROUPS: False},
get_state_response=data,
)
@ -341,7 +316,7 @@ async def test_disable_light_groups(hass):
assert hass.states.get("light.light_group") is None
async def test_configuration_tool(hass):
async def test_configuration_tool(hass, aioclient_mock):
"""Test that lights or groups entities are created."""
data = deepcopy(DECONZ_WEB_REQUEST)
data["lights"] = {
@ -359,12 +334,12 @@ async def test_configuration_tool(hass):
"uniqueid": "00:21:2e:ff:ff:05:a7:a3-01",
}
}
await setup_deconz_integration(hass, get_state_response=data)
await setup_deconz_integration(hass, aioclient_mock, get_state_response=data)
assert len(hass.states.async_all()) == 0
async def test_lidl_christmas_light(hass):
async def test_lidl_christmas_light(hass, aioclient_mock):
"""Test that lights or groups entities are created."""
data = deepcopy(DECONZ_WEB_REQUEST)
data["lights"] = {
@ -390,33 +365,27 @@ async def test_lidl_christmas_light(hass):
"uniqueid": "58:8e:81:ff:fe:db:7b:be-01",
}
}
config_entry = await setup_deconz_integration(hass, get_state_response=data)
gateway = get_gateway_from_config_entry(hass, config_entry)
xmas_light_device = gateway.api.lights["0"]
config_entry = await setup_deconz_integration(
hass, aioclient_mock, get_state_response=data
)
assert len(hass.states.async_all()) == 1
mock_deconz_put_request(aioclient_mock, config_entry.data, "/lights/0/state")
with patch.object(xmas_light_device, "_request", return_value=True) as set_callback:
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_ON,
{
ATTR_ENTITY_ID: "light.xmas_light",
ATTR_HS_COLOR: (20, 30),
},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with(
"put",
"/lights/0/state",
json={"on": True, "hue": 3640, "sat": 76},
)
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_ON,
{
ATTR_ENTITY_ID: "light.xmas_light",
ATTR_HS_COLOR: (20, 30),
},
blocking=True,
)
assert aioclient_mock.mock_calls[1][2] == {"on": True, "hue": 3640, "sat": 76}
assert hass.states.get("light.xmas_light")
async def test_non_color_light_reports_color(hass):
async def test_non_color_light_reports_color(hass, aioclient_mock):
"""Verify hs_color does not crash when a group gets updated with a bad color value.
After calling a scene color temp light of certain manufacturers
@ -500,7 +469,9 @@ async def test_non_color_light_reports_color(hass):
"uniqueid": "ec:1b:bd:ff:fe:ee:ed:dd-01",
},
}
config_entry = await setup_deconz_integration(hass, get_state_response=data)
config_entry = await setup_deconz_integration(
hass, aioclient_mock, get_state_response=data
)
gateway = get_gateway_from_config_entry(hass, config_entry)
assert len(hass.states.async_all()) == 3
@ -531,7 +502,7 @@ async def test_non_color_light_reports_color(hass):
assert hass.states.get("light.all").attributes[ATTR_HS_COLOR]
async def test_verify_group_supported_features(hass):
async def test_verify_group_supported_features(hass, aioclient_mock):
"""Test that group supported features reflect what included lights support."""
data = deepcopy(DECONZ_WEB_REQUEST)
data["groups"] = deepcopy(
@ -581,7 +552,7 @@ async def test_verify_group_supported_features(hass):
},
}
)
await setup_deconz_integration(hass, get_state_response=data)
await setup_deconz_integration(hass, aioclient_mock, get_state_response=data)
assert len(hass.states.async_all()) == 4

View File

@ -1,9 +1,7 @@
"""deCONZ lock platform tests."""
from copy import deepcopy
from unittest.mock import patch
from homeassistant.components.deconz.const import DOMAIN as DECONZ_DOMAIN
from homeassistant.components.deconz.gateway import get_gateway_from_config_entry
from homeassistant.components.lock import (
DOMAIN as LOCK_DOMAIN,
@ -16,9 +14,12 @@ from homeassistant.const import (
STATE_UNAVAILABLE,
STATE_UNLOCKED,
)
from homeassistant.setup import async_setup_component
from .test_gateway import DECONZ_WEB_REQUEST, setup_deconz_integration
from .test_gateway import (
DECONZ_WEB_REQUEST,
mock_deconz_put_request,
setup_deconz_integration,
)
LOCKS = {
"1": {
@ -37,28 +38,19 @@ LOCKS = {
}
async def test_platform_manually_configured(hass):
"""Test that we do not discover anything or try to set up a gateway."""
assert (
await async_setup_component(
hass, LOCK_DOMAIN, {"lock": {"platform": DECONZ_DOMAIN}}
)
is True
)
assert DECONZ_DOMAIN not in hass.data
async def test_no_locks(hass):
async def test_no_locks(hass, aioclient_mock):
"""Test that no lock entities are created."""
await setup_deconz_integration(hass)
await setup_deconz_integration(hass, aioclient_mock)
assert len(hass.states.async_all()) == 0
async def test_locks(hass):
async def test_locks(hass, aioclient_mock):
"""Test that all supported lock entities are created."""
data = deepcopy(DECONZ_WEB_REQUEST)
data["lights"] = deepcopy(LOCKS)
config_entry = await setup_deconz_integration(hass, get_state_response=data)
config_entry = await setup_deconz_integration(
hass, aioclient_mock, get_state_response=data
)
gateway = get_gateway_from_config_entry(hass, config_entry)
assert len(hass.states.async_all()) == 1
@ -81,31 +73,27 @@ async def test_locks(hass):
# Verify service calls
door_lock_device = gateway.api.lights["1"]
mock_deconz_put_request(aioclient_mock, config_entry.data, "/lights/1/state")
# Service lock door
with patch.object(door_lock_device, "_request", return_value=True) as set_callback:
await hass.services.async_call(
LOCK_DOMAIN,
SERVICE_LOCK,
{ATTR_ENTITY_ID: "lock.door_lock"},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with("put", "/lights/1/state", json={"on": True})
await hass.services.async_call(
LOCK_DOMAIN,
SERVICE_LOCK,
{ATTR_ENTITY_ID: "lock.door_lock"},
blocking=True,
)
assert aioclient_mock.mock_calls[1][2] == {"on": True}
# Service unlock door
with patch.object(door_lock_device, "_request", return_value=True) as set_callback:
await hass.services.async_call(
LOCK_DOMAIN,
SERVICE_UNLOCK,
{ATTR_ENTITY_ID: "lock.door_lock"},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with("put", "/lights/1/state", json={"on": False})
await hass.services.async_call(
LOCK_DOMAIN,
SERVICE_UNLOCK,
{ATTR_ENTITY_ID: "lock.door_lock"},
blocking=True,
)
assert aioclient_mock.mock_calls[2][2] == {"on": False}
await hass.config_entries.async_unload(config_entry.entry_id)

View File

@ -14,7 +14,7 @@ from .test_gateway import DECONZ_WEB_REQUEST, setup_deconz_integration
from tests.components.logbook.test_init import MockLazyEventPartialState
async def test_humanifying_deconz_event(hass):
async def test_humanifying_deconz_event(hass, aioclient_mock):
"""Test humanifying deCONZ event."""
data = deepcopy(DECONZ_WEB_REQUEST)
data["sensors"] = {
@ -53,7 +53,9 @@ async def test_humanifying_deconz_event(hass):
"uniqueid": "00:00:00:00:00:00:00:04-00",
},
}
config_entry = await setup_deconz_integration(hass, get_state_response=data)
config_entry = await setup_deconz_integration(
hass, aioclient_mock, get_state_response=data
)
gateway = get_gateway_from_config_entry(hass, config_entry)
hass.config.components.add("recorder")

View File

@ -1,15 +1,15 @@
"""deCONZ scene platform tests."""
from copy import deepcopy
from unittest.mock import patch
from homeassistant.components.deconz import DOMAIN as DECONZ_DOMAIN
from homeassistant.components.deconz.gateway import get_gateway_from_config_entry
from homeassistant.components.scene import DOMAIN as SCENE_DOMAIN, SERVICE_TURN_ON
from homeassistant.const import ATTR_ENTITY_ID
from homeassistant.setup import async_setup_component
from .test_gateway import DECONZ_WEB_REQUEST, setup_deconz_integration
from .test_gateway import (
DECONZ_WEB_REQUEST,
mock_deconz_put_request,
setup_deconz_integration,
)
GROUPS = {
"1": {
@ -24,48 +24,38 @@ GROUPS = {
}
async def test_platform_manually_configured(hass):
"""Test that we do not discover anything or try to set up a gateway."""
assert (
await async_setup_component(
hass, SCENE_DOMAIN, {"scene": {"platform": DECONZ_DOMAIN}}
)
is True
)
assert DECONZ_DOMAIN not in hass.data
async def test_no_scenes(hass):
async def test_no_scenes(hass, aioclient_mock):
"""Test that scenes can be loaded without scenes being available."""
await setup_deconz_integration(hass)
await setup_deconz_integration(hass, aioclient_mock)
assert len(hass.states.async_all()) == 0
async def test_scenes(hass):
async def test_scenes(hass, aioclient_mock):
"""Test that scenes works."""
data = deepcopy(DECONZ_WEB_REQUEST)
data["groups"] = deepcopy(GROUPS)
config_entry = await setup_deconz_integration(hass, get_state_response=data)
gateway = get_gateway_from_config_entry(hass, config_entry)
config_entry = await setup_deconz_integration(
hass, aioclient_mock, get_state_response=data
)
assert len(hass.states.async_all()) == 1
assert hass.states.get("scene.light_group_scene")
# Verify service calls
group_scene = gateway.api.groups["1"].scenes["1"]
mock_deconz_put_request(
aioclient_mock, config_entry.data, "/groups/1/scenes/1/recall"
)
# Service turn on scene
with patch.object(group_scene, "_request", return_value=True) as set_callback:
await hass.services.async_call(
SCENE_DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: "scene.light_group_scene"},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with("put", "/groups/1/scenes/1/recall", json={})
await hass.services.async_call(
SCENE_DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: "scene.light_group_scene"},
blocking=True,
)
assert aioclient_mock.mock_calls[1][2] == {}
await hass.config_entries.async_unload(config_entry.entry_id)

View File

@ -2,19 +2,14 @@
from copy import deepcopy
from homeassistant.components.deconz.const import (
CONF_ALLOW_CLIP_SENSOR,
DOMAIN as DECONZ_DOMAIN,
)
from homeassistant.components.deconz.const import CONF_ALLOW_CLIP_SENSOR
from homeassistant.components.deconz.gateway import get_gateway_from_config_entry
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
from homeassistant.const import (
DEVICE_CLASS_BATTERY,
DEVICE_CLASS_ILLUMINANCE,
DEVICE_CLASS_POWER,
STATE_UNAVAILABLE,
)
from homeassistant.setup import async_setup_component
from .test_gateway import DECONZ_WEB_REQUEST, setup_deconz_integration
@ -86,28 +81,19 @@ SENSORS = {
}
async def test_platform_manually_configured(hass):
"""Test that we do not discover anything or try to set up a gateway."""
assert (
await async_setup_component(
hass, SENSOR_DOMAIN, {"sensor": {"platform": DECONZ_DOMAIN}}
)
is True
)
assert DECONZ_DOMAIN not in hass.data
async def test_no_sensors(hass):
async def test_no_sensors(hass, aioclient_mock):
"""Test that no sensors in deconz results in no sensor entities."""
await setup_deconz_integration(hass)
await setup_deconz_integration(hass, aioclient_mock)
assert len(hass.states.async_all()) == 0
async def test_sensors(hass):
async def test_sensors(hass, aioclient_mock):
"""Test successful creation of sensor entities."""
data = deepcopy(DECONZ_WEB_REQUEST)
data["sensors"] = deepcopy(SENSORS)
config_entry = await setup_deconz_integration(hass, get_state_response=data)
config_entry = await setup_deconz_integration(
hass, aioclient_mock, get_state_response=data
)
gateway = get_gateway_from_config_entry(hass, config_entry)
assert len(hass.states.async_all()) == 5
@ -176,12 +162,13 @@ async def test_sensors(hass):
assert len(hass.states.async_all()) == 0
async def test_allow_clip_sensors(hass):
async def test_allow_clip_sensors(hass, aioclient_mock):
"""Test that CLIP sensors can be allowed."""
data = deepcopy(DECONZ_WEB_REQUEST)
data["sensors"] = deepcopy(SENSORS)
config_entry = await setup_deconz_integration(
hass,
aioclient_mock,
options={CONF_ALLOW_CLIP_SENSOR: True},
get_state_response=data,
)
@ -210,9 +197,9 @@ async def test_allow_clip_sensors(hass):
assert hass.states.get("sensor.clip_light_level_sensor")
async def test_add_new_sensor(hass):
async def test_add_new_sensor(hass, aioclient_mock):
"""Test that adding a new sensor works."""
config_entry = await setup_deconz_integration(hass)
config_entry = await setup_deconz_integration(hass, aioclient_mock)
gateway = get_gateway_from_config_entry(hass, config_entry)
assert len(hass.states.async_all()) == 0
@ -230,11 +217,13 @@ async def test_add_new_sensor(hass):
assert hass.states.get("sensor.light_level_sensor").state == "999.8"
async def test_add_battery_later(hass):
async def test_add_battery_later(hass, aioclient_mock):
"""Test that a sensor without an initial battery state creates a battery sensor once state exist."""
data = deepcopy(DECONZ_WEB_REQUEST)
data["sensors"] = {"1": deepcopy(SENSORS["3"])}
config_entry = await setup_deconz_integration(hass, get_state_response=data)
config_entry = await setup_deconz_integration(
hass, aioclient_mock, get_state_response=data
)
gateway = get_gateway_from_config_entry(hass, config_entry)
remote = gateway.api.sensors["1"]
@ -252,7 +241,7 @@ async def test_add_battery_later(hass):
assert hass.states.get("sensor.switch_1_battery_level")
async def test_air_quality_sensor(hass):
async def test_air_quality_sensor(hass, aioclient_mock):
"""Test successful creation of air quality sensor entities."""
data = deepcopy(DECONZ_WEB_REQUEST)
data["sensors"] = {
@ -274,7 +263,7 @@ async def test_air_quality_sensor(hass):
"uniqueid": "00:12:4b:00:14:4d:00:07-02-fdef",
}
}
await setup_deconz_integration(hass, get_state_response=data)
await setup_deconz_integration(hass, aioclient_mock, get_state_response=data)
assert len(hass.states.async_all()) == 1
@ -282,7 +271,7 @@ async def test_air_quality_sensor(hass):
assert air_quality.state == "poor"
async def test_time_sensor(hass):
async def test_time_sensor(hass, aioclient_mock):
"""Test successful creation of time sensor entities."""
data = deepcopy(DECONZ_WEB_REQUEST)
data["sensors"] = {
@ -305,7 +294,7 @@ async def test_time_sensor(hass):
"uniqueid": "cc:cc:cc:ff:fe:38:4d:b3-01-000a",
}
}
await setup_deconz_integration(hass, get_state_response=data)
await setup_deconz_integration(hass, aioclient_mock, get_state_response=data)
assert len(hass.states.async_all()) == 2
@ -316,13 +305,13 @@ async def test_time_sensor(hass):
assert time_battery.state == "40"
async def test_unsupported_sensor(hass):
async def test_unsupported_sensor(hass, aioclient_mock):
"""Test that unsupported sensors doesn't break anything."""
data = deepcopy(DECONZ_WEB_REQUEST)
data["sensors"] = {
"0": {"type": "not supported", "name": "name", "state": {}, "config": {}}
}
await setup_deconz_integration(hass, get_state_response=data)
await setup_deconz_integration(hass, aioclient_mock, get_state_response=data)
assert len(hass.states.async_all()) == 1

View File

@ -25,7 +25,13 @@ from homeassistant.components.deconz.services import (
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
from homeassistant.helpers.entity_registry import async_entries_for_config_entry
from .test_gateway import BRIDGEID, DECONZ_WEB_REQUEST, setup_deconz_integration
from .test_gateway import (
BRIDGEID,
DECONZ_WEB_REQUEST,
mock_deconz_put_request,
mock_deconz_request,
setup_deconz_integration,
)
GROUP = {
"1": {
@ -114,72 +120,66 @@ async def test_service_unload_not_registered(hass):
async_remove.assert_not_called()
async def test_configure_service_with_field(hass):
async def test_configure_service_with_field(hass, aioclient_mock):
"""Test that service invokes pydeconz with the correct path and data."""
await setup_deconz_integration(hass)
config_entry = await setup_deconz_integration(hass, aioclient_mock)
data = {
SERVICE_FIELD: "/light/2",
SERVICE_FIELD: "/lights/2",
CONF_BRIDGE_ID: BRIDGEID,
SERVICE_DATA: {"on": True, "attr1": 10, "attr2": 20},
}
with patch("pydeconz.DeconzSession.request", return_value=Mock(True)) as put_state:
await hass.services.async_call(
DECONZ_DOMAIN, SERVICE_CONFIGURE_DEVICE, service_data=data
)
await hass.async_block_till_done()
put_state.assert_called_with(
"put", "/light/2", json={"on": True, "attr1": 10, "attr2": 20}
)
mock_deconz_put_request(aioclient_mock, config_entry.data, "/lights/2")
await hass.services.async_call(
DECONZ_DOMAIN, SERVICE_CONFIGURE_DEVICE, service_data=data, blocking=True
)
assert aioclient_mock.mock_calls[1][2] == {"on": True, "attr1": 10, "attr2": 20}
async def test_configure_service_with_entity(hass):
async def test_configure_service_with_entity(hass, aioclient_mock):
"""Test that service invokes pydeconz with the correct path and data."""
config_entry = await setup_deconz_integration(hass)
config_entry = await setup_deconz_integration(hass, aioclient_mock)
gateway = get_gateway_from_config_entry(hass, config_entry)
gateway.deconz_ids["light.test"] = "/light/1"
gateway.deconz_ids["light.test"] = "/lights/1"
data = {
SERVICE_ENTITY: "light.test",
SERVICE_DATA: {"on": True, "attr1": 10, "attr2": 20},
}
with patch("pydeconz.DeconzSession.request", return_value=Mock(True)) as put_state:
await hass.services.async_call(
DECONZ_DOMAIN, SERVICE_CONFIGURE_DEVICE, service_data=data
)
await hass.async_block_till_done()
put_state.assert_called_with(
"put", "/light/1", json={"on": True, "attr1": 10, "attr2": 20}
)
mock_deconz_put_request(aioclient_mock, config_entry.data, "/lights/1")
await hass.services.async_call(
DECONZ_DOMAIN, SERVICE_CONFIGURE_DEVICE, service_data=data, blocking=True
)
assert aioclient_mock.mock_calls[1][2] == {"on": True, "attr1": 10, "attr2": 20}
async def test_configure_service_with_entity_and_field(hass):
async def test_configure_service_with_entity_and_field(hass, aioclient_mock):
"""Test that service invokes pydeconz with the correct path and data."""
config_entry = await setup_deconz_integration(hass)
config_entry = await setup_deconz_integration(hass, aioclient_mock)
gateway = get_gateway_from_config_entry(hass, config_entry)
gateway.deconz_ids["light.test"] = "/light/1"
gateway.deconz_ids["light.test"] = "/lights/1"
data = {
SERVICE_ENTITY: "light.test",
SERVICE_FIELD: "/state",
SERVICE_DATA: {"on": True, "attr1": 10, "attr2": 20},
}
with patch("pydeconz.DeconzSession.request", return_value=Mock(True)) as put_state:
await hass.services.async_call(
DECONZ_DOMAIN, SERVICE_CONFIGURE_DEVICE, service_data=data
)
await hass.async_block_till_done()
put_state.assert_called_with(
"put", "/light/1/state", json={"on": True, "attr1": 10, "attr2": 20}
)
mock_deconz_put_request(aioclient_mock, config_entry.data, "/lights/1/state")
await hass.services.async_call(
DECONZ_DOMAIN, SERVICE_CONFIGURE_DEVICE, service_data=data, blocking=True
)
assert aioclient_mock.mock_calls[1][2] == {"on": True, "attr1": 10, "attr2": 20}
async def test_configure_service_with_faulty_field(hass):
async def test_configure_service_with_faulty_field(hass, aioclient_mock):
"""Test that service invokes pydeconz with the correct path and data."""
await setup_deconz_integration(hass)
await setup_deconz_integration(hass, aioclient_mock)
data = {SERVICE_FIELD: "light/2", SERVICE_DATA: {}}
@ -190,9 +190,9 @@ async def test_configure_service_with_faulty_field(hass):
await hass.async_block_till_done()
async def test_configure_service_with_faulty_entity(hass):
async def test_configure_service_with_faulty_entity(hass, aioclient_mock):
"""Test that service invokes pydeconz with the correct path and data."""
await setup_deconz_integration(hass)
await setup_deconz_integration(hass, aioclient_mock)
data = {
SERVICE_ENTITY: "light.nonexisting",
@ -207,21 +207,24 @@ async def test_configure_service_with_faulty_entity(hass):
put_state.assert_not_called()
async def test_service_refresh_devices(hass):
async def test_service_refresh_devices(hass, aioclient_mock):
"""Test that service can refresh devices."""
config_entry = await setup_deconz_integration(hass)
config_entry = await setup_deconz_integration(hass, aioclient_mock)
gateway = get_gateway_from_config_entry(hass, config_entry)
aioclient_mock.clear_requests()
data = {CONF_BRIDGE_ID: BRIDGEID}
with patch(
"pydeconz.DeconzSession.request",
return_value={"groups": GROUP, "lights": LIGHT, "sensors": SENSOR},
):
await hass.services.async_call(
DECONZ_DOMAIN, SERVICE_DEVICE_REFRESH, service_data=data
)
await hass.async_block_till_done()
mock_deconz_request(
aioclient_mock,
config_entry.data,
{"groups": GROUP, "lights": LIGHT, "sensors": SENSOR},
)
await hass.services.async_call(
DECONZ_DOMAIN, SERVICE_DEVICE_REFRESH, service_data=data
)
await hass.async_block_till_done()
assert gateway.deconz_ids == {
"light.group_1_name": "/groups/1",
@ -231,12 +234,14 @@ async def test_service_refresh_devices(hass):
}
async def test_remove_orphaned_entries_service(hass):
async def test_remove_orphaned_entries_service(hass, aioclient_mock):
"""Test service works and also don't remove more than expected."""
data = deepcopy(DECONZ_WEB_REQUEST)
data["lights"] = deepcopy(LIGHT)
data["sensors"] = deepcopy(SWITCH)
config_entry = await setup_deconz_integration(hass, get_state_response=data)
config_entry = await setup_deconz_integration(
hass, aioclient_mock, get_state_response=data
)
data = {CONF_BRIDGE_ID: BRIDGEID}

View File

@ -1,9 +1,7 @@
"""deCONZ switch platform tests."""
from copy import deepcopy
from unittest.mock import patch
from homeassistant.components.deconz import DOMAIN as DECONZ_DOMAIN
from homeassistant.components.deconz.gateway import get_gateway_from_config_entry
from homeassistant.components.switch import (
DOMAIN as SWITCH_DOMAIN,
@ -11,9 +9,12 @@ from homeassistant.components.switch import (
SERVICE_TURN_ON,
)
from homeassistant.const import ATTR_ENTITY_ID, STATE_OFF, STATE_ON, STATE_UNAVAILABLE
from homeassistant.setup import async_setup_component
from .test_gateway import DECONZ_WEB_REQUEST, setup_deconz_integration
from .test_gateway import (
DECONZ_WEB_REQUEST,
mock_deconz_put_request,
setup_deconz_integration,
)
POWER_PLUGS = {
"1": {
@ -64,28 +65,19 @@ SIRENS = {
}
async def test_platform_manually_configured(hass):
"""Test that we do not discover anything or try to set up a gateway."""
assert (
await async_setup_component(
hass, SWITCH_DOMAIN, {"switch": {"platform": DECONZ_DOMAIN}}
)
is True
)
assert DECONZ_DOMAIN not in hass.data
async def test_no_switches(hass):
async def test_no_switches(hass, aioclient_mock):
"""Test that no switch entities are created."""
await setup_deconz_integration(hass)
await setup_deconz_integration(hass, aioclient_mock)
assert len(hass.states.async_all()) == 0
async def test_power_plugs(hass):
async def test_power_plugs(hass, aioclient_mock):
"""Test that all supported switch entities are created."""
data = deepcopy(DECONZ_WEB_REQUEST)
data["lights"] = deepcopy(POWER_PLUGS)
config_entry = await setup_deconz_integration(hass, get_state_response=data)
config_entry = await setup_deconz_integration(
hass, aioclient_mock, get_state_response=data
)
gateway = get_gateway_from_config_entry(hass, config_entry)
assert len(hass.states.async_all()) == 4
@ -107,35 +99,27 @@ async def test_power_plugs(hass):
# Verify service calls
on_off_switch_device = gateway.api.lights["1"]
mock_deconz_put_request(aioclient_mock, config_entry.data, "/lights/1/state")
# Service turn on power plug
with patch.object(
on_off_switch_device, "_request", return_value=True
) as set_callback:
await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: "switch.on_off_switch"},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with("put", "/lights/1/state", json={"on": True})
await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: "switch.on_off_switch"},
blocking=True,
)
assert aioclient_mock.mock_calls[1][2] == {"on": True}
# Service turn off power plug
with patch.object(
on_off_switch_device, "_request", return_value=True
) as set_callback:
await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: "switch.on_off_switch"},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with("put", "/lights/1/state", json={"on": False})
await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: "switch.on_off_switch"},
blocking=True,
)
assert aioclient_mock.mock_calls[2][2] == {"on": False}
await hass.config_entries.async_unload(config_entry.entry_id)
@ -149,11 +133,13 @@ async def test_power_plugs(hass):
assert len(hass.states.async_all()) == 0
async def test_sirens(hass):
async def test_sirens(hass, aioclient_mock):
"""Test that siren entities are created."""
data = deepcopy(DECONZ_WEB_REQUEST)
data["lights"] = deepcopy(SIRENS)
config_entry = await setup_deconz_integration(hass, get_state_response=data)
config_entry = await setup_deconz_integration(
hass, aioclient_mock, get_state_response=data
)
gateway = get_gateway_from_config_entry(hass, config_entry)
assert len(hass.states.async_all()) == 2
@ -173,39 +159,27 @@ async def test_sirens(hass):
# Verify service calls
warning_device_device = gateway.api.lights["1"]
mock_deconz_put_request(aioclient_mock, config_entry.data, "/lights/1/state")
# Service turn on siren
with patch.object(
warning_device_device, "_request", return_value=True
) as set_callback:
await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: "switch.warning_device"},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with(
"put", "/lights/1/state", json={"alert": "lselect"}
)
await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: "switch.warning_device"},
blocking=True,
)
assert aioclient_mock.mock_calls[1][2] == {"alert": "lselect"}
# Service turn off siren
with patch.object(
warning_device_device, "_request", return_value=True
) as set_callback:
await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: "switch.warning_device"},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with(
"put", "/lights/1/state", json={"alert": "none"}
)
await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: "switch.warning_device"},
blocking=True,
)
assert aioclient_mock.mock_calls[2][2] == {"alert": "none"}
await hass.config_entries.async_unload(config_entry.entry_id)