diff --git a/homeassistant/components/zwave_js/__init__.py b/homeassistant/components/zwave_js/__init__.py index 7ff351893b1bae..d477964d229849 100644 --- a/homeassistant/components/zwave_js/__init__.py +++ b/homeassistant/components/zwave_js/__init__.py @@ -9,7 +9,7 @@ from async_timeout import timeout from zwave_js_server.client import Client as ZwaveClient -from zwave_js_server.const import CommandClass +from zwave_js_server.const import CommandClass, RemoveNodeReason from zwave_js_server.exceptions import BaseZwaveJSServerError, InvalidServerVersion from zwave_js_server.model.driver import Driver from zwave_js_server.model.node import Node as ZwaveNode @@ -398,13 +398,13 @@ async def async_on_node_added(self, node: ZwaveNode) -> None: def async_on_node_removed(self, event: dict) -> None: """Handle node removed event.""" node: ZwaveNode = event["node"] - replaced: bool = event.get("replaced", False) + reason: RemoveNodeReason = event["reason"] # grab device in device registry attached to this node dev_id = get_device_id(self.driver_events.driver, node) device = self.dev_reg.async_get_device(identifiers={dev_id}) # We assert because we know the device exists assert device - if replaced: + if reason in (RemoveNodeReason.REPLACED, RemoveNodeReason.PROXY_REPLACED): self.discovered_value_ids.pop(device.id, None) async_dispatcher_send( diff --git a/homeassistant/components/zwave_js/api.py b/homeassistant/components/zwave_js/api.py index 5fc7da68e99c4f..6d2461df3e42e4 100644 --- a/homeassistant/components/zwave_js/api.py +++ b/homeassistant/components/zwave_js/api.py @@ -1138,6 +1138,7 @@ def node_removed(event: dict) -> None: node = event["node"] node_details = { "node_id": node.node_id, + "reason": event["reason"], } connection.send_message( diff --git a/homeassistant/components/zwave_js/discovery.py b/homeassistant/components/zwave_js/discovery.py index 947e5157a8af38..b1f9fe52aa09a0 100644 --- a/homeassistant/components/zwave_js/discovery.py +++ b/homeassistant/components/zwave_js/discovery.py @@ -1125,36 +1125,29 @@ def async_discover_single_configuration_value( ConfigurationValueType.RANGE, ConfigurationValueType.MANUAL_ENTRY, ): - if value.metadata.type == ValueType.BOOLEAN or ( - value.metadata.min == 0 and value.metadata.max == 1 - ): - yield ZwaveDiscoveryInfo( - node=value.node, - primary_value=value, - assumed_state=False, - platform=Platform.SWITCH, - platform_hint="config_parameter", - platform_data=None, - additional_value_ids_to_watch=set(), - entity_registry_enabled_default=False, - ) - else: - yield ZwaveDiscoveryInfo( - node=value.node, - primary_value=value, - assumed_state=False, - platform=Platform.NUMBER, - platform_hint="config_parameter", - platform_data=None, - additional_value_ids_to_watch=set(), - entity_registry_enabled_default=False, - ) + yield ZwaveDiscoveryInfo( + node=value.node, + primary_value=value, + assumed_state=False, + platform=Platform.NUMBER, + platform_hint="config_parameter", + platform_data=None, + additional_value_ids_to_watch=set(), + entity_registry_enabled_default=False, + ) + elif value.configuration_value_type == ConfigurationValueType.BOOLEAN: + yield ZwaveDiscoveryInfo( + node=value.node, + primary_value=value, + assumed_state=False, + platform=Platform.SWITCH, + platform_hint="config_parameter", + platform_data=None, + additional_value_ids_to_watch=set(), + entity_registry_enabled_default=False, + ) elif not value.metadata.writeable and value.metadata.readable: - if value.metadata.type == ValueType.BOOLEAN or ( - value.metadata.min == 0 - and value.metadata.max == 1 - and not value.metadata.states - ): + if value.configuration_value_type == ConfigurationValueType.BOOLEAN: yield ZwaveDiscoveryInfo( node=value.node, primary_value=value, diff --git a/homeassistant/components/zwave_js/manifest.json b/homeassistant/components/zwave_js/manifest.json index b163ace1d24f01..7850db608f6f43 100644 --- a/homeassistant/components/zwave_js/manifest.json +++ b/homeassistant/components/zwave_js/manifest.json @@ -9,7 +9,7 @@ "iot_class": "local_push", "loggers": ["zwave_js_server"], "quality_scale": "platinum", - "requirements": ["pyserial==3.5", "zwave-js-server-python==0.49.0"], + "requirements": ["pyserial==3.5", "zwave-js-server-python==0.50.0"], "usb": [ { "vid": "0658", diff --git a/homeassistant/components/zwave_js/services.py b/homeassistant/components/zwave_js/services.py index 133cb40740558c..44ef3a2269cec2 100644 --- a/homeassistant/components/zwave_js/services.py +++ b/homeassistant/components/zwave_js/services.py @@ -8,7 +8,7 @@ import voluptuous as vol from zwave_js_server.client import Client as ZwaveClient -from zwave_js_server.const import CommandClass, CommandStatus +from zwave_js_server.const import SET_VALUE_SUCCESS, CommandClass, CommandStatus from zwave_js_server.exceptions import FailedZWaveCommand, SetValueFailed from zwave_js_server.model.endpoint import Endpoint from zwave_js_server.model.node import Node as ZwaveNode @@ -39,12 +39,6 @@ _LOGGER = logging.getLogger(__name__) -SET_VALUE_FAILED_EXC = SetValueFailed( - "Unable to set value, refer to " - "https://zwave-js.github.io/node-zwave-js/#/api/node?id=setvalue for " - "possible reasons" -) - def parameter_name_does_not_need_bitmask( val: dict[str, int | str | list[str]] @@ -538,16 +532,20 @@ async def async_set_value(self, service: ServiceCall) -> None: nodes_list = list(nodes) # multiple set_values my fail so we will track the entire list set_value_failed_nodes_list: list[ZwaveNode | Endpoint] = [] - for node_, success in get_valid_responses_from_results(nodes_list, results): - if success is False: - # If we failed to set a value, add node to SetValueFailed exception list + set_value_failed_error_list: list[SetValueFailed] = [] + for node_, result in get_valid_responses_from_results(nodes_list, results): + if result and result.status not in SET_VALUE_SUCCESS: + # If we failed to set a value, add node to exception list set_value_failed_nodes_list.append(node_) + set_value_failed_error_list.append( + SetValueFailed(f"{result.status} {result.message}") + ) - # Add the SetValueFailed exception to the results and the nodes to the node - # list. No-op if there are no SetValueFailed exceptions + # Add the exception to the results and the nodes to the node list. No-op if + # no set value commands failed raise_exceptions_from_results( (*nodes_list, *set_value_failed_nodes_list), - (*results, *([SET_VALUE_FAILED_EXC] * len(set_value_failed_nodes_list))), + (*results, *set_value_failed_error_list), ) async def async_multicast_set_value(self, service: ServiceCall) -> None: @@ -611,7 +609,7 @@ async def async_multicast_set_value(self, service: ServiceCall) -> None: new_value = str(new_value) try: - success = await async_multicast_set_value( + result = await async_multicast_set_value( client=client, new_value=new_value, value_data=value, @@ -621,10 +619,10 @@ async def async_multicast_set_value(self, service: ServiceCall) -> None: except FailedZWaveCommand as err: raise HomeAssistantError("Unable to set value via multicast") from err - if success is False: + if result.status not in SET_VALUE_SUCCESS: raise HomeAssistantError( "Unable to set value via multicast" - ) from SetValueFailed + ) from SetValueFailed(f"{result.status} {result.message}") async def async_ping(self, service: ServiceCall) -> None: """Ping node(s).""" diff --git a/requirements_all.txt b/requirements_all.txt index 5d4d9648d7199d..24bff1c464cc0b 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2768,7 +2768,7 @@ zigpy==0.56.2 zm-py==0.5.2 # homeassistant.components.zwave_js -zwave-js-server-python==0.49.0 +zwave-js-server-python==0.50.0 # homeassistant.components.zwave_me zwave-me-ws==0.4.3 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 649c25c4d6ba05..b1d775d94bab4e 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -2029,7 +2029,7 @@ zigpy-znp==0.11.3 zigpy==0.56.2 # homeassistant.components.zwave_js -zwave-js-server-python==0.49.0 +zwave-js-server-python==0.50.0 # homeassistant.components.zwave_me zwave-me-ws==0.4.3 diff --git a/tests/components/zwave_js/common.py b/tests/components/zwave_js/common.py index 606dda30b243c0..dbd117d90cc5e2 100644 --- a/tests/components/zwave_js/common.py +++ b/tests/components/zwave_js/common.py @@ -48,6 +48,16 @@ PROPERTY_ULTRAVIOLET = "Ultraviolet" +SET_VALUE_RESULT_MAP = { + True: {"result": {"success": True, "status": 255}}, + False: {"result": {"status": 2, "message": "test"}}, +} + + +def set_value_response(client, success): + """Set response for set_value command.""" + client.async_send_command.return_value = SET_VALUE_RESULT_MAP[success] + def replace_value_of_zwave_value( node_data: NodeDataType, matchers: list[ZwaveValueMatcher], new_value: Any diff --git a/tests/components/zwave_js/fixtures/nortek_thermostat_removed_event.json b/tests/components/zwave_js/fixtures/nortek_thermostat_removed_event.json index 8491e65c037ad0..e30e0297e7d7d8 100644 --- a/tests/components/zwave_js/fixtures/nortek_thermostat_removed_event.json +++ b/tests/components/zwave_js/fixtures/nortek_thermostat_removed_event.json @@ -270,5 +270,5 @@ } ] }, - "replaced": false + "reason": 0 } diff --git a/tests/components/zwave_js/test_api.py b/tests/components/zwave_js/test_api.py index ebdf21124357fe..b50f50a2197130 100644 --- a/tests/components/zwave_js/test_api.py +++ b/tests/components/zwave_js/test_api.py @@ -1715,7 +1715,7 @@ async def test_remove_node( assert len(client.async_send_command.call_args_list) == 1 assert client.async_send_command.call_args[0][0] == { "command": "controller.begin_exclusion", - "strategy": 0, + "options": {"strategy": 0}, } # Test FailedZWaveCommand is caught diff --git a/tests/components/zwave_js/test_climate.py b/tests/components/zwave_js/test_climate.py index 753c107c2ee072..39e4a6b536559e 100644 --- a/tests/components/zwave_js/test_climate.py +++ b/tests/components/zwave_js/test_climate.py @@ -49,6 +49,7 @@ CLIMATE_MAIN_HEAT_ACTIONNER, CLIMATE_RADIO_THERMOSTAT_ENTITY, replace_value_of_zwave_value, + set_value_response, ) @@ -87,6 +88,7 @@ async def test_thermostat_v2( ) client.async_send_command.reset_mock() + set_value_response(client, True) # Test setting hvac mode await hass.services.async_call( @@ -111,6 +113,7 @@ async def test_thermostat_v2( assert args["value"] == 2 client.async_send_command.reset_mock() + set_value_response(client, True) # Test setting temperature await hass.services.async_call( @@ -146,6 +149,7 @@ async def test_thermostat_v2( assert args["value"] == 77 client.async_send_command.reset_mock() + set_value_response(client, True) # Test cool mode update from value updated event event = Event( @@ -200,6 +204,7 @@ async def test_thermostat_v2( assert state.attributes[ATTR_TARGET_TEMP_LOW] == 22.2 client.async_send_command.reset_mock() + set_value_response(client, True) # Test setting temperature with heat_cool await hass.services.async_call( @@ -237,6 +242,7 @@ async def test_thermostat_v2( assert args["value"] == 86 client.async_send_command.reset_mock() + set_value_response(client, True) # Test setting invalid hvac mode with pytest.raises(ValueError): @@ -251,6 +257,7 @@ async def test_thermostat_v2( ) client.async_send_command.reset_mock() + set_value_response(client, True) # Test setting fan mode await hass.services.async_call( @@ -275,6 +282,7 @@ async def test_thermostat_v2( assert args["value"] == 1 client.async_send_command.reset_mock() + set_value_response(client, True) # Test setting invalid fan mode with pytest.raises(ValueError): @@ -571,6 +579,8 @@ async def test_preset_and_no_setpoint( assert state.state == HVACMode.HEAT assert state.attributes[ATTR_TEMPERATURE] == 22 + set_value_response(client, True) + # Test setting preset mode Full power await hass.services.async_call( CLIMATE_DOMAIN, @@ -594,6 +604,7 @@ async def test_preset_and_no_setpoint( assert args["value"] == 15 client.async_send_command.reset_mock() + set_value_response(client, True) # Test Full power preset update from value updated event event = Event( @@ -635,6 +646,7 @@ async def test_preset_and_no_setpoint( assert len(client.async_send_command.call_args_list) == 0 client.async_send_command.reset_mock() + set_value_response(client, True) # Restore hvac mode by setting preset None await hass.services.async_call( diff --git a/tests/components/zwave_js/test_cover.py b/tests/components/zwave_js/test_cover.py index 502f2413c992cc..4b8962a1059be7 100644 --- a/tests/components/zwave_js/test_cover.py +++ b/tests/components/zwave_js/test_cover.py @@ -40,7 +40,7 @@ ) from homeassistant.core import HomeAssistant -from .common import replace_value_of_zwave_value +from .common import replace_value_of_zwave_value, set_value_response WINDOW_COVER_ENTITY = "cover.zws_12" GDC_COVER_ENTITY = "cover.aeon_labs_garage_door_controller_gen5" @@ -64,6 +64,8 @@ async def test_window_cover( assert state.state == STATE_CLOSED assert state.attributes[ATTR_CURRENT_POSITION] == 0 + set_value_response(client, True) + # Test setting position await hass.services.async_call( DOMAIN, @@ -84,6 +86,7 @@ async def test_window_cover( assert args["value"] == 50 client.async_send_command.reset_mock() + set_value_response(client, True) # Test setting position await hass.services.async_call( @@ -105,6 +108,7 @@ async def test_window_cover( assert args["value"] == 0 client.async_send_command.reset_mock() + set_value_response(client, True) # Test opening await hass.services.async_call( @@ -126,6 +130,8 @@ async def test_window_cover( assert args["value"] client.async_send_command.reset_mock() + set_value_response(client, True) + # Test stop after opening await hass.services.async_call( DOMAIN, @@ -165,6 +171,7 @@ async def test_window_cover( ) node.receive_event(event) client.async_send_command.reset_mock() + set_value_response(client, True) state = hass.states.get(WINDOW_COVER_ENTITY) assert state.state == STATE_OPEN @@ -188,6 +195,7 @@ async def test_window_cover( assert args["value"] == 0 client.async_send_command.reset_mock() + set_value_response(client, True) # Test stop after closing await hass.services.async_call( @@ -209,6 +217,7 @@ async def test_window_cover( assert not open_args["value"] client.async_send_command.reset_mock() + set_value_response(client, True) event = Event( type="value updated", @@ -244,6 +253,8 @@ async def test_fibaro_fgr222_shutter_cover( assert state.state == STATE_OPEN assert state.attributes[ATTR_CURRENT_TILT_POSITION] == 0 + set_value_response(client, True) + # Test opening tilts await hass.services.async_call( DOMAIN, @@ -265,6 +276,8 @@ async def test_fibaro_fgr222_shutter_cover( assert args["value"] == 99 client.async_send_command.reset_mock() + set_value_response(client, True) + # Test closing tilts await hass.services.async_call( DOMAIN, @@ -286,6 +299,8 @@ async def test_fibaro_fgr222_shutter_cover( assert args["value"] == 0 client.async_send_command.reset_mock() + set_value_response(client, True) + # Test setting tilt position await hass.services.async_call( DOMAIN, @@ -345,6 +360,8 @@ async def test_aeotec_nano_shutter_cover( assert state.state == STATE_CLOSED assert state.attributes[ATTR_CURRENT_POSITION] == 0 + set_value_response(client, True) + # Test opening await hass.services.async_call( DOMAIN, @@ -365,6 +382,8 @@ async def test_aeotec_nano_shutter_cover( assert args["value"] client.async_send_command.reset_mock() + set_value_response(client, True) + # Test stop after opening await hass.services.async_call( DOMAIN, @@ -405,6 +424,7 @@ async def test_aeotec_nano_shutter_cover( node.receive_event(event) client.async_send_command.reset_mock() + set_value_response(client, True) state = hass.states.get(AEOTEC_SHUTTER_COVER_ENTITY) assert state.state == STATE_OPEN @@ -428,6 +448,7 @@ async def test_aeotec_nano_shutter_cover( assert args["value"] == 0 client.async_send_command.reset_mock() + set_value_response(client, True) # Test stop after closing await hass.services.async_call( @@ -481,6 +502,8 @@ async def test_motor_barrier_cover( assert state.state == STATE_CLOSED + set_value_response(client, True) + # Test open await hass.services.async_call( DOMAIN, SERVICE_OPEN_COVER, {ATTR_ENTITY_ID: GDC_COVER_ENTITY}, blocking=True @@ -502,6 +525,7 @@ async def test_motor_barrier_cover( assert state.state == STATE_CLOSED client.async_send_command.reset_mock() + set_value_response(client, True) # Test close await hass.services.async_call( @@ -524,6 +548,7 @@ async def test_motor_barrier_cover( assert state.state == STATE_CLOSED client.async_send_command.reset_mock() + set_value_response(client, True) # Barrier sends an opening state event = Event( @@ -716,6 +741,8 @@ async def test_iblinds_v3_cover( assert ATTR_CURRENT_TILT_POSITION in state.attributes assert state.attributes[ATTR_CURRENT_TILT_POSITION] == 0 + set_value_response(client, True) + await hass.services.async_call( DOMAIN, SERVICE_CLOSE_COVER_TILT, @@ -736,6 +763,7 @@ async def test_iblinds_v3_cover( assert args["value"] == 0 client.async_send_command.reset_mock() + set_value_response(client, True) await hass.services.async_call( DOMAIN, @@ -757,6 +785,7 @@ async def test_iblinds_v3_cover( assert args["value"] == 50 client.async_send_command.reset_mock() + set_value_response(client, True) await hass.services.async_call( DOMAIN, @@ -778,6 +807,7 @@ async def test_iblinds_v3_cover( assert args["value"] == 12 client.async_send_command.reset_mock() + set_value_response(client, True) await hass.services.async_call( DOMAIN, @@ -820,6 +850,8 @@ async def test_nice_ibt4zwave_cover( assert state.attributes[ATTR_CURRENT_POSITION] == 0 assert state.attributes[ATTR_DEVICE_CLASS] == CoverDeviceClass.GATE + set_value_response(client, True) + await hass.services.async_call( DOMAIN, SERVICE_CLOSE_COVER, @@ -839,6 +871,7 @@ async def test_nice_ibt4zwave_cover( assert args["value"] == 0 client.async_send_command.reset_mock() + set_value_response(client, True) await hass.services.async_call( DOMAIN, diff --git a/tests/components/zwave_js/test_discovery.py b/tests/components/zwave_js/test_discovery.py index 1c4a69d32e39c6..6d359b4f25391b 100644 --- a/tests/components/zwave_js/test_discovery.py +++ b/tests/components/zwave_js/test_discovery.py @@ -26,6 +26,8 @@ from homeassistant.core import HomeAssistant from homeassistant.helpers import entity_registry as er +from .common import set_value_response + async def test_iblinds_v2(hass: HomeAssistant, client, iblinds_v2, integration) -> None: """Test that an iBlinds v2.0 multilevel switch value is discovered as a cover.""" @@ -171,6 +173,9 @@ async def test_zooz_zen72( state = hass.states.get(entity_id) assert state assert state.state == STATE_UNKNOWN + + set_value_response(client, True) + await hass.services.async_call( NUMBER_DOMAIN, SERVICE_SET_VALUE, @@ -192,6 +197,7 @@ async def test_zooz_zen72( assert args["value"] == 5 client.async_send_command.reset_mock() + set_value_response(client, True) entity_id = "button.z_wave_plus_700_series_dimmer_switch_identify" entry = ent_reg.async_get(entity_id) @@ -256,6 +262,9 @@ async def test_indicator_test( state = hass.states.get(entity_id) assert state assert state.state == STATE_OFF + + set_value_response(client, True) + await hass.services.async_call( SWITCH_DOMAIN, SERVICE_TURN_ON, @@ -275,6 +284,7 @@ async def test_indicator_test( assert args["value"] is True client.async_send_command.reset_mock() + set_value_response(client, True) await hass.services.async_call( SWITCH_DOMAIN, diff --git a/tests/components/zwave_js/test_fan.py b/tests/components/zwave_js/test_fan.py index 2b50870041391d..1769dedd086093 100644 --- a/tests/components/zwave_js/test_fan.py +++ b/tests/components/zwave_js/test_fan.py @@ -33,6 +33,8 @@ from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers import entity_registry as er +from .common import set_value_response + async def test_generic_fan( hass: HomeAssistant, client, fan_generic, integration @@ -45,6 +47,8 @@ async def test_generic_fan( assert state assert state.state == STATE_OFF + set_value_response(client, True) + # Test turn on no speed await hass.services.async_call( "fan", @@ -65,6 +69,7 @@ async def test_generic_fan( assert args["value"] == 255 client.async_send_command.reset_mock() + set_value_response(client, True) # Due to optimistic updates, the state should be on even though the Z-Wave state # hasn't been updated yet @@ -93,6 +98,7 @@ async def test_generic_fan( assert args["value"] == 66 client.async_send_command.reset_mock() + set_value_response(client, True) # Test setting unknown speed with pytest.raises(MultipleInvalid): @@ -104,6 +110,7 @@ async def test_generic_fan( ) client.async_send_command.reset_mock() + set_value_response(client, True) # Test turning off await hass.services.async_call( @@ -125,6 +132,7 @@ async def test_generic_fan( assert args["value"] == 0 client.async_send_command.reset_mock() + set_value_response(client, True) # Test speed update from value updated event event = Event( @@ -151,6 +159,7 @@ async def test_generic_fan( assert state.attributes[ATTR_PERCENTAGE] == 100 client.async_send_command.reset_mock() + set_value_response(client, True) event = Event( type="value updated", @@ -176,6 +185,7 @@ async def test_generic_fan( assert state.attributes[ATTR_PERCENTAGE] == 0 client.async_send_command.reset_mock() + set_value_response(client, True) # Test setting percentage to 0 await hass.services.async_call( @@ -231,6 +241,8 @@ async def test_configurable_speeds_fan( async def get_zwave_speed_from_percentage(percentage): """Set the fan to a particular percentage and get the resulting Zwave speed.""" client.async_send_command.reset_mock() + set_value_response(client, True) + await hass.services.async_call( "fan", "turn_on", @@ -356,6 +368,8 @@ async def test_ge_12730_fan(hass: HomeAssistant, client, ge_12730, integration) async def get_zwave_speed_from_percentage(percentage): """Set the fan to a particular percentage and get the resulting Zwave speed.""" client.async_send_command.reset_mock() + set_value_response(client, True) + await hass.services.async_call( "fan", "turn_on", @@ -448,6 +462,8 @@ async def test_inovelli_lzw36( async def get_zwave_speed_from_percentage(percentage): """Set the fan to a particular percentage and get the resulting Zwave speed.""" client.async_send_command.reset_mock() + set_value_response(client, True) + await hass.services.async_call( "fan", "turn_on", @@ -518,6 +534,8 @@ async def get_percentage_from_zwave_speed(zwave_speed): assert state.attributes[ATTR_PERCENTAGE] is None client.async_send_command.reset_mock() + set_value_response(client, True) + await hass.services.async_call( "fan", "turn_on", @@ -553,6 +571,8 @@ async def test_leviton_zw4sf_fan( async def get_zwave_speed_from_percentage(percentage): """Set the fan to a particular percentage and get the resulting Zwave speed.""" client.async_send_command.reset_mock() + set_value_response(client, True) + await hass.services.async_call( "fan", "turn_on", @@ -640,6 +660,7 @@ async def test_thermostat_fan( await hass.async_block_till_done() client.async_send_command.reset_mock() + set_value_response(client, True) state = hass.states.get(entity_id) assert state @@ -668,6 +689,7 @@ async def test_thermostat_fan( assert args["value"] == 1 client.async_send_command.reset_mock() + set_value_response(client, True) # Test setting unknown preset mode with pytest.raises(ValueError): @@ -679,6 +701,7 @@ async def test_thermostat_fan( ) client.async_send_command.reset_mock() + set_value_response(client, True) # Test turning off await hass.services.async_call( @@ -700,6 +723,7 @@ async def test_thermostat_fan( assert args["value"] client.async_send_command.reset_mock() + set_value_response(client, True) # Test turning on await hass.services.async_call( @@ -721,6 +745,7 @@ async def test_thermostat_fan( assert not args["value"] client.async_send_command.reset_mock() + set_value_response(client, True) # Test fan state update from value updated event event = Event( @@ -746,6 +771,7 @@ async def test_thermostat_fan( assert state.attributes.get(ATTR_FAN_STATE) == "Circulation mode" client.async_send_command.reset_mock() + set_value_response(client, True) # Test unknown fan state update from value updated event event = Event( @@ -771,6 +797,7 @@ async def test_thermostat_fan( assert not state.attributes.get(ATTR_FAN_STATE) client.async_send_command.reset_mock() + set_value_response(client, True) # Test fan mode update from value updated event event = Event( @@ -796,6 +823,7 @@ async def test_thermostat_fan( assert state.attributes.get(ATTR_PRESET_MODE) == "Low" client.async_send_command.reset_mock() + set_value_response(client, True) # Test fan mode update from value updated event for an unknown mode event = Event( @@ -821,6 +849,7 @@ async def test_thermostat_fan( assert not state.attributes.get(ATTR_PRESET_MODE) client.async_send_command.reset_mock() + set_value_response(client, True) # Test fan mode turned off update from value updated event event = Event( @@ -951,6 +980,8 @@ async def test_honeywell_39358_fan( async def get_zwave_speed_from_percentage(percentage): """Set the fan to a particular percentage and get the resulting Zwave speed.""" client.async_send_command.reset_mock() + set_value_response(client, True) + await hass.services.async_call( "fan", "turn_on", diff --git a/tests/components/zwave_js/test_humidifier.py b/tests/components/zwave_js/test_humidifier.py index 23e2dc6831494a..81baca2bc696bf 100644 --- a/tests/components/zwave_js/test_humidifier.py +++ b/tests/components/zwave_js/test_humidifier.py @@ -24,7 +24,11 @@ ) from homeassistant.core import HomeAssistant -from .common import DEHUMIDIFIER_ADC_T3000_ENTITY, HUMIDIFIER_ADC_T3000_ENTITY +from .common import ( + DEHUMIDIFIER_ADC_T3000_ENTITY, + HUMIDIFIER_ADC_T3000_ENTITY, + set_value_response, +) async def test_humidifier( @@ -43,6 +47,7 @@ async def test_humidifier( assert state.attributes[ATTR_MAX_HUMIDITY] == 70 client.async_send_command.reset_mock() + set_value_response(client, True) # Test setting humidity await hass.services.async_call( @@ -68,6 +73,7 @@ async def test_humidifier( assert args["value"] == 41 client.async_send_command.reset_mock() + set_value_response(client, True) # Test de-humidify mode update from value updated event event = Event( @@ -93,6 +99,7 @@ async def test_humidifier( assert state.state == STATE_OFF client.async_send_command.reset_mock() + set_value_response(client, True) # Test auto mode update from value updated event event = Event( @@ -118,6 +125,7 @@ async def test_humidifier( assert state.state == STATE_ON client.async_send_command.reset_mock() + set_value_response(client, True) # Test off mode update from value updated event event = Event( @@ -143,6 +151,7 @@ async def test_humidifier( assert state.state == STATE_OFF client.async_send_command.reset_mock() + set_value_response(client, True) # Test turning off when device is previously humidifying event = Event( @@ -183,6 +192,7 @@ async def test_humidifier( assert args["value"] == int(HumidityControlMode.OFF) client.async_send_command.reset_mock() + set_value_response(client, True) # Test turning off when device is previously auto event = Event( @@ -223,6 +233,7 @@ async def test_humidifier( assert args["value"] == int(HumidityControlMode.DEHUMIDIFY) client.async_send_command.reset_mock() + set_value_response(client, True) # Test turning off when device is previously de-humidifying event = Event( @@ -254,6 +265,7 @@ async def test_humidifier( assert len(client.async_send_command.call_args_list) == 0 client.async_send_command.reset_mock() + set_value_response(client, True) # Test turning off when device is previously off event = Event( @@ -285,6 +297,7 @@ async def test_humidifier( assert len(client.async_send_command.call_args_list) == 0 client.async_send_command.reset_mock() + set_value_response(client, True) # Test turning on when device is previously humidifying event = Event( @@ -316,6 +329,7 @@ async def test_humidifier( assert len(client.async_send_command.call_args_list) == 0 client.async_send_command.reset_mock() + set_value_response(client, True) # Test turning on when device is previously auto event = Event( @@ -347,6 +361,7 @@ async def test_humidifier( assert len(client.async_send_command.call_args_list) == 0 client.async_send_command.reset_mock() + set_value_response(client, True) # Test turning on when device is previously de-humidifying event = Event( @@ -387,6 +402,7 @@ async def test_humidifier( assert args["value"] == int(HumidityControlMode.AUTO) client.async_send_command.reset_mock() + set_value_response(client, True) # Test turning on when device is previously off event = Event( @@ -475,6 +491,7 @@ async def test_humidifier_missing_mode( assert state client.async_send_command.reset_mock() + set_value_response(client, True) # Test turning off when device is previously auto for a device which does not have de-humidify mode event = Event( @@ -533,6 +550,7 @@ async def test_dehumidifier( assert state.attributes[ATTR_MAX_HUMIDITY] == 90 client.async_send_command.reset_mock() + set_value_response(client, True) # Test setting humidity await hass.services.async_call( @@ -558,6 +576,7 @@ async def test_dehumidifier( assert args["value"] == 41 client.async_send_command.reset_mock() + set_value_response(client, True) # Test humidify mode update from value updated event event = Event( @@ -583,6 +602,7 @@ async def test_dehumidifier( assert state.state == STATE_OFF client.async_send_command.reset_mock() + set_value_response(client, True) # Test auto mode update from value updated event event = Event( @@ -608,6 +628,7 @@ async def test_dehumidifier( assert state.state == STATE_ON client.async_send_command.reset_mock() + set_value_response(client, True) # Test off mode update from value updated event event = Event( @@ -633,6 +654,7 @@ async def test_dehumidifier( assert state.state == STATE_OFF client.async_send_command.reset_mock() + set_value_response(client, True) # Test turning off when device is previously de-humidifying event = Event( @@ -673,6 +695,7 @@ async def test_dehumidifier( assert args["value"] == int(HumidityControlMode.OFF) client.async_send_command.reset_mock() + set_value_response(client, True) # Test turning off when device is previously auto event = Event( @@ -713,6 +736,7 @@ async def test_dehumidifier( assert args["value"] == int(HumidityControlMode.HUMIDIFY) client.async_send_command.reset_mock() + set_value_response(client, True) # Test turning off when device is previously humidifying event = Event( @@ -744,6 +768,7 @@ async def test_dehumidifier( assert len(client.async_send_command.call_args_list) == 0 client.async_send_command.reset_mock() + set_value_response(client, True) # Test turning off when device is previously off event = Event( @@ -775,6 +800,7 @@ async def test_dehumidifier( assert len(client.async_send_command.call_args_list) == 0 client.async_send_command.reset_mock() + set_value_response(client, True) # Test turning on when device is previously de-humidifying event = Event( @@ -806,6 +832,7 @@ async def test_dehumidifier( assert len(client.async_send_command.call_args_list) == 0 client.async_send_command.reset_mock() + set_value_response(client, True) # Test turning on when device is previously auto event = Event( @@ -837,6 +864,7 @@ async def test_dehumidifier( assert len(client.async_send_command.call_args_list) == 0 client.async_send_command.reset_mock() + set_value_response(client, True) # Test turning on when device is previously humidifying event = Event( @@ -877,6 +905,7 @@ async def test_dehumidifier( assert args["value"] == int(HumidityControlMode.AUTO) client.async_send_command.reset_mock() + set_value_response(client, True) # Test turning on when device is previously off event = Event( @@ -942,6 +971,7 @@ async def test_dehumidifier( assert state.state == STATE_UNKNOWN client.async_send_command.reset_mock() + set_value_response(client, True) await hass.services.async_call( HUMIDIFIER_DOMAIN, diff --git a/tests/components/zwave_js/test_init.py b/tests/components/zwave_js/test_init.py index 3ec1f113b3e086..a23945b6720424 100644 --- a/tests/components/zwave_js/test_init.py +++ b/tests/components/zwave_js/test_init.py @@ -1014,7 +1014,7 @@ async def test_node_removed( old_device = dev_reg.async_get_device(identifiers={(DOMAIN, device_id)}) assert old_device.id - event = {"node": node, "replaced": False} + event = {"node": node, "reason": 0} client.driver.controller.emit("node removed", event) await hass.async_block_till_done() @@ -1047,14 +1047,14 @@ async def test_replace_same_node( assert hass.states.get(AIR_TEMPERATURE_SENSOR) - # A replace node event has the extra field "replaced" set to True + # A replace node event has the extra field "reason" # to distinguish it from an exclusion event = Event( type="node removed", data={ "source": "controller", "event": "node removed", - "replaced": True, + "reason": 3, "node": multisensor_6_state, }, ) @@ -1171,7 +1171,7 @@ async def test_replace_different_node( data={ "source": "controller", "event": "node removed", - "replaced": True, + "reason": 3, "node": multisensor_6_state, }, ) @@ -1345,7 +1345,7 @@ async def test_disabled_node_status_entity_on_node_replaced( data={ "source": "controller", "event": "node removed", - "replaced": True, + "reason": 3, "node": zp3111_state, }, ) diff --git a/tests/components/zwave_js/test_light.py b/tests/components/zwave_js/test_light.py index 3a862ee3a0c427..98100066131f09 100644 --- a/tests/components/zwave_js/test_light.py +++ b/tests/components/zwave_js/test_light.py @@ -32,6 +32,7 @@ BULB_6_MULTI_COLOR_LIGHT_ENTITY, EATON_RF9640_ENTITY, ZEN_31_ENTITY, + set_value_response, ) HSM200_V1_ENTITY = "light.hsm200" @@ -51,6 +52,8 @@ async def test_light( assert state.attributes[ATTR_SUPPORTED_FEATURES] == LightEntityFeature.TRANSITION assert state.attributes[ATTR_SUPPORTED_COLOR_MODES] == ["color_temp", "hs"] + set_value_response(client, True) + # Test turning on await hass.services.async_call( "light", @@ -78,6 +81,7 @@ async def test_light( assert state.state == STATE_ON client.async_send_command.reset_mock() + set_value_response(client, True) # Test turning on with transition await hass.services.async_call( @@ -100,6 +104,7 @@ async def test_light( assert args["options"]["transitionDuration"] == "10s" client.async_send_command.reset_mock() + set_value_response(client, True) # Test brightness update from value updated event event = Event( @@ -139,6 +144,7 @@ async def test_light( assert len(client.async_send_command.call_args_list) == 1 client.async_send_command.reset_mock() + set_value_response(client, True) # Test turning on with brightness await hass.services.async_call( @@ -161,6 +167,7 @@ async def test_light( assert args["options"]["transitionDuration"] == "default" client.async_send_command.reset_mock() + set_value_response(client, True) # Test turning on with brightness and transition await hass.services.async_call( @@ -187,6 +194,7 @@ async def test_light( assert args["options"]["transitionDuration"] == "20s" client.async_send_command.reset_mock() + set_value_response(client, True) # Test turning on with rgb color await hass.services.async_call( @@ -254,6 +262,7 @@ async def test_light( assert ATTR_COLOR_TEMP not in state.attributes client.async_send_command.reset_mock() + set_value_response(client, True) # Test turning on with same rgb color await hass.services.async_call( @@ -266,6 +275,7 @@ async def test_light( assert len(client.async_send_command.call_args_list) == 2 client.async_send_command.reset_mock() + set_value_response(client, True) # Test turning on with rgb color and transition await hass.services.async_call( @@ -308,6 +318,7 @@ async def test_light( } client.async_send_command.reset_mock() + set_value_response(client, True) # Test color temp update from value updated event red_event = Event( @@ -367,6 +378,7 @@ async def test_light( assert len(client.async_send_command.call_args_list) == 2 client.async_send_command.reset_mock() + set_value_response(client, True) # Test turning on with color temp and transition await hass.services.async_call( @@ -385,6 +397,7 @@ async def test_light( assert args["options"]["transitionDuration"] == "35s" client.async_send_command.reset_mock() + set_value_response(client, True) # Test turning off await hass.services.async_call( @@ -406,6 +419,7 @@ async def test_light( assert args["value"] == 0 client.async_send_command.reset_mock() + set_value_response(client, True) # Test brightness update to None from value updated event event = Event( @@ -461,6 +475,8 @@ async def test_rgbw_light(hass: HomeAssistant, client, zen_31, integration) -> N assert state.state == STATE_ON assert state.attributes[ATTR_SUPPORTED_FEATURES] == LightEntityFeature.TRANSITION + set_value_response(client, True) + # Test turning on await hass.services.async_call( "light", @@ -514,6 +530,8 @@ async def test_black_is_off( state = hass.states.get(HSM200_V1_ENTITY) assert state.state == STATE_ON + set_value_response(client, True) + # Attempt to turn on the light and ensure it defaults to white await hass.services.async_call( LIGHT_DOMAIN, @@ -533,6 +551,7 @@ async def test_black_is_off( assert args["value"] == {"red": 255, "green": 255, "blue": 255} client.async_send_command.reset_mock() + set_value_response(client, True) # Force the light to turn off event = Event( @@ -614,6 +633,7 @@ async def test_black_is_off( assert args["value"] == {"red": 0, "green": 0, "blue": 0} client.async_send_command.reset_mock() + set_value_response(client, True) # Assert that the last color is restored await hass.services.async_call( @@ -634,6 +654,7 @@ async def test_black_is_off( assert args["value"] == {"red": 0, "green": 255, "blue": 0} client.async_send_command.reset_mock() + set_value_response(client, True) # Force the light to turn on event = Event( @@ -663,6 +684,7 @@ async def test_black_is_off( assert state.state == STATE_UNKNOWN client.async_send_command.reset_mock() + set_value_response(client, True) # Assert that call fails if attribute is added to service call await hass.services.async_call( diff --git a/tests/components/zwave_js/test_lock.py b/tests/components/zwave_js/test_lock.py index 5a5711d9dad281..ad573338f38bae 100644 --- a/tests/components/zwave_js/test_lock.py +++ b/tests/components/zwave_js/test_lock.py @@ -31,7 +31,11 @@ from homeassistant.core import HomeAssistant from homeassistant.exceptions import HomeAssistantError -from .common import SCHLAGE_BE469_LOCK_ENTITY, replace_value_of_zwave_value +from .common import ( + SCHLAGE_BE469_LOCK_ENTITY, + replace_value_of_zwave_value, + set_value_response, +) async def test_door_lock( @@ -44,6 +48,8 @@ async def test_door_lock( assert state assert state.state == STATE_UNLOCKED + set_value_response(client, True) + # Test locking await hass.services.async_call( LOCK_DOMAIN, @@ -64,6 +70,7 @@ async def test_door_lock( assert args["value"] == 255 client.async_send_command.reset_mock() + set_value_response(client, True) # Test locked update from value updated event event = Event( @@ -88,6 +95,7 @@ async def test_door_lock( assert hass.states.get(SCHLAGE_BE469_LOCK_ENTITY).state == STATE_LOCKED client.async_send_command.reset_mock() + set_value_response(client, True) # Test unlocking await hass.services.async_call( @@ -109,6 +117,7 @@ async def test_door_lock( assert args["value"] == 0 client.async_send_command.reset_mock() + set_value_response(client, True) # Test set usercode service await hass.services.async_call( @@ -135,6 +144,7 @@ async def test_door_lock( assert args["value"] == "1234" client.async_send_command.reset_mock() + set_value_response(client, True) # Test clear usercode await hass.services.async_call( @@ -157,6 +167,7 @@ async def test_door_lock( assert args["value"] == 0 client.async_send_command.reset_mock() + set_value_response(client, True) client.async_send_command.side_effect = FailedZWaveCommand("test", 1, "test") # Test set usercode service error handling @@ -182,6 +193,7 @@ async def test_door_lock( ) client.async_send_command.reset_mock() + set_value_response(client, True) event = Event( type="dead", diff --git a/tests/components/zwave_js/test_number.py b/tests/components/zwave_js/test_number.py index 7229d10ebad30c..d701a20a278134 100644 --- a/tests/components/zwave_js/test_number.py +++ b/tests/components/zwave_js/test_number.py @@ -9,7 +9,7 @@ from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers import entity_registry as er -from .common import BASIC_NUMBER_ENTITY +from .common import BASIC_NUMBER_ENTITY, set_value_response from tests.common import MockConfigEntry @@ -27,6 +27,8 @@ async def test_number( assert state assert state.state == "75.0" + set_value_response(client, True) + # Test turn on setting value await hass.services.async_call( "number", @@ -47,6 +49,7 @@ async def test_number( assert args["value"] == 30.0 client.async_send_command.reset_mock() + set_value_response(client, True) # Test value update from value updated event event = Event( @@ -116,6 +119,8 @@ async def test_number_writeable( await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() + set_value_response(client, True) + # Test turn on setting value await hass.services.async_call( "number", @@ -151,6 +156,8 @@ async def test_volume_number( assert state.attributes["max"] == 1.0 assert state.attributes["min"] == 0 + set_value_response(client, True) + # Test turn on setting value await hass.services.async_call( "number", @@ -171,6 +178,7 @@ async def test_volume_number( assert args["value"] == 30 client.async_send_command.reset_mock() + set_value_response(client, True) # Test value update from value updated event event = Event( diff --git a/tests/components/zwave_js/test_select.py b/tests/components/zwave_js/test_select.py index c63f0c429fd41e..872b114b7e3130 100644 --- a/tests/components/zwave_js/test_select.py +++ b/tests/components/zwave_js/test_select.py @@ -11,7 +11,7 @@ from homeassistant.core import HomeAssistant import homeassistant.helpers.entity_registry as er -from .common import replace_value_of_zwave_value +from .common import replace_value_of_zwave_value, set_value_response DEFAULT_TONE_SELECT_ENTITY = "select.indoor_siren_6_default_tone_2" PROTECTION_SELECT_ENTITY = "select.family_room_combo_local_protection_state" @@ -69,6 +69,8 @@ async def test_default_tone_select( assert entity_entry assert entity_entry.entity_category is EntityCategory.CONFIG + set_value_response(client, True) + # Test select option with string value await hass.services.async_call( "select", @@ -89,6 +91,7 @@ async def test_default_tone_select( assert args["value"] == 30 client.async_send_command.reset_mock() + set_value_response(client, True) # Test value update from value updated event event = Event( @@ -140,6 +143,8 @@ async def test_protection_select( assert entity_entry assert entity_entry.entity_category is EntityCategory.CONFIG + set_value_response(client, True) + # Test select option with string value await hass.services.async_call( "select", @@ -160,6 +165,7 @@ async def test_protection_select( assert args["value"] == 1 client.async_send_command.reset_mock() + set_value_response(client, True) # Test value update from value updated event event = Event( @@ -227,6 +233,8 @@ async def test_multilevel_switch_select( "Siren & Strobe FULL Alarm", ] + set_value_response(client, True) + # Test select option with string value await hass.services.async_call( "select", @@ -247,6 +255,7 @@ async def test_multilevel_switch_select( assert args["value"] == 33 client.async_send_command.reset_mock() + set_value_response(client, True) # Test value update from value updated event event = Event( diff --git a/tests/components/zwave_js/test_services.py b/tests/components/zwave_js/test_services.py index 54638358fe7d1c..7ec884fe550173 100644 --- a/tests/components/zwave_js/test_services.py +++ b/tests/components/zwave_js/test_services.py @@ -47,6 +47,7 @@ CLIMATE_EUROTRONICS_SPIRIT_Z_ENTITY, CLIMATE_RADIO_THERMOSTAT_ENTITY, SCHLAGE_BE469_LOCK_ENTITY, + set_value_response, ) from tests.common import MockConfigEntry @@ -60,6 +61,8 @@ async def test_set_config_parameter( ent_reg = async_get_ent_reg(hass) entity_entry = ent_reg.async_get(AIR_TEMPERATURE_SENSOR) + set_value_response(client, True) + # Test setting config parameter by property and property_key await hass.services.async_call( DOMAIN, @@ -86,6 +89,7 @@ async def test_set_config_parameter( assert args["value"] == 1 client.async_send_command_no_wait.reset_mock() + set_value_response(client, True) # Test setting config parameter value in hex await hass.services.async_call( @@ -113,6 +117,7 @@ async def test_set_config_parameter( assert args["value"] == 1 client.async_send_command_no_wait.reset_mock() + set_value_response(client, True) # Test setting parameter by property name await hass.services.async_call( @@ -139,6 +144,7 @@ async def test_set_config_parameter( assert args["value"] == 1 client.async_send_command_no_wait.reset_mock() + set_value_response(client, True) # Test setting parameter by property name and state label await hass.services.async_call( @@ -165,6 +171,7 @@ async def test_set_config_parameter( assert args["value"] == 2 client.async_send_command_no_wait.reset_mock() + set_value_response(client, True) # Test using area ID area_reg = async_get_area_reg(hass) @@ -194,6 +201,7 @@ async def test_set_config_parameter( assert args["value"] == 2 client.async_send_command_no_wait.reset_mock() + set_value_response(client, True) # Test setting parameter by property and bitmask await hass.services.async_call( @@ -221,6 +229,7 @@ async def test_set_config_parameter( assert args["value"] == 1 client.async_send_command_no_wait.reset_mock() + set_value_response(client, True) # Test groups get expanded assert await async_setup_component(hass, "group", {}) @@ -250,6 +259,7 @@ async def test_set_config_parameter( assert args["value"] == 1 client.async_send_command_no_wait.reset_mock() + set_value_response(client, True) # Test that we can't include a bitmask value if parameter is a string with pytest.raises(vol.Invalid): @@ -320,6 +330,7 @@ async def test_set_config_parameter( assert args["value"] == 1 client.async_send_command_no_wait.reset_mock() + set_value_response(client, True) # Test that when a device is awake, we call async_send_command instead of # async_send_command_no_wait @@ -414,6 +425,8 @@ async def test_bulk_set_config_parameters( identifiers={get_device_id(client.driver, multisensor_6)} ) assert device + set_value_response(client, True) + # Test setting config parameter by property and property_key await hass.services.async_call( DOMAIN, @@ -438,6 +451,7 @@ async def test_bulk_set_config_parameters( assert args["value"] == 241 client.async_send_command_no_wait.reset_mock() + set_value_response(client, True) # Test using area ID area_reg = async_get_area_reg(hass) @@ -466,6 +480,7 @@ async def test_bulk_set_config_parameters( assert args["value"] == 241 client.async_send_command_no_wait.reset_mock() + set_value_response(client, True) await hass.services.async_call( DOMAIN, @@ -496,6 +511,7 @@ async def test_bulk_set_config_parameters( assert args["value"] == 241 client.async_send_command_no_wait.reset_mock() + set_value_response(client, True) # Test using hex values for config parameter values await hass.services.async_call( @@ -527,6 +543,7 @@ async def test_bulk_set_config_parameters( assert args["value"] == 241 client.async_send_command_no_wait.reset_mock() + set_value_response(client, True) await hass.services.async_call( DOMAIN, @@ -557,6 +574,7 @@ async def test_bulk_set_config_parameters( assert args["value"] == 241 client.async_send_command_no_wait.reset_mock() + set_value_response(client, True) # Test that when a device is awake, we call async_send_command instead of # async_send_command_no_wait @@ -590,6 +608,7 @@ async def test_bulk_set_config_parameters( assert args["value"] == 241 client.async_send_command.reset_mock() + set_value_response(client, True) # Test groups get expanded assert await async_setup_component(hass, "group", {}) @@ -762,6 +781,7 @@ async def test_set_value( identifiers={get_device_id(client.driver, climate_danfoss_lc_13)} ) assert device + set_value_response(client, True) await hass.services.async_call( DOMAIN, @@ -787,6 +807,7 @@ async def test_set_value( assert args["value"] == 2 client.async_send_command_no_wait.reset_mock() + set_value_response(client, True) # Test bitmask as value and non bool as bool await hass.services.async_call( @@ -814,6 +835,7 @@ async def test_set_value( assert args["value"] == 2 client.async_send_command.reset_mock() + set_value_response(client, True) # Test using area ID area_reg = async_get_area_reg(hass) @@ -844,6 +866,7 @@ async def test_set_value( assert args["value"] == 2 client.async_send_command.reset_mock() + set_value_response(client, True) # Test groups get expanded assert await async_setup_component(hass, "group", {}) @@ -875,7 +898,7 @@ async def test_set_value( client.async_send_command.reset_mock() # Test that when a command fails we raise an exception - client.async_send_command.return_value = {"success": False} + set_value_response(client, False) with pytest.raises(HomeAssistantError): await hass.services.async_call( @@ -924,7 +947,7 @@ async def test_set_value_string( hass: HomeAssistant, client, climate_danfoss_lc_13, lock_schlage_be469, integration ) -> None: """Test set_value service converts number to string when needed.""" - client.async_send_command.return_value = {"success": True} + set_value_response(client, True) # Test that number gets converted to a string when needed await hass.services.async_call( @@ -957,6 +980,8 @@ async def test_set_value_options( hass: HomeAssistant, client, aeon_smart_switch_6, integration ) -> None: """Test set_value service with options.""" + set_value_response(client, True) + await hass.services.async_call( DOMAIN, SERVICE_SET_VALUE, @@ -993,6 +1018,8 @@ async def test_set_value_gather( integration, ) -> None: """Test the set_value service gather functionality.""" + set_value_response(client, True) + # Test setting value by property and validate that the first node # which triggers an error doesn't prevent the second one to be called. with pytest.raises(HomeAssistantError): @@ -1036,6 +1063,8 @@ async def test_multicast_set_value( integration, ) -> None: """Test multicast_set_value service.""" + set_value_response(client, True) + # Test successful multicast call await hass.services.async_call( DOMAIN, @@ -1068,6 +1097,7 @@ async def test_multicast_set_value( assert args["value"] == 2 client.async_send_command.reset_mock() + set_value_response(client, True) # Test successful multicast call with hex value await hass.services.async_call( @@ -1101,6 +1131,7 @@ async def test_multicast_set_value( assert args["value"] == 2 client.async_send_command.reset_mock() + set_value_response(client, True) # Test using area ID dev_reg = async_get_dev_reg(hass) @@ -1144,6 +1175,7 @@ async def test_multicast_set_value( assert args["value"] == 2 client.async_send_command.reset_mock() + set_value_response(client, True) # Test groups get expanded for multicast call assert await async_setup_component(hass, "group", {}) @@ -1178,6 +1210,7 @@ async def test_multicast_set_value( assert args["value"] == 2 client.async_send_command.reset_mock() + set_value_response(client, True) # Test successful broadcast call await hass.services.async_call( @@ -1204,6 +1237,7 @@ async def test_multicast_set_value( assert args["value"] == 2 client.async_send_command.reset_mock() + set_value_response(client, True) # Test sending one node without broadcast uses the node.set_value command instead await hass.services.async_call( @@ -1224,6 +1258,7 @@ async def test_multicast_set_value( assert args["command"] == "node.set_value" client.async_send_command_no_wait.reset_mock() + set_value_response(client, True) # Test no device, entity, or broadcast flag raises error with pytest.raises(vol.Invalid): @@ -1240,7 +1275,7 @@ async def test_multicast_set_value( ) # Test that when a command is unsuccessful we raise an exception - client.async_send_command.return_value = {"success": False} + set_value_response(client, False) with pytest.raises(HomeAssistantError): await hass.services.async_call( @@ -1335,6 +1370,8 @@ async def test_multicast_set_value_options( integration, ) -> None: """Test multicast_set_value service with options.""" + set_value_response(client, True) + await hass.services.async_call( DOMAIN, SERVICE_MULTICAST_SET_VALUE, @@ -1381,7 +1418,7 @@ async def test_multicast_set_value_string( integration, ) -> None: """Test multicast_set_value service converts number to string when needed.""" - client.async_send_command.return_value = {"success": True} + client.async_send_command.return_value = {"result": {"status": 255}} # Test that number gets converted to a string when needed await hass.services.async_call( diff --git a/tests/components/zwave_js/test_siren.py b/tests/components/zwave_js/test_siren.py index 210339e22d7d90..d0d35f4d6ff822 100644 --- a/tests/components/zwave_js/test_siren.py +++ b/tests/components/zwave_js/test_siren.py @@ -9,6 +9,8 @@ from homeassistant.const import STATE_OFF, STATE_ON, STATE_UNKNOWN from homeassistant.core import HomeAssistant +from .common import set_value_response + SIREN_ENTITY = "siren.indoor_siren_6_2" TONE_ID_VALUE_ID = { @@ -106,6 +108,8 @@ async def test_siren( 255: "default", } + set_value_response(client, True) + # Test turn on with default await hass.services.async_call( "siren", @@ -126,6 +130,7 @@ async def test_siren( assert args["value"] == 255 client.async_send_command.reset_mock() + set_value_response(client, True) # Test value update from value updated event event = Event( @@ -175,6 +180,7 @@ async def test_siren( assert args["options"] == {"volume": 50} client.async_send_command.reset_mock() + set_value_response(client, True) # Test turn on with specific tone ID and volume level await hass.services.async_call( @@ -201,6 +207,7 @@ async def test_siren( assert args["options"] == {"volume": 50} client.async_send_command.reset_mock() + set_value_response(client, True) # Test turn off await hass.services.async_call( @@ -222,6 +229,7 @@ async def test_siren( assert args["value"] == 0 client.async_send_command.reset_mock() + set_value_response(client, True) # Test value update from value updated event event = Event( diff --git a/tests/components/zwave_js/test_switch.py b/tests/components/zwave_js/test_switch.py index ebf7d9f441fa1e..e5e852584174a7 100644 --- a/tests/components/zwave_js/test_switch.py +++ b/tests/components/zwave_js/test_switch.py @@ -12,7 +12,7 @@ from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers import entity_registry as er -from .common import SWITCH_ENTITY, replace_value_of_zwave_value +from .common import SWITCH_ENTITY, replace_value_of_zwave_value, set_value_response async def test_switch( @@ -25,6 +25,8 @@ async def test_switch( assert state assert state.state == STATE_OFF + set_value_response(client, True) + # Test turning on await hass.services.async_call( "switch", "turn_on", {"entity_id": SWITCH_ENTITY}, blocking=True @@ -63,6 +65,9 @@ async def test_switch( state = hass.states.get(SWITCH_ENTITY) assert state.state == "on" + client.async_send_command.reset_mock() + set_value_response(client, True) + # Test turning off await hass.services.async_call( "switch", "turn_off", {"entity_id": SWITCH_ENTITY}, blocking=True @@ -90,6 +95,8 @@ async def test_barrier_signaling_switch( assert state assert state.state == "on" + set_value_response(client, True) + # Test turning off await hass.services.async_call( DOMAIN, SERVICE_TURN_OFF, {"entity_id": entity}, blocking=True @@ -114,6 +121,7 @@ async def test_barrier_signaling_switch( assert state.state == STATE_OFF client.async_send_command.reset_mock() + set_value_response(client, True) # Test turning on await hass.services.async_call( @@ -241,6 +249,7 @@ async def test_config_parameter_switch( assert state.state == STATE_ON client.async_send_command.reset_mock() + set_value_response(client, True) # Test turning on await hass.services.async_call( @@ -259,6 +268,7 @@ async def test_config_parameter_switch( } client.async_send_command.reset_mock() + set_value_response(client, True) # Test turning off await hass.services.async_call( diff --git a/tests/components/zwave_js/test_update.py b/tests/components/zwave_js/test_update.py index dcd71789e840bb..f30812e7fedc9d 100644 --- a/tests/components/zwave_js/test_update.py +++ b/tests/components/zwave_js/test_update.py @@ -341,7 +341,9 @@ async def test_update_entity_progress( assert attrs[ATTR_LATEST_VERSION] == "11.2.4" client.async_send_command.reset_mock() - client.async_send_command.return_value = {"success": False} + client.async_send_command.return_value = { + "result": {"status": 2, "success": False, "reInterview": False} + } # Test successful install call without a version install_task = hass.async_create_task( @@ -437,7 +439,9 @@ async def test_update_entity_install_failed( assert attrs[ATTR_LATEST_VERSION] == "11.2.4" client.async_send_command.reset_mock() - client.async_send_command.return_value = {"success": False} + client.async_send_command.return_value = { + "result": {"status": 2, "success": False, "reInterview": False} + } # Test install call - we expect it to finish fail install_task = hass.async_create_task( @@ -710,7 +714,9 @@ async def test_update_entity_full_restore_data_update_available( assert state.attributes[ATTR_SKIPPED_VERSION] is None assert state.attributes[ATTR_LATEST_VERSION] == "11.2.4" - client.async_send_command.return_value = {"success": True} + client.async_send_command.return_value = { + "result": {"status": 255, "success": True, "reInterview": False} + } # Test successful install call without a version install_task = hass.async_create_task(