diff --git a/homeassistant/components/mqtt/__init__.py b/homeassistant/components/mqtt/__init__.py index a0527cfe427..81c44ac8aea 100644 --- a/homeassistant/components/mqtt/__init__.py +++ b/homeassistant/components/mqtt/__init__.py @@ -44,6 +44,7 @@ from . import config_flow # noqa: F401 pylint: disable=unused-import from . import debug_info, discovery from .const import ( ATTR_DISCOVERY_HASH, + ATTR_DISCOVERY_PAYLOAD, ATTR_DISCOVERY_TOPIC, ATTR_PAYLOAD, ATTR_QOS, @@ -1169,6 +1170,7 @@ class MqttDiscoveryUpdate(Entity): _LOGGER.info( "Got update for entity with hash: %s '%s'", discovery_hash, payload, ) + old_payload = self._discovery_data[ATTR_DISCOVERY_PAYLOAD] debug_info.update_entity_discovery_data(self.hass, payload, self.entity_id) if not payload: # Empty payload: Remove component @@ -1176,9 +1178,13 @@ class MqttDiscoveryUpdate(Entity): self._cleanup_discovery_on_remove() await _async_remove_state_and_registry_entry(self) elif self._discovery_update: - # Non-empty payload: Notify component - _LOGGER.info("Updating component: %s", self.entity_id) - await self._discovery_update(payload) + if old_payload != self._discovery_data[ATTR_DISCOVERY_PAYLOAD]: + # Non-empty, changed payload: Notify component + _LOGGER.info("Updating component: %s", self.entity_id) + await self._discovery_update(payload) + else: + # Non-empty, unchanged payload: Ignore to avoid changing states + _LOGGER.info("Ignoring unchanged update for: %s", self.entity_id) if discovery_hash: debug_info.add_entity_discovery_data( diff --git a/homeassistant/components/mqtt/binary_sensor.py b/homeassistant/components/mqtt/binary_sensor.py index cd69967e6a7..5d69bfde4f6 100644 --- a/homeassistant/components/mqtt/binary_sensor.py +++ b/homeassistant/components/mqtt/binary_sensor.py @@ -169,7 +169,8 @@ class MqttBinarySensor( if expire_after is not None and expire_after > 0: - # When expire_after is set, and we receive a message, assume device is not expired since it has to be to receive the message + # When expire_after is set, and we receive a message, assume device is + # not expired since it has to be to receive the message self._expired = False # Reset old trigger diff --git a/homeassistant/components/mqtt/light/schema_template.py b/homeassistant/components/mqtt/light/schema_template.py index a9f18e7039b..d14cda70bb6 100644 --- a/homeassistant/components/mqtt/light/schema_template.py +++ b/homeassistant/components/mqtt/light/schema_template.py @@ -101,10 +101,10 @@ async def async_setup_entity_template( config, async_add_entities, config_entry, discovery_data ): """Set up a MQTT Template light.""" - async_add_entities([MqttTemplate(config, config_entry, discovery_data)]) + async_add_entities([MqttLightTemplate(config, config_entry, discovery_data)]) -class MqttTemplate( +class MqttLightTemplate( MqttAttributes, MqttAvailability, MqttDiscoveryUpdate, diff --git a/tests/components/mqtt/test_alarm_control_panel.py b/tests/components/mqtt/test_alarm_control_panel.py index aa6452fd9c8..734e1fd552f 100644 --- a/tests/components/mqtt/test_alarm_control_panel.py +++ b/tests/components/mqtt/test_alarm_control_panel.py @@ -28,6 +28,7 @@ from .test_common import ( help_test_discovery_removal, help_test_discovery_update, help_test_discovery_update_attr, + help_test_discovery_update_unchanged, help_test_entity_debug_info_message, help_test_entity_device_info_remove, help_test_entity_device_info_update, @@ -42,6 +43,7 @@ from .test_common import ( help_test_update_with_json_attrs_not_dict, ) +from tests.async_mock import patch from tests.common import assert_setup_component, async_fire_mqtt_message from tests.components.alarm_control_panel import common @@ -575,6 +577,20 @@ async def test_discovery_update_alarm(hass, mqtt_mock, caplog): ) +async def test_discovery_update_unchanged_alarm(hass, mqtt_mock, caplog): + """Test update of discovered alarm_control_panel.""" + config1 = copy.deepcopy(DEFAULT_CONFIG[alarm_control_panel.DOMAIN]) + config1["name"] = "Beer" + + data1 = json.dumps(config1) + with patch( + "homeassistant.components.mqtt.alarm_control_panel.MqttAlarm.discovery_update" + ) as discovery_update: + await help_test_discovery_update_unchanged( + hass, mqtt_mock, caplog, alarm_control_panel.DOMAIN, data1, discovery_update + ) + + @pytest.mark.no_fail_on_log_exception async def test_discovery_broken(hass, mqtt_mock, caplog): """Test handling of bad discovery message.""" diff --git a/tests/components/mqtt/test_binary_sensor.py b/tests/components/mqtt/test_binary_sensor.py index b909a0592e0..c739f4378d1 100644 --- a/tests/components/mqtt/test_binary_sensor.py +++ b/tests/components/mqtt/test_binary_sensor.py @@ -26,6 +26,7 @@ from .test_common import ( help_test_discovery_removal, help_test_discovery_update, help_test_discovery_update_attr, + help_test_discovery_update_unchanged, help_test_entity_debug_info_message, help_test_entity_device_info_remove, help_test_entity_device_info_update, @@ -593,6 +594,20 @@ async def test_discovery_update_binary_sensor(hass, mqtt_mock, caplog): ) +async def test_discovery_update_unchanged_binary_sensor(hass, mqtt_mock, caplog): + """Test update of discovered binary_sensor.""" + config1 = copy.deepcopy(DEFAULT_CONFIG[binary_sensor.DOMAIN]) + config1["name"] = "Beer" + + data1 = json.dumps(config1) + with patch( + "homeassistant.components.mqtt.binary_sensor.MqttBinarySensor.discovery_update" + ) as discovery_update: + await help_test_discovery_update_unchanged( + hass, mqtt_mock, caplog, binary_sensor.DOMAIN, data1, discovery_update + ) + + async def test_expiration_on_discovery_and_discovery_update_of_binary_sensor( hass, mqtt_mock, legacy_patchable_time, caplog ): diff --git a/tests/components/mqtt/test_camera.py b/tests/components/mqtt/test_camera.py index 6869b530668..22f714fdcf7 100644 --- a/tests/components/mqtt/test_camera.py +++ b/tests/components/mqtt/test_camera.py @@ -16,6 +16,7 @@ from .test_common import ( help_test_discovery_removal, help_test_discovery_update, help_test_discovery_update_attr, + help_test_discovery_update_unchanged, help_test_entity_debug_info_message, help_test_entity_device_info_remove, help_test_entity_device_info_update, @@ -30,6 +31,7 @@ from .test_common import ( help_test_update_with_json_attrs_not_dict, ) +from tests.async_mock import patch from tests.common import async_fire_mqtt_message DEFAULT_CONFIG = { @@ -153,14 +155,25 @@ async def test_discovery_update_camera(hass, mqtt_mock, caplog): entry = hass.config_entries.async_entries(mqtt.DOMAIN)[0] await async_start(hass, "homeassistant", entry) - data1 = '{ "name": "Beer",' ' "topic": "test_topic"}' - data2 = '{ "name": "Milk",' ' "topic": "test_topic"}' + data1 = '{ "name": "Beer", "topic": "test_topic"}' + data2 = '{ "name": "Milk", "topic": "test_topic"}' await help_test_discovery_update( hass, mqtt_mock, caplog, camera.DOMAIN, data1, data2 ) +async def test_discovery_update_unchanged_camera(hass, mqtt_mock, caplog): + """Test update of discovered camera.""" + data1 = '{ "name": "Beer", "topic": "test_topic"}' + with patch( + "homeassistant.components.mqtt.camera.MqttCamera.discovery_update" + ) as discovery_update: + await help_test_discovery_update_unchanged( + hass, mqtt_mock, caplog, camera.DOMAIN, data1, discovery_update + ) + + @pytest.mark.no_fail_on_log_exception async def test_discovery_broken(hass, mqtt_mock, caplog): """Test handling of bad discovery message.""" @@ -168,7 +181,7 @@ async def test_discovery_broken(hass, mqtt_mock, caplog): await async_start(hass, "homeassistant", entry) data1 = '{ "name": "Beer" }' - data2 = '{ "name": "Milk",' ' "topic": "test_topic"}' + data2 = '{ "name": "Milk", "topic": "test_topic"}' await help_test_discovery_broken( hass, mqtt_mock, caplog, camera.DOMAIN, data1, data2 diff --git a/tests/components/mqtt/test_climate.py b/tests/components/mqtt/test_climate.py index 6a7bdf0b7e6..d60af211d71 100644 --- a/tests/components/mqtt/test_climate.py +++ b/tests/components/mqtt/test_climate.py @@ -34,6 +34,7 @@ from .test_common import ( help_test_discovery_removal, help_test_discovery_update, help_test_discovery_update_attr, + help_test_discovery_update_unchanged, help_test_entity_debug_info_message, help_test_entity_device_info_remove, help_test_entity_device_info_update, @@ -48,7 +49,7 @@ from .test_common import ( help_test_update_with_json_attrs_not_dict, ) -from tests.async_mock import call +from tests.async_mock import call, patch from tests.common import async_fire_mqtt_message from tests.components.climate import common @@ -909,11 +910,22 @@ async def test_discovery_update_climate(hass, mqtt_mock, caplog): ) +async def test_discovery_update_unchanged_climate(hass, mqtt_mock, caplog): + """Test update of discovered climate.""" + data1 = '{ "name": "Beer" }' + with patch( + "homeassistant.components.mqtt.climate.MqttClimate.discovery_update" + ) as discovery_update: + await help_test_discovery_update_unchanged( + hass, mqtt_mock, caplog, CLIMATE_DOMAIN, data1, discovery_update + ) + + @pytest.mark.no_fail_on_log_exception async def test_discovery_broken(hass, mqtt_mock, caplog): """Test handling of bad discovery message.""" - data1 = '{ "name": "Beer",' ' "power_command_topic": "test_topic#" }' - data2 = '{ "name": "Milk", ' ' "power_command_topic": "test_topic" }' + data1 = '{ "name": "Beer", "power_command_topic": "test_topic#" }' + data2 = '{ "name": "Milk", "power_command_topic": "test_topic" }' await help_test_discovery_broken( hass, mqtt_mock, caplog, CLIMATE_DOMAIN, data1, data2 ) diff --git a/tests/components/mqtt/test_common.py b/tests/components/mqtt/test_common.py index 31566885a37..89bfde22d87 100644 --- a/tests/components/mqtt/test_common.py +++ b/tests/components/mqtt/test_common.py @@ -497,6 +497,29 @@ async def help_test_discovery_update(hass, mqtt_mock, caplog, domain, data1, dat assert state is None +async def help_test_discovery_update_unchanged( + hass, mqtt_mock, caplog, domain, data1, discovery_update +): + """Test update of discovered component without changes. + + This is a test helper for the MqttDiscoveryUpdate mixin. + """ + entry = hass.config_entries.async_entries(mqtt.DOMAIN)[0] + await async_start(hass, "homeassistant", entry) + + async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", data1) + await hass.async_block_till_done() + + state = hass.states.get(f"{domain}.beer") + assert state is not None + assert state.name == "Beer" + + async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", data1) + await hass.async_block_till_done() + + assert not discovery_update.called + + async def help_test_discovery_broken(hass, mqtt_mock, caplog, domain, data1, data2): """Test handling of bad discovery message.""" entry = hass.config_entries.async_entries(mqtt.DOMAIN)[0] diff --git a/tests/components/mqtt/test_cover.py b/tests/components/mqtt/test_cover.py index c3f00badef8..f9036bcfa0f 100644 --- a/tests/components/mqtt/test_cover.py +++ b/tests/components/mqtt/test_cover.py @@ -38,6 +38,7 @@ from .test_common import ( help_test_discovery_removal, help_test_discovery_update, help_test_discovery_update_attr, + help_test_discovery_update_unchanged, help_test_entity_debug_info_message, help_test_entity_device_info_remove, help_test_entity_device_info_update, @@ -52,6 +53,7 @@ from .test_common import ( help_test_update_with_json_attrs_not_dict, ) +from tests.async_mock import patch from tests.common import async_fire_mqtt_message DEFAULT_CONFIG = { @@ -1862,24 +1864,35 @@ async def test_unique_id(hass, mqtt_mock): async def test_discovery_removal_cover(hass, mqtt_mock, caplog): """Test removal of discovered cover.""" - data = '{ "name": "test",' ' "command_topic": "test_topic" }' + data = '{ "name": "test", "command_topic": "test_topic" }' await help_test_discovery_removal(hass, mqtt_mock, caplog, cover.DOMAIN, data) async def test_discovery_update_cover(hass, mqtt_mock, caplog): """Test update of discovered cover.""" - data1 = '{ "name": "Beer",' ' "command_topic": "test_topic" }' - data2 = '{ "name": "Milk",' ' "command_topic": "test_topic" }' + data1 = '{ "name": "Beer", "command_topic": "test_topic" }' + data2 = '{ "name": "Milk", "command_topic": "test_topic" }' await help_test_discovery_update( hass, mqtt_mock, caplog, cover.DOMAIN, data1, data2 ) +async def test_discovery_update_unchanged_cover(hass, mqtt_mock, caplog): + """Test update of discovered cover.""" + data1 = '{ "name": "Beer", "command_topic": "test_topic" }' + with patch( + "homeassistant.components.mqtt.cover.MqttCover.discovery_update" + ) as discovery_update: + await help_test_discovery_update_unchanged( + hass, mqtt_mock, caplog, cover.DOMAIN, data1, discovery_update + ) + + @pytest.mark.no_fail_on_log_exception async def test_discovery_broken(hass, mqtt_mock, caplog): """Test handling of bad discovery message.""" - data1 = '{ "name": "Beer",' ' "command_topic": "test_topic#" }' - data2 = '{ "name": "Milk",' ' "command_topic": "test_topic" }' + data1 = '{ "name": "Beer", "command_topic": "test_topic#" }' + data2 = '{ "name": "Milk", "command_topic": "test_topic" }' await help_test_discovery_broken( hass, mqtt_mock, caplog, cover.DOMAIN, data1, data2 ) diff --git a/tests/components/mqtt/test_fan.py b/tests/components/mqtt/test_fan.py index 6114fe48ff4..e1801c5c15a 100644 --- a/tests/components/mqtt/test_fan.py +++ b/tests/components/mqtt/test_fan.py @@ -19,6 +19,7 @@ from .test_common import ( help_test_discovery_removal, help_test_discovery_update, help_test_discovery_update_attr, + help_test_discovery_update_unchanged, help_test_entity_debug_info_message, help_test_entity_device_info_remove, help_test_entity_device_info_update, @@ -33,6 +34,7 @@ from .test_common import ( help_test_update_with_json_attrs_not_dict, ) +from tests.async_mock import patch from tests.common import async_fire_mqtt_message from tests.components.fan import common @@ -689,22 +691,33 @@ async def test_unique_id(hass, mqtt_mock): async def test_discovery_removal_fan(hass, mqtt_mock, caplog): """Test removal of discovered fan.""" - data = '{ "name": "test",' ' "command_topic": "test_topic" }' + data = '{ "name": "test", "command_topic": "test_topic" }' await help_test_discovery_removal(hass, mqtt_mock, caplog, fan.DOMAIN, data) async def test_discovery_update_fan(hass, mqtt_mock, caplog): """Test update of discovered fan.""" - data1 = '{ "name": "Beer",' ' "command_topic": "test_topic" }' - data2 = '{ "name": "Milk",' ' "command_topic": "test_topic" }' + data1 = '{ "name": "Beer", "command_topic": "test_topic" }' + data2 = '{ "name": "Milk", "command_topic": "test_topic" }' await help_test_discovery_update(hass, mqtt_mock, caplog, fan.DOMAIN, data1, data2) +async def test_discovery_update_unchanged_fan(hass, mqtt_mock, caplog): + """Test update of discovered fan.""" + data1 = '{ "name": "Beer", "command_topic": "test_topic" }' + with patch( + "homeassistant.components.mqtt.fan.MqttFan.discovery_update" + ) as discovery_update: + await help_test_discovery_update_unchanged( + hass, mqtt_mock, caplog, fan.DOMAIN, data1, discovery_update + ) + + @pytest.mark.no_fail_on_log_exception async def test_discovery_broken(hass, mqtt_mock, caplog): """Test handling of bad discovery message.""" data1 = '{ "name": "Beer" }' - data2 = '{ "name": "Milk",' ' "command_topic": "test_topic" }' + data2 = '{ "name": "Milk", "command_topic": "test_topic" }' await help_test_discovery_broken(hass, mqtt_mock, caplog, fan.DOMAIN, data1, data2) diff --git a/tests/components/mqtt/test_legacy_vacuum.py b/tests/components/mqtt/test_legacy_vacuum.py index 893c1b78f1e..aacea4e345e 100644 --- a/tests/components/mqtt/test_legacy_vacuum.py +++ b/tests/components/mqtt/test_legacy_vacuum.py @@ -31,6 +31,7 @@ from .test_common import ( help_test_discovery_removal, help_test_discovery_update, help_test_discovery_update_attr, + help_test_discovery_update_unchanged, help_test_entity_debug_info_message, help_test_entity_device_info_remove, help_test_entity_device_info_update, @@ -45,6 +46,7 @@ from .test_common import ( help_test_update_with_json_attrs_not_dict, ) +from tests.async_mock import patch from tests.common import async_fire_mqtt_message from tests.components.vacuum import common @@ -643,6 +645,17 @@ async def test_discovery_update_vacuum(hass, mqtt_mock, caplog): ) +async def test_discovery_update_unchanged_vacuum(hass, mqtt_mock, caplog): + """Test update of discovered vacuum.""" + data1 = '{ "name": "Beer", "command_topic": "test_topic" }' + with patch( + "homeassistant.components.mqtt.vacuum.schema_legacy.MqttVacuum.discovery_update" + ) as discovery_update: + await help_test_discovery_update_unchanged( + hass, mqtt_mock, caplog, vacuum.DOMAIN, data1, discovery_update + ) + + @pytest.mark.no_fail_on_log_exception async def test_discovery_broken(hass, mqtt_mock, caplog): """Test handling of bad discovery message.""" diff --git a/tests/components/mqtt/test_light.py b/tests/components/mqtt/test_light.py index 5fa8fa181e5..75d3e694838 100644 --- a/tests/components/mqtt/test_light.py +++ b/tests/components/mqtt/test_light.py @@ -170,6 +170,7 @@ from .test_common import ( help_test_discovery_removal, help_test_discovery_update, help_test_discovery_update_attr, + help_test_discovery_update_unchanged, help_test_entity_debug_info_message, help_test_entity_device_info_remove, help_test_entity_device_info_update, @@ -1450,6 +1451,21 @@ async def test_discovery_update_light(hass, mqtt_mock, caplog): ) +async def test_discovery_update_unchanged_light(hass, mqtt_mock, caplog): + """Test update of discovered light.""" + data1 = ( + '{ "name": "Beer",' + ' "state_topic": "test_topic",' + ' "command_topic": "test_topic" }' + ) + with patch( + "homeassistant.components.mqtt.light.schema_basic.MqttLight.discovery_update" + ) as discovery_update: + await help_test_discovery_update_unchanged( + hass, mqtt_mock, caplog, light.DOMAIN, data1, discovery_update + ) + + @pytest.mark.no_fail_on_log_exception async def test_discovery_broken(hass, mqtt_mock, caplog): """Test handling of bad discovery message.""" diff --git a/tests/components/mqtt/test_light_json.py b/tests/components/mqtt/test_light_json.py index 7bb3763654e..54292aeeb7b 100644 --- a/tests/components/mqtt/test_light_json.py +++ b/tests/components/mqtt/test_light_json.py @@ -110,6 +110,7 @@ from .test_common import ( help_test_discovery_removal, help_test_discovery_update, help_test_discovery_update_attr, + help_test_discovery_update_unchanged, help_test_entity_debug_info_message, help_test_entity_device_info_remove, help_test_entity_device_info_update, @@ -1179,6 +1180,22 @@ async def test_discovery_update_light(hass, mqtt_mock, caplog): ) +async def test_discovery_update_unchanged_light(hass, mqtt_mock, caplog): + """Test update of discovered light.""" + data1 = ( + '{ "name": "Beer",' + ' "schema": "json",' + ' "state_topic": "test_topic",' + ' "command_topic": "test_topic" }' + ) + with patch( + "homeassistant.components.mqtt.light.schema_json.MqttLightJson.discovery_update" + ) as discovery_update: + await help_test_discovery_update_unchanged( + hass, mqtt_mock, caplog, light.DOMAIN, data1, discovery_update + ) + + @pytest.mark.no_fail_on_log_exception async def test_discovery_broken(hass, mqtt_mock, caplog): """Test handling of bad discovery message.""" diff --git a/tests/components/mqtt/test_light_template.py b/tests/components/mqtt/test_light_template.py index f0e226d2095..17b3332da40 100644 --- a/tests/components/mqtt/test_light_template.py +++ b/tests/components/mqtt/test_light_template.py @@ -47,6 +47,7 @@ from .test_common import ( help_test_discovery_removal, help_test_discovery_update, help_test_discovery_update_attr, + help_test_discovery_update_unchanged, help_test_entity_debug_info_message, help_test_entity_device_info_remove, help_test_entity_device_info_update, @@ -923,6 +924,24 @@ async def test_discovery_update_light(hass, mqtt_mock, caplog): ) +async def test_discovery_update_unchanged_light(hass, mqtt_mock, caplog): + """Test update of discovered light.""" + data1 = ( + '{ "name": "Beer",' + ' "schema": "template",' + ' "state_topic": "test_topic",' + ' "command_topic": "test_topic",' + ' "command_on_template": "on",' + ' "command_off_template": "off"}' + ) + with patch( + "homeassistant.components.mqtt.light.schema_template.MqttLightTemplate.discovery_update" + ) as discovery_update: + await help_test_discovery_update_unchanged( + hass, mqtt_mock, caplog, light.DOMAIN, data1, discovery_update + ) + + @pytest.mark.no_fail_on_log_exception async def test_discovery_broken(hass, mqtt_mock, caplog): """Test handling of bad discovery message.""" diff --git a/tests/components/mqtt/test_lock.py b/tests/components/mqtt/test_lock.py index ff130077a95..cd37543d94e 100644 --- a/tests/components/mqtt/test_lock.py +++ b/tests/components/mqtt/test_lock.py @@ -20,6 +20,7 @@ from .test_common import ( help_test_discovery_removal, help_test_discovery_update, help_test_discovery_update_attr, + help_test_discovery_update_unchanged, help_test_entity_debug_info_message, help_test_entity_device_info_remove, help_test_entity_device_info_update, @@ -34,6 +35,7 @@ from .test_common import ( help_test_update_with_json_attrs_not_dict, ) +from tests.async_mock import patch from tests.common import async_fire_mqtt_message DEFAULT_CONFIG = { @@ -382,6 +384,21 @@ async def test_discovery_update_lock(hass, mqtt_mock, caplog): await help_test_discovery_update(hass, mqtt_mock, caplog, LOCK_DOMAIN, data1, data2) +async def test_discovery_update_unchanged_lock(hass, mqtt_mock, caplog): + """Test update of discovered lock.""" + data1 = ( + '{ "name": "Beer",' + ' "state_topic": "test_topic",' + ' "command_topic": "command_topic" }' + ) + with patch( + "homeassistant.components.mqtt.lock.MqttLock.discovery_update" + ) as discovery_update: + await help_test_discovery_update_unchanged( + hass, mqtt_mock, caplog, LOCK_DOMAIN, data1, discovery_update + ) + + @pytest.mark.no_fail_on_log_exception async def test_discovery_broken(hass, mqtt_mock, caplog): """Test handling of bad discovery message.""" diff --git a/tests/components/mqtt/test_sensor.py b/tests/components/mqtt/test_sensor.py index 5ec5fccbe28..0d31b9f33f2 100644 --- a/tests/components/mqtt/test_sensor.py +++ b/tests/components/mqtt/test_sensor.py @@ -24,6 +24,7 @@ from .test_common import ( help_test_discovery_update, help_test_discovery_update_attr, help_test_discovery_update_availability, + help_test_discovery_update_unchanged, help_test_entity_debug_info, help_test_entity_debug_info_max_messages, help_test_entity_debug_info_message, @@ -425,24 +426,35 @@ async def test_unique_id(hass, mqtt_mock): async def test_discovery_removal_sensor(hass, mqtt_mock, caplog): """Test removal of discovered sensor.""" - data = '{ "name": "test",' ' "state_topic": "test_topic" }' + data = '{ "name": "test", "state_topic": "test_topic" }' await help_test_discovery_removal(hass, mqtt_mock, caplog, sensor.DOMAIN, data) async def test_discovery_update_sensor(hass, mqtt_mock, caplog): """Test update of discovered sensor.""" - data1 = '{ "name": "Beer",' ' "state_topic": "test_topic" }' - data2 = '{ "name": "Milk",' ' "state_topic": "test_topic" }' + data1 = '{ "name": "Beer", "state_topic": "test_topic" }' + data2 = '{ "name": "Milk", "state_topic": "test_topic" }' await help_test_discovery_update( hass, mqtt_mock, caplog, sensor.DOMAIN, data1, data2 ) +async def test_discovery_update_unchanged_sensor(hass, mqtt_mock, caplog): + """Test update of discovered sensor.""" + data1 = '{ "name": "Beer", "state_topic": "test_topic" }' + with patch( + "homeassistant.components.mqtt.sensor.MqttSensor.discovery_update" + ) as discovery_update: + await help_test_discovery_update_unchanged( + hass, mqtt_mock, caplog, sensor.DOMAIN, data1, discovery_update + ) + + @pytest.mark.no_fail_on_log_exception async def test_discovery_broken(hass, mqtt_mock, caplog): """Test handling of bad discovery message.""" - data1 = '{ "name": "Beer",' ' "state_topic": "test_topic#" }' - data2 = '{ "name": "Milk",' ' "state_topic": "test_topic" }' + data1 = '{ "name": "Beer", "state_topic": "test_topic#" }' + data2 = '{ "name": "Milk", "state_topic": "test_topic" }' await help_test_discovery_broken( hass, mqtt_mock, caplog, sensor.DOMAIN, data1, data2 ) diff --git a/tests/components/mqtt/test_state_vacuum.py b/tests/components/mqtt/test_state_vacuum.py index c8ca7d3691b..fe410821395 100644 --- a/tests/components/mqtt/test_state_vacuum.py +++ b/tests/components/mqtt/test_state_vacuum.py @@ -41,6 +41,7 @@ from .test_common import ( help_test_discovery_removal, help_test_discovery_update, help_test_discovery_update_attr, + help_test_discovery_update_unchanged, help_test_entity_debug_info_message, help_test_entity_device_info_remove, help_test_entity_device_info_update, @@ -55,6 +56,7 @@ from .test_common import ( help_test_update_with_json_attrs_not_dict, ) +from tests.async_mock import patch from tests.common import async_fire_mqtt_message from tests.components.vacuum import common @@ -410,24 +412,35 @@ async def test_unique_id(hass, mqtt_mock): async def test_discovery_removal_vacuum(hass, mqtt_mock, caplog): """Test removal of discovered vacuum.""" - data = '{ "schema": "state", "name": "test",' ' "command_topic": "test_topic"}' + data = '{ "schema": "state", "name": "test", "command_topic": "test_topic"}' await help_test_discovery_removal(hass, mqtt_mock, caplog, vacuum.DOMAIN, data) async def test_discovery_update_vacuum(hass, mqtt_mock, caplog): """Test update of discovered vacuum.""" - data1 = '{ "schema": "state", "name": "Beer",' ' "command_topic": "test_topic"}' - data2 = '{ "schema": "state", "name": "Milk",' ' "command_topic": "test_topic"}' + data1 = '{ "schema": "state", "name": "Beer", "command_topic": "test_topic"}' + data2 = '{ "schema": "state", "name": "Milk", "command_topic": "test_topic"}' await help_test_discovery_update( hass, mqtt_mock, caplog, vacuum.DOMAIN, data1, data2 ) +async def test_discovery_update_unchanged_vacuum(hass, mqtt_mock, caplog): + """Test update of discovered vacuum.""" + data1 = '{ "schema": "state", "name": "Beer", "command_topic": "test_topic"}' + with patch( + "homeassistant.components.mqtt.vacuum.schema_state.MqttStateVacuum.discovery_update" + ) as discovery_update: + await help_test_discovery_update_unchanged( + hass, mqtt_mock, caplog, vacuum.DOMAIN, data1, discovery_update + ) + + @pytest.mark.no_fail_on_log_exception async def test_discovery_broken(hass, mqtt_mock, caplog): """Test handling of bad discovery message.""" - data1 = '{ "schema": "state", "name": "Beer",' ' "command_topic": "test_topic#"}' - data2 = '{ "schema": "state", "name": "Milk",' ' "command_topic": "test_topic"}' + data1 = '{ "schema": "state", "name": "Beer", "command_topic": "test_topic#"}' + data2 = '{ "schema": "state", "name": "Milk", "command_topic": "test_topic"}' await help_test_discovery_broken( hass, mqtt_mock, caplog, vacuum.DOMAIN, data1, data2 ) diff --git a/tests/components/mqtt/test_switch.py b/tests/components/mqtt/test_switch.py index 869a413eb6b..a6edb8d6f14 100644 --- a/tests/components/mqtt/test_switch.py +++ b/tests/components/mqtt/test_switch.py @@ -15,6 +15,7 @@ from .test_common import ( help_test_discovery_removal, help_test_discovery_update, help_test_discovery_update_attr, + help_test_discovery_update_unchanged, help_test_entity_debug_info_message, help_test_entity_device_info_remove, help_test_entity_device_info_update, @@ -320,6 +321,21 @@ async def test_discovery_update_switch(hass, mqtt_mock, caplog): ) +async def test_discovery_update_unchanged_switch(hass, mqtt_mock, caplog): + """Test update of discovered switch.""" + data1 = ( + '{ "name": "Beer",' + ' "state_topic": "test_topic",' + ' "command_topic": "test_topic" }' + ) + with patch( + "homeassistant.components.mqtt.switch.MqttSwitch.discovery_update" + ) as discovery_update: + await help_test_discovery_update_unchanged( + hass, mqtt_mock, caplog, switch.DOMAIN, data1, discovery_update + ) + + @pytest.mark.no_fail_on_log_exception async def test_discovery_broken(hass, mqtt_mock, caplog): """Test handling of bad discovery message."""