From 20f45f8ab9e744de7488fe66c5e7f8aca9b60e2d Mon Sep 17 00:00:00 2001 From: Robert Svensson Date: Tue, 9 Feb 2021 08:31:29 +0100 Subject: [PATCH] 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 --- tests/components/deconz/test_binary_sensor.py | 60 ++-- tests/components/deconz/test_climate.py | 290 ++++++++---------- tests/components/deconz/test_config_flow.py | 34 +- tests/components/deconz/test_cover.py | 259 +++++++--------- tests/components/deconz/test_deconz_event.py | 6 +- .../components/deconz/test_device_trigger.py | 16 +- tests/components/deconz/test_fan.py | 145 ++++----- tests/components/deconz/test_gateway.py | 61 +++- tests/components/deconz/test_init.py | 45 +-- tests/components/deconz/test_light.py | 245 +++++++-------- tests/components/deconz/test_lock.py | 64 ++-- tests/components/deconz/test_logbook.py | 6 +- tests/components/deconz/test_scene.py | 52 ++-- tests/components/deconz/test_sensor.py | 53 ++-- tests/components/deconz/test_services.py | 105 ++++--- tests/components/deconz/test_switch.py | 116 +++---- 16 files changed, 700 insertions(+), 857 deletions(-) diff --git a/tests/components/deconz/test_binary_sensor.py b/tests/components/deconz/test_binary_sensor.py index f64a4c4c259..70d3db4149b 100644 --- a/tests/components/deconz/test_binary_sensor.py +++ b/tests/components/deconz/test_binary_sensor.py @@ -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") diff --git a/tests/components/deconz/test_climate.py b/tests/components/deconz/test_climate.py index fcb6e16f07f..0a37debade3 100644 --- a/tests/components/deconz/test_climate.py +++ b/tests/components/deconz/test_climate.py @@ -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 diff --git a/tests/components/deconz/test_config_flow.py b/tests/components/deconz/test_config_flow.py index e18418ff9ae..19f544fabc9 100644 --- a/tests/components/deconz/test_config_flow.py +++ b/tests/components/deconz/test_config_flow.py @@ -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) diff --git a/tests/components/deconz/test_cover.py b/tests/components/deconz/test_cover.py index 43364208f4f..e48d44fb61e 100644 --- a/tests/components/deconz/test_cover.py +++ b/tests/components/deconz/test_cover.py @@ -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} diff --git a/tests/components/deconz/test_deconz_event.py b/tests/components/deconz/test_deconz_event.py index 232de5eacd2..1212d72a6ee 100644 --- a/tests/components/deconz/test_deconz_event.py +++ b/tests/components/deconz/test_deconz_event.py @@ -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 diff --git a/tests/components/deconz/test_device_trigger.py b/tests/components/deconz/test_device_trigger.py index a5399fe4796..b9d538588cd 100644 --- a/tests/components/deconz/test_device_trigger.py +++ b/tests/components/deconz/test_device_trigger.py @@ -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 diff --git a/tests/components/deconz/test_fan.py b/tests/components/deconz/test_fan.py index 7f225196744..c6acbb7f6aa 100644 --- a/tests/components/deconz/test_fan.py +++ b/tests/components/deconz/test_fan.py @@ -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" diff --git a/tests/components/deconz/test_gateway.py b/tests/components/deconz/test_gateway.py index f670f2a1d10..5c1642ba8f7 100644 --- a/tests/components/deconz/test_gateway.py +++ b/tests/components/deconz/test_gateway.py @@ -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() diff --git a/tests/components/deconz/test_init.py b/tests/components/deconz/test_init.py index 43c0c48440c..ed7655bf620 100644 --- a/tests/components/deconz/test_init.py +++ b/tests/components/deconz/test_init.py @@ -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): diff --git a/tests/components/deconz/test_light.py b/tests/components/deconz/test_light.py index bdb7fbb8aef..c7f7fab1868 100644 --- a/tests/components/deconz/test_light.py +++ b/tests/components/deconz/test_light.py @@ -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 diff --git a/tests/components/deconz/test_lock.py b/tests/components/deconz/test_lock.py index d53da74dfdd..a6b4caaec19 100644 --- a/tests/components/deconz/test_lock.py +++ b/tests/components/deconz/test_lock.py @@ -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) diff --git a/tests/components/deconz/test_logbook.py b/tests/components/deconz/test_logbook.py index 500ca03b7ed..5886a29a8bf 100644 --- a/tests/components/deconz/test_logbook.py +++ b/tests/components/deconz/test_logbook.py @@ -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") diff --git a/tests/components/deconz/test_scene.py b/tests/components/deconz/test_scene.py index ca8df2c0425..229111bf9ae 100644 --- a/tests/components/deconz/test_scene.py +++ b/tests/components/deconz/test_scene.py @@ -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) diff --git a/tests/components/deconz/test_sensor.py b/tests/components/deconz/test_sensor.py index 426a88b8bb6..8a00385ccb9 100644 --- a/tests/components/deconz/test_sensor.py +++ b/tests/components/deconz/test_sensor.py @@ -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 diff --git a/tests/components/deconz/test_services.py b/tests/components/deconz/test_services.py index faa1d3485bb..41eefa95785 100644 --- a/tests/components/deconz/test_services.py +++ b/tests/components/deconz/test_services.py @@ -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} diff --git a/tests/components/deconz/test_switch.py b/tests/components/deconz/test_switch.py index 22ce182cb62..6aafac1bd42 100644 --- a/tests/components/deconz/test_switch.py +++ b/tests/components/deconz/test_switch.py @@ -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)