From 933dde1d1e4aa41ad7e06351dfb9336a86416851 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Sep 2022 20:10:05 -0500 Subject: [PATCH 01/23] Handle Modalias missing from the bluetooth adapter details on older BlueZ (#78716) --- homeassistant/components/bluetooth/const.py | 2 +- homeassistant/components/bluetooth/util.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/bluetooth/const.py b/homeassistant/components/bluetooth/const.py index 3174603f08e32..891e6d8be8274 100644 --- a/homeassistant/components/bluetooth/const.py +++ b/homeassistant/components/bluetooth/const.py @@ -58,7 +58,7 @@ class AdapterDetails(TypedDict, total=False): address: str sw_version: str - hw_version: str + hw_version: str | None passive_scan: bool diff --git a/homeassistant/components/bluetooth/util.py b/homeassistant/components/bluetooth/util.py index 3f6c862e53d22..19efab7a15c7b 100644 --- a/homeassistant/components/bluetooth/util.py +++ b/homeassistant/components/bluetooth/util.py @@ -46,7 +46,7 @@ async def async_get_bluetooth_adapters() -> dict[str, AdapterDetails]: adapters[adapter] = AdapterDetails( address=adapter1["Address"], sw_version=adapter1["Name"], # This is actually the BlueZ version - hw_version=adapter1["Modalias"], + hw_version=adapter1.get("Modalias"), passive_scan="org.bluez.AdvertisementMonitorManager1" in details, ) return adapters From b3a48389789549b3cb1aabd042310137baccc9b9 Mon Sep 17 00:00:00 2001 From: Jan Bouwhuis Date: Tue, 6 Sep 2022 11:02:15 +0200 Subject: [PATCH 02/23] Refactor MQTT tests to use modern platform schema part 1 (#77387) * Tests alarm_control_panel * Tests binary_sensor * Tests button * Tests camera * Tests Climate + corrections default config * Tests cover * Tests device_tracker * Tests fan * Tests humidifier * Fix test_supported_features test fan * Tests init * Tests legacy vacuum * Derive DEFAULT_CONFIG_LEGACY from DEFAULT_CONFIG * Commit suggestion comment changes --- .../mqtt/test_alarm_control_panel.py | 265 +-- tests/components/mqtt/test_binary_sensor.py | 341 ++-- tests/components/mqtt/test_button.py | 169 +- tests/components/mqtt/test_camera.py | 131 +- tests/components/mqtt/test_climate.py | 290 +-- tests/components/mqtt/test_cover.py | 1620 +++++++++-------- tests/components/mqtt/test_device_tracker.py | 122 +- .../mqtt/test_device_tracker_discovery.py | 39 +- tests/components/mqtt/test_fan.py | 954 +++++----- tests/components/mqtt/test_humidifier.py | 659 ++++--- tests/components/mqtt/test_init.py | 35 +- tests/components/mqtt/test_legacy_vacuum.py | 284 +-- 12 files changed, 2686 insertions(+), 2223 deletions(-) diff --git a/tests/components/mqtt/test_alarm_control_panel.py b/tests/components/mqtt/test_alarm_control_panel.py index 7d127902f3d5a..e51ed9aeae951 100644 --- a/tests/components/mqtt/test_alarm_control_panel.py +++ b/tests/components/mqtt/test_alarm_control_panel.py @@ -5,7 +5,7 @@ import pytest -from homeassistant.components import alarm_control_panel +from homeassistant.components import alarm_control_panel, mqtt from homeassistant.components.mqtt.alarm_control_panel import ( MQTT_ALARM_ATTRIBUTES_BLOCKED, ) @@ -65,54 +65,65 @@ help_test_update_with_json_attrs_not_dict, ) -from tests.common import assert_setup_component, async_fire_mqtt_message +from tests.common import async_fire_mqtt_message from tests.components.alarm_control_panel import common CODE_NUMBER = "1234" CODE_TEXT = "HELLO_CODE" DEFAULT_CONFIG = { - alarm_control_panel.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "alarm/state", - "command_topic": "alarm/command", + mqtt.DOMAIN: { + alarm_control_panel.DOMAIN: { + "name": "test", + "state_topic": "alarm/state", + "command_topic": "alarm/command", + } } } DEFAULT_CONFIG_CODE = { - alarm_control_panel.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "alarm/state", - "command_topic": "alarm/command", - "code": "0123", - "code_arm_required": True, + mqtt.DOMAIN: { + alarm_control_panel.DOMAIN: { + "name": "test", + "state_topic": "alarm/state", + "command_topic": "alarm/command", + "code": "0123", + "code_arm_required": True, + } } } DEFAULT_CONFIG_REMOTE_CODE = { - alarm_control_panel.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "alarm/state", - "command_topic": "alarm/command", - "code": "REMOTE_CODE", - "code_arm_required": True, + mqtt.DOMAIN: { + alarm_control_panel.DOMAIN: { + "name": "test", + "state_topic": "alarm/state", + "command_topic": "alarm/command", + "code": "REMOTE_CODE", + "code_arm_required": True, + } } } DEFAULT_CONFIG_REMOTE_CODE_TEXT = { - alarm_control_panel.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "alarm/state", - "command_topic": "alarm/command", - "code": "REMOTE_CODE_TEXT", - "code_arm_required": True, + mqtt.DOMAIN: { + alarm_control_panel.DOMAIN: { + "name": "test", + "state_topic": "alarm/state", + "command_topic": "alarm/command", + "code": "REMOTE_CODE_TEXT", + "code_arm_required": True, + } } } +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +DEFAULT_CONFIG_LEGACY = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) +DEFAULT_CONFIG_LEGACY[alarm_control_panel.DOMAIN]["platform"] = mqtt.DOMAIN +DEFAULT_CONFIG_CODE_LEGACY = copy.deepcopy(DEFAULT_CONFIG_CODE[mqtt.DOMAIN]) +DEFAULT_CONFIG_CODE_LEGACY[alarm_control_panel.DOMAIN]["platform"] = mqtt.DOMAIN + @pytest.fixture(autouse=True) def alarm_control_panel_platform_only(): @@ -123,47 +134,62 @@ def alarm_control_panel_platform_only(): yield -async def test_fail_setup_without_state_topic(hass, mqtt_mock_entry_no_yaml_config): - """Test for failing with no state topic.""" - with assert_setup_component(0, alarm_control_panel.DOMAIN) as config: - assert await async_setup_component( - hass, - alarm_control_panel.DOMAIN, +@pytest.mark.parametrize( + "config,valid", + [ + ( { - alarm_control_panel.DOMAIN: { - "platform": "mqtt", - "command_topic": "alarm/command", + mqtt.DOMAIN: { + alarm_control_panel.DOMAIN: { + "name": "test", + "command_topic": "alarm/command", + } } }, - ) - await hass.async_block_till_done() - await mqtt_mock_entry_no_yaml_config() - assert not config[alarm_control_panel.DOMAIN] - - -async def test_fail_setup_without_command_topic(hass, mqtt_mock_entry_no_yaml_config): - """Test failing with no command topic.""" - with assert_setup_component(0, alarm_control_panel.DOMAIN) as config: - assert await async_setup_component( - hass, - alarm_control_panel.DOMAIN, + False, + ), + ( { - alarm_control_panel.DOMAIN: { - "platform": "mqtt", - "state_topic": "alarm/state", + mqtt.DOMAIN: { + alarm_control_panel.DOMAIN: { + "name": "test", + "state_topic": "alarm/state", + } + } + }, + False, + ), + ( + { + mqtt.DOMAIN: { + alarm_control_panel.DOMAIN: { + "name": "test", + "command_topic": "alarm/command", + "state_topic": "alarm/state", + } } }, + True, + ), + ], +) +async def test_fail_setup_without_state_or_command_topic(hass, config, valid): + """Test for failing setup with no state or command topic.""" + assert ( + await async_setup_component( + hass, + mqtt.DOMAIN, + config, ) - await hass.async_block_till_done() - await mqtt_mock_entry_no_yaml_config() - assert not config[alarm_control_panel.DOMAIN] + is valid + ) async def test_update_state_via_state_topic(hass, mqtt_mock_entry_with_yaml_config): """Test updating with via state topic.""" assert await async_setup_component( hass, - alarm_control_panel.DOMAIN, + mqtt.DOMAIN, DEFAULT_CONFIG, ) await hass.async_block_till_done() @@ -195,7 +221,7 @@ async def test_ignore_update_state_if_unknown_via_state_topic( """Test ignoring updates via state topic.""" assert await async_setup_component( hass, - alarm_control_panel.DOMAIN, + mqtt.DOMAIN, DEFAULT_CONFIG, ) await hass.async_block_till_done() @@ -227,7 +253,7 @@ async def test_publish_mqtt_no_code( """Test publishing of MQTT messages when no code is configured.""" assert await async_setup_component( hass, - alarm_control_panel.DOMAIN, + mqtt.DOMAIN, DEFAULT_CONFIG, ) await hass.async_block_till_done() @@ -261,7 +287,7 @@ async def test_publish_mqtt_with_code( """Test publishing of MQTT messages when code is configured.""" assert await async_setup_component( hass, - alarm_control_panel.DOMAIN, + mqtt.DOMAIN, DEFAULT_CONFIG_CODE, ) await hass.async_block_till_done() @@ -314,7 +340,7 @@ async def test_publish_mqtt_with_remote_code( """Test publishing of MQTT messages when remode code is configured.""" assert await async_setup_component( hass, - alarm_control_panel.DOMAIN, + mqtt.DOMAIN, DEFAULT_CONFIG_REMOTE_CODE, ) await hass.async_block_till_done() @@ -358,7 +384,7 @@ async def test_publish_mqtt_with_remote_code_text( """Test publishing of MQTT messages when remote text code is configured.""" assert await async_setup_component( hass, - alarm_control_panel.DOMAIN, + mqtt.DOMAIN, DEFAULT_CONFIG_REMOTE_CODE_TEXT, ) await hass.async_block_till_done() @@ -405,10 +431,10 @@ async def test_publish_mqtt_with_code_required_false( code_trigger_required = False """ config = copy.deepcopy(DEFAULT_CONFIG_CODE) - config[alarm_control_panel.DOMAIN][disable_code] = False + config[mqtt.DOMAIN][alarm_control_panel.DOMAIN][disable_code] = False assert await async_setup_component( hass, - alarm_control_panel.DOMAIN, + mqtt.DOMAIN, config, ) await hass.async_block_till_done() @@ -453,13 +479,13 @@ async def test_disarm_publishes_mqtt_with_template( When command_template set to output json """ config = copy.deepcopy(DEFAULT_CONFIG_CODE) - config[alarm_control_panel.DOMAIN]["code"] = "0123" - config[alarm_control_panel.DOMAIN][ + config[mqtt.DOMAIN][alarm_control_panel.DOMAIN]["code"] = "0123" + config[mqtt.DOMAIN][alarm_control_panel.DOMAIN][ "command_template" ] = '{"action":"{{ action }}","code":"{{ code }}"}' assert await async_setup_component( hass, - alarm_control_panel.DOMAIN, + mqtt.DOMAIN, config, ) await hass.async_block_till_done() @@ -477,19 +503,20 @@ async def test_update_state_via_state_topic_template( """Test updating with template_value via state topic.""" assert await async_setup_component( hass, - alarm_control_panel.DOMAIN, + mqtt.DOMAIN, { - alarm_control_panel.DOMAIN: { - "platform": "mqtt", - "name": "test", - "command_topic": "test-topic", - "state_topic": "test-topic", - "value_template": "\ + mqtt.DOMAIN: { + alarm_control_panel.DOMAIN: { + "name": "test", + "command_topic": "test-topic", + "state_topic": "test-topic", + "value_template": "\ {% if (value | int) == 100 %}\ armed_away\ {% else %}\ disarmed\ {% endif %}", + } } }, ) @@ -508,9 +535,9 @@ async def test_update_state_via_state_topic_template( async def test_attributes_code_number(hass, mqtt_mock_entry_with_yaml_config): """Test attributes which are not supported by the vacuum.""" config = copy.deepcopy(DEFAULT_CONFIG) - config[alarm_control_panel.DOMAIN]["code"] = CODE_NUMBER + config[mqtt.DOMAIN][alarm_control_panel.DOMAIN]["code"] = CODE_NUMBER - assert await async_setup_component(hass, alarm_control_panel.DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, config) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -524,9 +551,9 @@ async def test_attributes_code_number(hass, mqtt_mock_entry_with_yaml_config): async def test_attributes_remote_code_number(hass, mqtt_mock_entry_with_yaml_config): """Test attributes which are not supported by the vacuum.""" config = copy.deepcopy(DEFAULT_CONFIG_REMOTE_CODE) - config[alarm_control_panel.DOMAIN]["code"] = "REMOTE_CODE" + config[mqtt.DOMAIN][alarm_control_panel.DOMAIN]["code"] = "REMOTE_CODE" - assert await async_setup_component(hass, alarm_control_panel.DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, config) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -540,9 +567,9 @@ async def test_attributes_remote_code_number(hass, mqtt_mock_entry_with_yaml_con async def test_attributes_code_text(hass, mqtt_mock_entry_with_yaml_config): """Test attributes which are not supported by the vacuum.""" config = copy.deepcopy(DEFAULT_CONFIG) - config[alarm_control_panel.DOMAIN]["code"] = CODE_TEXT + config[mqtt.DOMAIN][alarm_control_panel.DOMAIN]["code"] = CODE_TEXT - assert await async_setup_component(hass, alarm_control_panel.DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, config) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -561,7 +588,7 @@ async def test_availability_when_connection_lost( hass, mqtt_mock_entry_with_yaml_config, alarm_control_panel.DOMAIN, - DEFAULT_CONFIG_CODE, + DEFAULT_CONFIG_CODE_LEGACY, ) @@ -571,7 +598,7 @@ async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config hass, mqtt_mock_entry_with_yaml_config, alarm_control_panel.DOMAIN, - DEFAULT_CONFIG_CODE, + DEFAULT_CONFIG_CODE_LEGACY, ) @@ -581,7 +608,7 @@ async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_conf hass, mqtt_mock_entry_with_yaml_config, alarm_control_panel.DOMAIN, - DEFAULT_CONFIG_CODE, + DEFAULT_CONFIG_CODE_LEGACY, ) @@ -591,7 +618,7 @@ async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_confi hass, mqtt_mock_entry_with_yaml_config, alarm_control_panel.DOMAIN, - DEFAULT_CONFIG_CODE, + DEFAULT_CONFIG_CODE_LEGACY, ) @@ -603,7 +630,7 @@ async def test_setting_attribute_via_mqtt_json_message( hass, mqtt_mock_entry_with_yaml_config, alarm_control_panel.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, ) @@ -615,7 +642,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( hass, mqtt_mock_entry_no_yaml_config, alarm_control_panel.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, MQTT_ALARM_ATTRIBUTES_BLOCKED, ) @@ -626,7 +653,7 @@ async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_c hass, mqtt_mock_entry_with_yaml_config, alarm_control_panel.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, ) @@ -639,7 +666,7 @@ async def test_update_with_json_attrs_not_dict( mqtt_mock_entry_with_yaml_config, caplog, alarm_control_panel.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, ) @@ -652,7 +679,7 @@ async def test_update_with_json_attrs_bad_JSON( mqtt_mock_entry_with_yaml_config, caplog, alarm_control_panel.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, ) @@ -663,7 +690,7 @@ async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplo mqtt_mock_entry_no_yaml_config, caplog, alarm_control_panel.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, ) @@ -694,7 +721,7 @@ async def test_unique_id(hass, mqtt_mock_entry_with_yaml_config): async def test_discovery_removal_alarm(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test removal of discovered alarm_control_panel.""" - data = json.dumps(DEFAULT_CONFIG[alarm_control_panel.DOMAIN]) + data = json.dumps(DEFAULT_CONFIG_LEGACY[alarm_control_panel.DOMAIN]) await help_test_discovery_removal( hass, mqtt_mock_entry_no_yaml_config, caplog, alarm_control_panel.DOMAIN, data ) @@ -704,8 +731,8 @@ async def test_discovery_update_alarm_topic_and_template( hass, mqtt_mock_entry_no_yaml_config, caplog ): """Test update of discovered alarm_control_panel.""" - config1 = copy.deepcopy(DEFAULT_CONFIG[alarm_control_panel.DOMAIN]) - config2 = copy.deepcopy(DEFAULT_CONFIG[alarm_control_panel.DOMAIN]) + config1 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[alarm_control_panel.DOMAIN]) + config2 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[alarm_control_panel.DOMAIN]) config1["name"] = "Beer" config2["name"] = "Milk" config1["state_topic"] = "alarm/state1" @@ -739,8 +766,8 @@ async def test_discovery_update_alarm_template( hass, mqtt_mock_entry_no_yaml_config, caplog ): """Test update of discovered alarm_control_panel.""" - config1 = copy.deepcopy(DEFAULT_CONFIG[alarm_control_panel.DOMAIN]) - config2 = copy.deepcopy(DEFAULT_CONFIG[alarm_control_panel.DOMAIN]) + config1 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[alarm_control_panel.DOMAIN]) + config2 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[alarm_control_panel.DOMAIN]) config1["name"] = "Beer" config2["name"] = "Milk" config1["state_topic"] = "alarm/state1" @@ -772,7 +799,7 @@ async def test_discovery_update_unchanged_alarm( hass, mqtt_mock_entry_no_yaml_config, caplog ): """Test update of discovered alarm_control_panel.""" - config1 = copy.deepcopy(DEFAULT_CONFIG[alarm_control_panel.DOMAIN]) + config1 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[alarm_control_panel.DOMAIN]) config1["name"] = "Beer" data1 = json.dumps(config1) @@ -824,7 +851,7 @@ async def test_encoding_subscribable_topics( mqtt_mock_entry_with_yaml_config, caplog, alarm_control_panel.DOMAIN, - DEFAULT_CONFIG[alarm_control_panel.DOMAIN], + DEFAULT_CONFIG_LEGACY[alarm_control_panel.DOMAIN], topic, value, ) @@ -836,7 +863,7 @@ async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_ hass, mqtt_mock_entry_no_yaml_config, alarm_control_panel.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, ) @@ -846,21 +873,27 @@ async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_ hass, mqtt_mock_entry_no_yaml_config, alarm_control_panel.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, ) async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): """Test device registry update.""" await help_test_entity_device_info_update( - hass, mqtt_mock_entry_no_yaml_config, alarm_control_panel.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_no_yaml_config, + alarm_control_panel.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test device registry remove.""" await help_test_entity_device_info_remove( - hass, mqtt_mock_entry_no_yaml_config, alarm_control_panel.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_no_yaml_config, + alarm_control_panel.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) @@ -870,14 +903,17 @@ async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_co hass, mqtt_mock_entry_with_yaml_config, alarm_control_panel.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, ) async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, alarm_control_panel.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_no_yaml_config, + alarm_control_panel.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) @@ -887,7 +923,7 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): hass, mqtt_mock_entry_no_yaml_config, alarm_control_panel.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, alarm_control_panel.SERVICE_ALARM_DISARM, command_payload="DISARM", ) @@ -930,7 +966,7 @@ async def test_publishing_with_custom_encoding( ): """Test publishing MQTT payload with different encoding.""" domain = alarm_control_panel.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_publishing_with_custom_encoding( hass, @@ -951,7 +987,7 @@ async def test_publishing_with_custom_encoding( async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = alarm_control_panel.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) @@ -960,14 +996,14 @@ async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_pa async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = alarm_control_panel.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable_late(hass, caplog, tmp_path, domain, config) async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = alarm_control_panel.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG[platform]) + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) config["name"] = "test" del config["platform"] await help_test_setup_manual_entity_from_yaml(hass, platform, config) @@ -977,7 +1013,20 @@ async def test_setup_manual_entity_from_yaml(hass): async def test_unload_entry(hass, mqtt_mock_entry_with_yaml_config, tmp_path): """Test unloading the config entry.""" domain = alarm_control_panel.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry_with_yaml_config, tmp_path, domain, config ) + + +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +async def test_setup_with_legacy_schema(hass, mqtt_mock_entry_with_yaml_config): + """Test a setup with deprecated yaml platform schema.""" + domain = alarm_control_panel.DOMAIN + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[domain]) + config["name"] = "test" + assert await async_setup_component(hass, domain, {domain: config}) + await hass.async_block_till_done() + await mqtt_mock_entry_with_yaml_config() + assert hass.states.get(f"{domain}.test") is not None diff --git a/tests/components/mqtt/test_binary_sensor.py b/tests/components/mqtt/test_binary_sensor.py index 7d4edace9887d..bbe8b97870768 100644 --- a/tests/components/mqtt/test_binary_sensor.py +++ b/tests/components/mqtt/test_binary_sensor.py @@ -6,7 +6,7 @@ import pytest -from homeassistant.components import binary_sensor +from homeassistant.components import binary_sensor, mqtt from homeassistant.const import ( EVENT_STATE_CHANGED, STATE_OFF, @@ -50,20 +50,25 @@ ) from tests.common import ( - assert_setup_component, async_fire_mqtt_message, async_fire_time_changed, mock_restore_cache, ) DEFAULT_CONFIG = { - binary_sensor.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "test-topic", + mqtt.DOMAIN: { + binary_sensor.DOMAIN: { + "name": "test", + "state_topic": "test-topic", + } } } +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +DEFAULT_CONFIG_LEGACY = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) +DEFAULT_CONFIG_LEGACY[binary_sensor.DOMAIN]["platform"] = mqtt.DOMAIN + @pytest.fixture(autouse=True) def binary_sensor_platform_only(): @@ -78,15 +83,16 @@ async def test_setting_sensor_value_expires_availability_topic( """Test the expiration of the value.""" assert await async_setup_component( hass, - binary_sensor.DOMAIN, + mqtt.DOMAIN, { - binary_sensor.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "test-topic", - "expire_after": 4, - "force_update": True, - "availability_topic": "availability-topic", + mqtt.DOMAIN: { + binary_sensor.DOMAIN: { + "name": "test", + "state_topic": "test-topic", + "expire_after": 4, + "force_update": True, + "availability_topic": "availability-topic", + } } }, ) @@ -270,14 +276,15 @@ async def test_setting_sensor_value_via_mqtt_message( """Test the setting of the value via MQTT.""" assert await async_setup_component( hass, - binary_sensor.DOMAIN, + mqtt.DOMAIN, { - binary_sensor.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "test-topic", - "payload_on": "ON", - "payload_off": "OFF", + mqtt.DOMAIN: { + binary_sensor.DOMAIN: { + "name": "test", + "state_topic": "test-topic", + "payload_on": "ON", + "payload_off": "OFF", + } } }, ) @@ -307,14 +314,15 @@ async def test_invalid_sensor_value_via_mqtt_message( """Test the setting of the value via MQTT.""" assert await async_setup_component( hass, - binary_sensor.DOMAIN, + mqtt.DOMAIN, { - binary_sensor.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "test-topic", - "payload_on": "ON", - "payload_off": "OFF", + mqtt.DOMAIN: { + binary_sensor.DOMAIN: { + "name": "test", + "state_topic": "test-topic", + "payload_on": "ON", + "payload_off": "OFF", + } } }, ) @@ -348,16 +356,17 @@ async def test_setting_sensor_value_via_mqtt_message_and_template( """Test the setting of the value via MQTT.""" assert await async_setup_component( hass, - binary_sensor.DOMAIN, + mqtt.DOMAIN, { - binary_sensor.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "test-topic", - "payload_on": "ON", - "payload_off": "OFF", - "value_template": '{%if is_state(entity_id,"on")-%}OFF' - "{%-else-%}ON{%-endif%}", + mqtt.DOMAIN: { + binary_sensor.DOMAIN: { + "name": "test", + "state_topic": "test-topic", + "payload_on": "ON", + "payload_off": "OFF", + "value_template": '{%if is_state(entity_id,"on")-%}OFF' + "{%-else-%}ON{%-endif%}", + } } }, ) @@ -382,15 +391,16 @@ async def test_setting_sensor_value_via_mqtt_message_and_template2( """Test the setting of the value via MQTT.""" assert await async_setup_component( hass, - binary_sensor.DOMAIN, + mqtt.DOMAIN, { - binary_sensor.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "test-topic", - "payload_on": "ON", - "payload_off": "OFF", - "value_template": "{{value | upper}}", + mqtt.DOMAIN: { + binary_sensor.DOMAIN: { + "name": "test", + "state_topic": "test-topic", + "payload_on": "ON", + "payload_off": "OFF", + "value_template": "{{value | upper}}", + } } }, ) @@ -420,16 +430,17 @@ async def test_setting_sensor_value_via_mqtt_message_and_template_and_raw_state_ """Test processing a raw value via MQTT.""" assert await async_setup_component( hass, - binary_sensor.DOMAIN, + mqtt.DOMAIN, { - binary_sensor.DOMAIN: { - "platform": "mqtt", - "name": "test", - "encoding": "", - "state_topic": "test-topic", - "payload_on": "ON", - "payload_off": "OFF", - "value_template": "{%if value|unpack('b')-%}ON{%else%}OFF{%-endif-%}", + mqtt.DOMAIN: { + binary_sensor.DOMAIN: { + "name": "test", + "encoding": "", + "state_topic": "test-topic", + "payload_on": "ON", + "payload_off": "OFF", + "value_template": "{%if value|unpack('b')-%}ON{%else%}OFF{%-endif-%}", + } } }, ) @@ -454,15 +465,16 @@ async def test_setting_sensor_value_via_mqtt_message_empty_template( """Test the setting of the value via MQTT.""" assert await async_setup_component( hass, - binary_sensor.DOMAIN, + mqtt.DOMAIN, { - binary_sensor.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "test-topic", - "payload_on": "ON", - "payload_off": "OFF", - "value_template": '{%if value == "ABC"%}ON{%endif%}', + mqtt.DOMAIN: { + binary_sensor.DOMAIN: { + "name": "test", + "state_topic": "test-topic", + "payload_on": "ON", + "payload_off": "OFF", + "value_template": '{%if value == "ABC"%}ON{%endif%}', + } } }, ) @@ -486,13 +498,14 @@ async def test_valid_device_class(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of a valid sensor class.""" assert await async_setup_component( hass, - binary_sensor.DOMAIN, + mqtt.DOMAIN, { - binary_sensor.DOMAIN: { - "platform": "mqtt", - "name": "test", - "device_class": "motion", - "state_topic": "test-topic", + mqtt.DOMAIN: { + binary_sensor.DOMAIN: { + "name": "test", + "device_class": "motion", + "state_topic": "test-topic", + } } }, ) @@ -503,25 +516,22 @@ async def test_valid_device_class(hass, mqtt_mock_entry_with_yaml_config): assert state.attributes.get("device_class") == "motion" -async def test_invalid_device_class(hass, mqtt_mock_entry_no_yaml_config): +async def test_invalid_device_class(hass, caplog): """Test the setting of an invalid sensor class.""" - assert await async_setup_component( + assert not await async_setup_component( hass, - binary_sensor.DOMAIN, + mqtt.DOMAIN, { - binary_sensor.DOMAIN: { - "platform": "mqtt", - "name": "test", - "device_class": "abc123", - "state_topic": "test-topic", + mqtt.DOMAIN: { + binary_sensor.DOMAIN: { + "name": "test", + "device_class": "abc123", + "state_topic": "test-topic", + } } }, ) - await hass.async_block_till_done() - await mqtt_mock_entry_no_yaml_config() - - state = hass.states.get("binary_sensor.test") - assert state is None + assert "Invalid config for [mqtt]: expected BinarySensorDeviceClass" in caplog.text async def test_availability_when_connection_lost( @@ -529,28 +539,40 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, binary_sensor.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_with_yaml_config, + binary_sensor.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, binary_sensor.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_with_yaml_config, + binary_sensor.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by default payload with defined topic.""" await help_test_default_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, binary_sensor.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_with_yaml_config, + binary_sensor.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by custom payload with defined topic.""" await help_test_custom_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, binary_sensor.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_with_yaml_config, + binary_sensor.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) @@ -558,14 +580,15 @@ async def test_force_update_disabled(hass, mqtt_mock_entry_with_yaml_config): """Test force update option.""" assert await async_setup_component( hass, - binary_sensor.DOMAIN, + mqtt.DOMAIN, { - binary_sensor.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "test-topic", - "payload_on": "ON", - "payload_off": "OFF", + mqtt.DOMAIN: { + binary_sensor.DOMAIN: { + "name": "test", + "state_topic": "test-topic", + "payload_on": "ON", + "payload_off": "OFF", + } } }, ) @@ -594,15 +617,16 @@ async def test_force_update_enabled(hass, mqtt_mock_entry_with_yaml_config): """Test force update option.""" assert await async_setup_component( hass, - binary_sensor.DOMAIN, + mqtt.DOMAIN, { - binary_sensor.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "test-topic", - "payload_on": "ON", - "payload_off": "OFF", - "force_update": True, + mqtt.DOMAIN: { + binary_sensor.DOMAIN: { + "name": "test", + "state_topic": "test-topic", + "payload_on": "ON", + "payload_off": "OFF", + "force_update": True, + } } }, ) @@ -631,16 +655,17 @@ async def test_off_delay(hass, mqtt_mock_entry_with_yaml_config): """Test off_delay option.""" assert await async_setup_component( hass, - binary_sensor.DOMAIN, + mqtt.DOMAIN, { - binary_sensor.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "test-topic", - "payload_on": "ON", - "payload_off": "OFF", - "off_delay": 30, - "force_update": True, + mqtt.DOMAIN: { + binary_sensor.DOMAIN: { + "name": "test", + "state_topic": "test-topic", + "payload_on": "ON", + "payload_off": "OFF", + "off_delay": 30, + "force_update": True, + } } }, ) @@ -680,14 +705,20 @@ async def test_setting_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_with_yaml_config, binary_sensor.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_with_yaml_config, + binary_sensor.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_with_template( - hass, mqtt_mock_entry_with_yaml_config, binary_sensor.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_with_yaml_config, + binary_sensor.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) @@ -700,7 +731,7 @@ async def test_update_with_json_attrs_not_dict( mqtt_mock_entry_with_yaml_config, caplog, binary_sensor.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, ) @@ -713,7 +744,7 @@ async def test_update_with_json_attrs_bad_JSON( mqtt_mock_entry_with_yaml_config, caplog, binary_sensor.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, ) @@ -724,7 +755,7 @@ async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplo mqtt_mock_entry_no_yaml_config, caplog, binary_sensor.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, ) @@ -755,7 +786,7 @@ async def test_discovery_removal_binary_sensor( hass, mqtt_mock_entry_no_yaml_config, caplog ): """Test removal of discovered binary_sensor.""" - data = json.dumps(DEFAULT_CONFIG[binary_sensor.DOMAIN]) + data = json.dumps(DEFAULT_CONFIG_LEGACY[binary_sensor.DOMAIN]) await help_test_discovery_removal( hass, mqtt_mock_entry_no_yaml_config, caplog, binary_sensor.DOMAIN, data ) @@ -765,8 +796,8 @@ async def test_discovery_update_binary_sensor_topic_template( hass, mqtt_mock_entry_no_yaml_config, caplog ): """Test update of discovered binary_sensor.""" - config1 = copy.deepcopy(DEFAULT_CONFIG[binary_sensor.DOMAIN]) - config2 = copy.deepcopy(DEFAULT_CONFIG[binary_sensor.DOMAIN]) + config1 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[binary_sensor.DOMAIN]) + config2 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[binary_sensor.DOMAIN]) config1["name"] = "Beer" config2["name"] = "Milk" config1["state_topic"] = "sensor/state1" @@ -802,8 +833,8 @@ async def test_discovery_update_binary_sensor_template( hass, mqtt_mock_entry_no_yaml_config, caplog ): """Test update of discovered binary_sensor.""" - config1 = copy.deepcopy(DEFAULT_CONFIG[binary_sensor.DOMAIN]) - config2 = copy.deepcopy(DEFAULT_CONFIG[binary_sensor.DOMAIN]) + config1 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[binary_sensor.DOMAIN]) + config2 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[binary_sensor.DOMAIN]) config1["name"] = "Beer" config2["name"] = "Milk" config1["state_topic"] = "sensor/state1" @@ -861,7 +892,7 @@ async def test_encoding_subscribable_topics( mqtt_mock_entry_with_yaml_config, caplog, binary_sensor.DOMAIN, - DEFAULT_CONFIG[binary_sensor.DOMAIN], + DEFAULT_CONFIG_LEGACY[binary_sensor.DOMAIN], topic, value, attribute, @@ -873,7 +904,7 @@ async def test_discovery_update_unchanged_binary_sensor( hass, mqtt_mock_entry_no_yaml_config, caplog ): """Test update of discovered binary_sensor.""" - config1 = copy.deepcopy(DEFAULT_CONFIG[binary_sensor.DOMAIN]) + config1 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[binary_sensor.DOMAIN]) config1["name"] = "Beer" data1 = json.dumps(config1) @@ -908,42 +939,60 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT binary sensor device registry integration.""" await help_test_entity_device_info_with_connection( - hass, mqtt_mock_entry_no_yaml_config, binary_sensor.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_no_yaml_config, + binary_sensor.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT binary sensor device registry integration.""" await help_test_entity_device_info_with_identifier( - hass, mqtt_mock_entry_no_yaml_config, binary_sensor.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_no_yaml_config, + binary_sensor.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): """Test device registry update.""" await help_test_entity_device_info_update( - hass, mqtt_mock_entry_no_yaml_config, binary_sensor.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_no_yaml_config, + binary_sensor.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test device registry remove.""" await help_test_entity_device_info_remove( - hass, mqtt_mock_entry_no_yaml_config, binary_sensor.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_no_yaml_config, + binary_sensor.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_config): """Test MQTT subscriptions are managed when entity_id is updated.""" await help_test_entity_id_update_subscriptions( - hass, mqtt_mock_entry_with_yaml_config, binary_sensor.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_with_yaml_config, + binary_sensor.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, binary_sensor.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_no_yaml_config, + binary_sensor.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) @@ -953,7 +1002,7 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): hass, mqtt_mock_entry_no_yaml_config, binary_sensor.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, None, ) @@ -961,7 +1010,7 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = binary_sensor.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) @@ -970,7 +1019,7 @@ async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_pa async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = binary_sensor.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable_late(hass, caplog, tmp_path, domain, config) @@ -991,11 +1040,11 @@ async def test_cleanup_triggers_and_restoring_state( ): """Test cleanup old triggers at reloading and restoring the state.""" domain = binary_sensor.DOMAIN - config1 = copy.deepcopy(DEFAULT_CONFIG[domain]) + config1 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[domain]) config1["name"] = "test1" config1["expire_after"] = 30 config1["state_topic"] = "test-topic1" - config2 = copy.deepcopy(DEFAULT_CONFIG[domain]) + config2 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[domain]) config2["name"] = "test2" config2["expire_after"] = 5 config2["state_topic"] = "test-topic2" @@ -1053,7 +1102,7 @@ async def test_skip_restoring_state_with_over_due_expire_trigger( freezer.move_to("2022-02-02 12:02:00+01:00") domain = binary_sensor.DOMAIN - config3 = copy.deepcopy(DEFAULT_CONFIG[domain]) + config3 = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][domain]) config3["name"] = "test3" config3["expire_after"] = 10 config3["state_topic"] = "test-topic3" @@ -1065,17 +1114,18 @@ async def test_skip_restoring_state_with_over_due_expire_trigger( ) mock_restore_cache(hass, (fake_state,)) - with assert_setup_component(1, domain): - assert await async_setup_component(hass, domain, {domain: config3}) - await hass.async_block_till_done() - await mqtt_mock_entry_with_yaml_config() + assert await async_setup_component( + hass, mqtt.DOMAIN, {mqtt.DOMAIN: {domain: config3}} + ) + await hass.async_block_till_done() + await mqtt_mock_entry_with_yaml_config() assert "Skip state recovery after reload for binary_sensor.test3" in caplog.text async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = binary_sensor.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG[platform]) + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) config["name"] = "test" del config["platform"] await help_test_setup_manual_entity_from_yaml(hass, platform, config) @@ -1085,7 +1135,20 @@ async def test_setup_manual_entity_from_yaml(hass): async def test_unload_entry(hass, mqtt_mock_entry_with_yaml_config, tmp_path): """Test unloading the config entry.""" domain = binary_sensor.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry_with_yaml_config, tmp_path, domain, config ) + + +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +async def test_setup_with_legacy_schema(hass, mqtt_mock_entry_with_yaml_config): + """Test a setup with deprecated yaml platform schema.""" + domain = binary_sensor.DOMAIN + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[domain]) + config["name"] = "test" + assert await async_setup_component(hass, domain, {domain: config}) + await hass.async_block_till_done() + await mqtt_mock_entry_with_yaml_config() + assert hass.states.get(f"{domain}.test") is not None diff --git a/tests/components/mqtt/test_button.py b/tests/components/mqtt/test_button.py index 68db846c91c8d..1274c700800b8 100644 --- a/tests/components/mqtt/test_button.py +++ b/tests/components/mqtt/test_button.py @@ -4,7 +4,7 @@ import pytest -from homeassistant.components import button +from homeassistant.components import button, mqtt from homeassistant.const import ( ATTR_ENTITY_ID, ATTR_FRIENDLY_NAME, @@ -43,9 +43,14 @@ ) DEFAULT_CONFIG = { - button.DOMAIN: {"platform": "mqtt", "name": "test", "command_topic": "test-topic"} + mqtt.DOMAIN: {button.DOMAIN: {"name": "test", "command_topic": "test-topic"}} } +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +DEFAULT_CONFIG_LEGACY = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) +DEFAULT_CONFIG_LEGACY[button.DOMAIN]["platform"] = mqtt.DOMAIN + @pytest.fixture(autouse=True) def button_platform_only(): @@ -59,15 +64,16 @@ async def test_sending_mqtt_commands(hass, mqtt_mock_entry_with_yaml_config): """Test the sending MQTT commands.""" assert await async_setup_component( hass, - button.DOMAIN, + mqtt.DOMAIN, { - button.DOMAIN: { - "command_topic": "command-topic", - "name": "test", - "object_id": "test_button", - "payload_press": "beer press", - "platform": "mqtt", - "qos": "2", + mqtt.DOMAIN: { + button.DOMAIN: { + "command_topic": "command-topic", + "name": "test", + "object_id": "test_button", + "payload_press": "beer press", + "qos": "2", + } } }, ) @@ -97,14 +103,15 @@ async def test_command_template(hass, mqtt_mock_entry_with_yaml_config): """Test the sending of MQTT commands through a command template.""" assert await async_setup_component( hass, - button.DOMAIN, + mqtt.DOMAIN, { - button.DOMAIN: { - "command_topic": "command-topic", - "command_template": '{ "{{ value }}": "{{ entity_id }}" }', - "name": "test", - "payload_press": "milky_way_press", - "platform": "mqtt", + mqtt.DOMAIN: { + button.DOMAIN: { + "command_topic": "command-topic", + "command_template": '{ "{{ value }}": "{{ entity_id }}" }', + "name": "test", + "payload_press": "milky_way_press", + } } }, ) @@ -133,14 +140,14 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, button.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, button.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, button.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, button.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -193,7 +200,7 @@ async def test_setting_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_with_yaml_config, button.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, button.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -202,14 +209,14 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_blocked_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_no_yaml_config, button.DOMAIN, DEFAULT_CONFIG, None + hass, mqtt_mock_entry_no_yaml_config, button.DOMAIN, DEFAULT_CONFIG_LEGACY, None ) async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_with_template( - hass, mqtt_mock_entry_with_yaml_config, button.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, button.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -218,7 +225,11 @@ async def test_update_with_json_attrs_not_dict( ): """Test attributes get extracted from a JSON result.""" await help_test_update_with_json_attrs_not_dict( - hass, mqtt_mock_entry_with_yaml_config, caplog, button.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_with_yaml_config, + caplog, + button.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) @@ -227,14 +238,22 @@ async def test_update_with_json_attrs_bad_JSON( ): """Test attributes get extracted from a JSON result.""" await help_test_update_with_json_attrs_bad_JSON( - hass, mqtt_mock_entry_with_yaml_config, caplog, button.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_with_yaml_config, + caplog, + button.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test update of discovered MQTTAttributes.""" await help_test_discovery_update_attr( - hass, mqtt_mock_entry_no_yaml_config, caplog, button.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_no_yaml_config, + caplog, + button.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) @@ -271,8 +290,8 @@ async def test_discovery_removal_button(hass, mqtt_mock_entry_no_yaml_config, ca async def test_discovery_update_button(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test update of discovered button.""" - config1 = copy.deepcopy(DEFAULT_CONFIG[button.DOMAIN]) - config2 = copy.deepcopy(DEFAULT_CONFIG[button.DOMAIN]) + config1 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[button.DOMAIN]) + config2 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[button.DOMAIN]) config1["name"] = "Beer" config2["name"] = "Milk" @@ -321,35 +340,35 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT button device registry integration.""" await help_test_entity_device_info_with_connection( - hass, mqtt_mock_entry_no_yaml_config, button.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, button.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT button device registry integration.""" await help_test_entity_device_info_with_identifier( - hass, mqtt_mock_entry_no_yaml_config, button.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, button.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): """Test device registry update.""" await help_test_entity_device_info_update( - hass, mqtt_mock_entry_no_yaml_config, button.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, button.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test device registry remove.""" await help_test_entity_device_info_remove( - hass, mqtt_mock_entry_no_yaml_config, button.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, button.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, button.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, button.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -359,59 +378,54 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): hass, mqtt_mock_entry_no_yaml_config, button.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, button.SERVICE_PRESS, command_payload="PRESS", state_topic=None, ) -async def test_invalid_device_class(hass, mqtt_mock_entry_no_yaml_config): +async def test_invalid_device_class(hass): """Test device_class option with invalid value.""" - assert await async_setup_component( + assert not await async_setup_component( hass, - button.DOMAIN, + mqtt.DOMAIN, { - button.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "test-topic", - "device_class": "foobarnotreal", + mqtt.DOMAIN: { + button.DOMAIN: { + "name": "test", + "state_topic": "test-topic", + "device_class": "foobarnotreal", + } } }, ) - await hass.async_block_till_done() - await mqtt_mock_entry_no_yaml_config() - - state = hass.states.get("button.test") - assert state is None async def test_valid_device_class(hass, mqtt_mock_entry_with_yaml_config): """Test device_class option with valid values.""" assert await async_setup_component( hass, - button.DOMAIN, + mqtt.DOMAIN, { - button.DOMAIN: [ - { - "platform": "mqtt", - "name": "Test 1", - "command_topic": "test-topic", - "device_class": "update", - }, - { - "platform": "mqtt", - "name": "Test 2", - "command_topic": "test-topic", - "device_class": "restart", - }, - { - "platform": "mqtt", - "name": "Test 3", - "command_topic": "test-topic", - }, - ] + mqtt.DOMAIN: { + button.DOMAIN: [ + { + "name": "Test 1", + "command_topic": "test-topic", + "device_class": "update", + }, + { + "name": "Test 2", + "command_topic": "test-topic", + "device_class": "restart", + }, + { + "name": "Test 3", + "command_topic": "test-topic", + }, + ] + } }, ) await hass.async_block_till_done() @@ -443,7 +457,7 @@ async def test_publishing_with_custom_encoding( ): """Test publishing MQTT payload with different encoding.""" domain = button.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_publishing_with_custom_encoding( hass, @@ -462,7 +476,7 @@ async def test_publishing_with_custom_encoding( async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = button.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) @@ -471,14 +485,14 @@ async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_pa async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = button.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable_late(hass, caplog, tmp_path, domain, config) async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = button.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG[platform]) + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) config["name"] = "test" del config["platform"] await help_test_setup_manual_entity_from_yaml(hass, platform, config) @@ -488,7 +502,20 @@ async def test_setup_manual_entity_from_yaml(hass): async def test_unload_entry(hass, mqtt_mock_entry_with_yaml_config, tmp_path): """Test unloading the config entry.""" domain = button.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry_with_yaml_config, tmp_path, domain, config ) + + +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +async def test_setup_with_legacy_schema(hass, mqtt_mock_entry_with_yaml_config): + """Test a setup with deprecated yaml platform schema.""" + domain = button.DOMAIN + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[domain]) + config["name"] = "test" + assert await async_setup_component(hass, domain, {domain: config}) + await hass.async_block_till_done() + await mqtt_mock_entry_with_yaml_config() + assert hass.states.get(f"{domain}.test") is not None diff --git a/tests/components/mqtt/test_camera.py b/tests/components/mqtt/test_camera.py index a76025a608a55..4d0b2fbfca062 100644 --- a/tests/components/mqtt/test_camera.py +++ b/tests/components/mqtt/test_camera.py @@ -7,7 +7,7 @@ import pytest -from homeassistant.components import camera +from homeassistant.components import camera, mqtt from homeassistant.components.mqtt.camera import MQTT_CAMERA_ATTRIBUTES_BLOCKED from homeassistant.const import Platform from homeassistant.setup import async_setup_component @@ -43,9 +43,12 @@ from tests.common import async_fire_mqtt_message -DEFAULT_CONFIG = { - camera.DOMAIN: {"platform": "mqtt", "name": "test", "topic": "test_topic"} -} +DEFAULT_CONFIG = {mqtt.DOMAIN: {camera.DOMAIN: {"name": "test", "topic": "test_topic"}}} + +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +DEFAULT_CONFIG_LEGACY = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) +DEFAULT_CONFIG_LEGACY[camera.DOMAIN]["platform"] = mqtt.DOMAIN @pytest.fixture(autouse=True) @@ -62,8 +65,8 @@ async def test_run_camera_setup( topic = "test/camera" await async_setup_component( hass, - "camera", - {"camera": {"platform": "mqtt", "topic": topic, "name": "Test Camera"}}, + mqtt.DOMAIN, + {mqtt.DOMAIN: {camera.DOMAIN: {"topic": topic, "name": "Test Camera"}}}, ) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -86,13 +89,14 @@ async def test_run_camera_b64_encoded( topic = "test/camera" await async_setup_component( hass, - "camera", + mqtt.DOMAIN, { - "camera": { - "platform": "mqtt", - "topic": topic, - "name": "Test Camera", - "encoding": "b64", + mqtt.DOMAIN: { + camera.DOMAIN: { + "topic": topic, + "name": "Test Camera", + "encoding": "b64", + } } }, ) @@ -110,7 +114,7 @@ async def test_run_camera_b64_encoded( assert body == "grass" -# Using CONF_ENCODING to set b64 encoding for images is deprecated Home Assistant 2022.9, use CONF_IMAGE_ENCODING instead +# Using CONF_ENCODING to set b64 encoding for images is deprecated in Home Assistant 2022.9, use CONF_IMAGE_ENCODING instead async def test_legacy_camera_b64_encoded_with_availability( hass, hass_client_no_auth, mqtt_mock_entry_with_yaml_config ): @@ -119,14 +123,15 @@ async def test_legacy_camera_b64_encoded_with_availability( topic_availability = "test/camera_availability" await async_setup_component( hass, - "camera", + mqtt.DOMAIN, { - "camera": { - "platform": "mqtt", - "topic": topic, - "name": "Test Camera", - "encoding": "b64", - "availability": {"topic": topic_availability}, + mqtt.DOMAIN: { + camera.DOMAIN: { + "topic": topic, + "name": "Test Camera", + "encoding": "b64", + "availability": {"topic": topic_availability}, + } } }, ) @@ -155,15 +160,16 @@ async def test_camera_b64_encoded_with_availability( topic_availability = "test/camera_availability" await async_setup_component( hass, - "camera", + mqtt.DOMAIN, { - "camera": { - "platform": "mqtt", - "topic": topic, - "name": "Test Camera", - "encoding": "utf-8", - "image_encoding": "b64", - "availability": {"topic": topic_availability}, + mqtt.DOMAIN: { + "camera": { + "topic": topic, + "name": "Test Camera", + "encoding": "utf-8", + "image_encoding": "b64", + "availability": {"topic": topic_availability}, + } } }, ) @@ -189,28 +195,28 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, camera.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, camera.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, camera.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, camera.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by default payload with defined topic.""" await help_test_default_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, camera.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, camera.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by custom payload with defined topic.""" await help_test_custom_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, camera.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, camera.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -219,7 +225,7 @@ async def test_setting_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_with_yaml_config, camera.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, camera.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -231,7 +237,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( hass, mqtt_mock_entry_no_yaml_config, camera.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, MQTT_CAMERA_ATTRIBUTES_BLOCKED, ) @@ -239,7 +245,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_with_template( - hass, mqtt_mock_entry_with_yaml_config, camera.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, camera.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -248,7 +254,11 @@ async def test_update_with_json_attrs_not_dict( ): """Test attributes get extracted from a JSON result.""" await help_test_update_with_json_attrs_not_dict( - hass, mqtt_mock_entry_with_yaml_config, caplog, camera.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_with_yaml_config, + caplog, + camera.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) @@ -257,14 +267,22 @@ async def test_update_with_json_attrs_bad_JSON( ): """Test attributes get extracted from a JSON result.""" await help_test_update_with_json_attrs_bad_JSON( - hass, mqtt_mock_entry_with_yaml_config, caplog, camera.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_with_yaml_config, + caplog, + camera.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test update of discovered MQTTAttributes.""" await help_test_discovery_update_attr( - hass, mqtt_mock_entry_no_yaml_config, caplog, camera.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_no_yaml_config, + caplog, + camera.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) @@ -293,7 +311,7 @@ async def test_unique_id(hass, mqtt_mock_entry_with_yaml_config): async def test_discovery_removal_camera(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test removal of discovered camera.""" - data = json.dumps(DEFAULT_CONFIG[camera.DOMAIN]) + data = json.dumps(DEFAULT_CONFIG_LEGACY[camera.DOMAIN]) await help_test_discovery_removal( hass, mqtt_mock_entry_no_yaml_config, caplog, camera.DOMAIN, data ) @@ -341,28 +359,28 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT camera device registry integration.""" await help_test_entity_device_info_with_connection( - hass, mqtt_mock_entry_no_yaml_config, camera.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, camera.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT camera device registry integration.""" await help_test_entity_device_info_with_identifier( - hass, mqtt_mock_entry_no_yaml_config, camera.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, camera.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): """Test device registry update.""" await help_test_entity_device_info_update( - hass, mqtt_mock_entry_no_yaml_config, camera.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, camera.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test device registry remove.""" await help_test_entity_device_info_remove( - hass, mqtt_mock_entry_no_yaml_config, camera.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, camera.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -372,7 +390,7 @@ async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_co hass, mqtt_mock_entry_with_yaml_config, camera.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, ["test_topic"], ) @@ -380,7 +398,7 @@ async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_co async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, camera.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, camera.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -390,7 +408,7 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): hass, mqtt_mock_entry_no_yaml_config, camera.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, None, state_topic="test_topic", state_payload=b"ON", @@ -400,7 +418,7 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = camera.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) @@ -409,14 +427,14 @@ async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_pa async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = camera.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable_late(hass, caplog, tmp_path, domain, config) async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = camera.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG[platform]) + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) config["name"] = "test" del config["platform"] await help_test_setup_manual_entity_from_yaml(hass, platform, config) @@ -426,7 +444,20 @@ async def test_setup_manual_entity_from_yaml(hass): async def test_unload_entry(hass, mqtt_mock_entry_with_yaml_config, tmp_path): """Test unloading the config entry.""" domain = camera.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry_with_yaml_config, tmp_path, domain, config ) + + +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +async def test_setup_with_legacy_schema(hass, mqtt_mock_entry_with_yaml_config): + """Test a setup with deprecated yaml platform schema.""" + domain = camera.DOMAIN + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[domain]) + config["name"] = "test" + assert await async_setup_component(hass, domain, {domain: config}) + await hass.async_block_till_done() + await mqtt_mock_entry_with_yaml_config() + assert hass.states.get(f"{domain}.test") is not None diff --git a/tests/components/mqtt/test_climate.py b/tests/components/mqtt/test_climate.py index d5164e8571835..14bd9084abe4e 100644 --- a/tests/components/mqtt/test_climate.py +++ b/tests/components/mqtt/test_climate.py @@ -6,7 +6,7 @@ import pytest import voluptuous as vol -from homeassistant.components import climate +from homeassistant.components import climate, mqtt from homeassistant.components.climate import DEFAULT_MAX_TEMP, DEFAULT_MIN_TEMP from homeassistant.components.climate.const import ( ATTR_AUX_HEAT, @@ -16,10 +16,9 @@ ATTR_SWING_MODE, ATTR_TARGET_TEMP_HIGH, ATTR_TARGET_TEMP_LOW, - CURRENT_HVAC_ACTIONS, - DOMAIN as CLIMATE_DOMAIN, PRESET_ECO, ClimateEntityFeature, + HVACAction, HVACMode, ) from homeassistant.components.mqtt.climate import MQTT_CLIMATE_ATTRIBUTES_BLOCKED @@ -62,30 +61,37 @@ ENTITY_CLIMATE = "climate.test" + DEFAULT_CONFIG = { - CLIMATE_DOMAIN: { - "platform": "mqtt", - "name": "test", - "mode_command_topic": "mode-topic", - "temperature_command_topic": "temperature-topic", - "temperature_low_command_topic": "temperature-low-topic", - "temperature_high_command_topic": "temperature-high-topic", - "fan_mode_command_topic": "fan-mode-topic", - "swing_mode_command_topic": "swing-mode-topic", - "aux_command_topic": "aux-topic", - "preset_mode_command_topic": "preset-mode-topic", - "preset_modes": [ - "eco", - "away", - "boost", - "comfort", - "home", - "sleep", - "activity", - ], + mqtt.DOMAIN: { + climate.DOMAIN: { + "name": "test", + "mode_command_topic": "mode-topic", + "temperature_command_topic": "temperature-topic", + "temperature_low_command_topic": "temperature-low-topic", + "temperature_high_command_topic": "temperature-high-topic", + "fan_mode_command_topic": "fan-mode-topic", + "swing_mode_command_topic": "swing-mode-topic", + "aux_command_topic": "aux-topic", + "preset_mode_command_topic": "preset-mode-topic", + "preset_modes": [ + "eco", + "away", + "boost", + "comfort", + "home", + "sleep", + "activity", + ], + } } } +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +DEFAULT_CONFIG_LEGACY = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) +DEFAULT_CONFIG_LEGACY[climate.DOMAIN]["platform"] = mqtt.DOMAIN + @pytest.fixture(autouse=True) def climate_platform_only(): @@ -96,7 +102,7 @@ def climate_platform_only(): async def test_setup_params(hass, mqtt_mock_entry_with_yaml_config): """Test the initial parameters.""" - assert await async_setup_component(hass, CLIMATE_DOMAIN, DEFAULT_CONFIG) + assert await async_setup_component(hass, mqtt.DOMAIN, DEFAULT_CONFIG) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -109,18 +115,14 @@ async def test_setup_params(hass, mqtt_mock_entry_with_yaml_config): assert state.attributes.get("max_temp") == DEFAULT_MAX_TEMP -async def test_preset_none_in_preset_modes( - hass, mqtt_mock_entry_no_yaml_config, caplog -): +async def test_preset_none_in_preset_modes(hass, caplog): """Test the preset mode payload reset configuration.""" - config = copy.deepcopy(DEFAULT_CONFIG[CLIMATE_DOMAIN]) + config = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][climate.DOMAIN]) config["preset_modes"].append("none") - assert await async_setup_component(hass, CLIMATE_DOMAIN, {CLIMATE_DOMAIN: config}) - await hass.async_block_till_done() - await mqtt_mock_entry_no_yaml_config() - assert "Invalid config for [climate.mqtt]: not a valid value" in caplog.text - state = hass.states.get(ENTITY_CLIMATE) - assert state is None + assert not await async_setup_component( + hass, mqtt.DOMAIN, {mqtt.DOMAIN: {climate.DOMAIN: config}} + ) + assert "Invalid config for [mqtt]: not a valid value" in caplog.text # AWAY and HOLD mode topics and templates are deprecated, support will be removed with release 2022.9 @@ -136,22 +138,19 @@ async def test_preset_none_in_preset_modes( ("hold_mode_state_template", "{{ value_json }}"), ], ) -async def test_preset_modes_deprecation_guard( - hass, mqtt_mock_entry_no_yaml_config, caplog, parameter, config_value -): +async def test_preset_modes_deprecation_guard(hass, caplog, parameter, config_value): """Test the configuration for invalid legacy parameters.""" - config = copy.deepcopy(DEFAULT_CONFIG[CLIMATE_DOMAIN]) + config = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][climate.DOMAIN]) config[parameter] = config_value - assert await async_setup_component(hass, CLIMATE_DOMAIN, {CLIMATE_DOMAIN: config}) - await hass.async_block_till_done() - await mqtt_mock_entry_no_yaml_config() - state = hass.states.get(ENTITY_CLIMATE) - assert state is None + assert not await async_setup_component( + hass, mqtt.DOMAIN, {mqtt.DOMAIN: {climate.DOMAIN: config}} + ) + assert f"[{parameter}] is an invalid option for [mqtt]. Check: mqtt->mqtt->climate->0->{parameter}" async def test_supported_features(hass, mqtt_mock_entry_with_yaml_config): """Test the supported_features.""" - assert await async_setup_component(hass, CLIMATE_DOMAIN, DEFAULT_CONFIG) + assert await async_setup_component(hass, mqtt.DOMAIN, DEFAULT_CONFIG) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -170,7 +169,7 @@ async def test_supported_features(hass, mqtt_mock_entry_with_yaml_config): async def test_get_hvac_modes(hass, mqtt_mock_entry_with_yaml_config): """Test that the operation list returns the correct modes.""" - assert await async_setup_component(hass, CLIMATE_DOMAIN, DEFAULT_CONFIG) + assert await async_setup_component(hass, mqtt.DOMAIN, DEFAULT_CONFIG) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -193,7 +192,7 @@ async def test_set_operation_bad_attr_and_state( Also check the state. """ - assert await async_setup_component(hass, CLIMATE_DOMAIN, DEFAULT_CONFIG) + assert await async_setup_component(hass, mqtt.DOMAIN, DEFAULT_CONFIG) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -210,7 +209,7 @@ async def test_set_operation_bad_attr_and_state( async def test_set_operation(hass, mqtt_mock_entry_with_yaml_config): """Test setting of new operation mode.""" - assert await async_setup_component(hass, CLIMATE_DOMAIN, DEFAULT_CONFIG) + assert await async_setup_component(hass, mqtt.DOMAIN, DEFAULT_CONFIG) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -225,9 +224,9 @@ async def test_set_operation(hass, mqtt_mock_entry_with_yaml_config): async def test_set_operation_pessimistic(hass, mqtt_mock_entry_with_yaml_config): """Test setting operation mode in pessimistic mode.""" - config = copy.deepcopy(DEFAULT_CONFIG) + config = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) config["climate"]["mode_state_topic"] = "mode-state" - assert await async_setup_component(hass, CLIMATE_DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -249,9 +248,9 @@ async def test_set_operation_pessimistic(hass, mqtt_mock_entry_with_yaml_config) async def test_set_operation_with_power_command(hass, mqtt_mock_entry_with_yaml_config): """Test setting of new operation mode with power command enabled.""" - config = copy.deepcopy(DEFAULT_CONFIG) + config = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) config["climate"]["power_command_topic"] = "power-command" - assert await async_setup_component(hass, CLIMATE_DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -276,7 +275,7 @@ async def test_set_operation_with_power_command(hass, mqtt_mock_entry_with_yaml_ async def test_set_fan_mode_bad_attr(hass, mqtt_mock_entry_with_yaml_config, caplog): """Test setting fan mode without required attribute.""" - assert await async_setup_component(hass, CLIMATE_DOMAIN, DEFAULT_CONFIG) + assert await async_setup_component(hass, mqtt.DOMAIN, DEFAULT_CONFIG) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -293,9 +292,9 @@ async def test_set_fan_mode_bad_attr(hass, mqtt_mock_entry_with_yaml_config, cap async def test_set_fan_mode_pessimistic(hass, mqtt_mock_entry_with_yaml_config): """Test setting of new fan mode in pessimistic mode.""" - config = copy.deepcopy(DEFAULT_CONFIG) + config = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) config["climate"]["fan_mode_state_topic"] = "fan-state" - assert await async_setup_component(hass, CLIMATE_DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -317,7 +316,7 @@ async def test_set_fan_mode_pessimistic(hass, mqtt_mock_entry_with_yaml_config): async def test_set_fan_mode(hass, mqtt_mock_entry_with_yaml_config): """Test setting of new fan mode.""" - assert await async_setup_component(hass, CLIMATE_DOMAIN, DEFAULT_CONFIG) + assert await async_setup_component(hass, mqtt.DOMAIN, DEFAULT_CONFIG) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -331,7 +330,7 @@ async def test_set_fan_mode(hass, mqtt_mock_entry_with_yaml_config): async def test_set_swing_mode_bad_attr(hass, mqtt_mock_entry_with_yaml_config, caplog): """Test setting swing mode without required attribute.""" - assert await async_setup_component(hass, CLIMATE_DOMAIN, DEFAULT_CONFIG) + assert await async_setup_component(hass, mqtt.DOMAIN, DEFAULT_CONFIG) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -348,9 +347,9 @@ async def test_set_swing_mode_bad_attr(hass, mqtt_mock_entry_with_yaml_config, c async def test_set_swing_pessimistic(hass, mqtt_mock_entry_with_yaml_config): """Test setting swing mode in pessimistic mode.""" - config = copy.deepcopy(DEFAULT_CONFIG) + config = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) config["climate"]["swing_mode_state_topic"] = "swing-state" - assert await async_setup_component(hass, CLIMATE_DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -372,7 +371,7 @@ async def test_set_swing_pessimistic(hass, mqtt_mock_entry_with_yaml_config): async def test_set_swing(hass, mqtt_mock_entry_with_yaml_config): """Test setting of new swing mode.""" - assert await async_setup_component(hass, CLIMATE_DOMAIN, DEFAULT_CONFIG) + assert await async_setup_component(hass, mqtt.DOMAIN, DEFAULT_CONFIG) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -386,7 +385,7 @@ async def test_set_swing(hass, mqtt_mock_entry_with_yaml_config): async def test_set_target_temperature(hass, mqtt_mock_entry_with_yaml_config): """Test setting the target temperature.""" - assert await async_setup_component(hass, CLIMATE_DOMAIN, DEFAULT_CONFIG) + assert await async_setup_component(hass, mqtt.DOMAIN, DEFAULT_CONFIG) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -425,9 +424,9 @@ async def test_set_target_temperature_pessimistic( hass, mqtt_mock_entry_with_yaml_config ): """Test setting the target temperature.""" - config = copy.deepcopy(DEFAULT_CONFIG) + config = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) config["climate"]["temperature_state_topic"] = "temperature-state" - assert await async_setup_component(hass, CLIMATE_DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -449,7 +448,7 @@ async def test_set_target_temperature_pessimistic( async def test_set_target_temperature_low_high(hass, mqtt_mock_entry_with_yaml_config): """Test setting the low/high target temperature.""" - assert await async_setup_component(hass, CLIMATE_DOMAIN, DEFAULT_CONFIG) + assert await async_setup_component(hass, mqtt.DOMAIN, DEFAULT_CONFIG) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -467,10 +466,10 @@ async def test_set_target_temperature_low_highpessimistic( hass, mqtt_mock_entry_with_yaml_config ): """Test setting the low/high target temperature.""" - config = copy.deepcopy(DEFAULT_CONFIG) + config = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) config["climate"]["temperature_low_state_topic"] = "temperature-low-state" config["climate"]["temperature_high_state_topic"] = "temperature-high-state" - assert await async_setup_component(hass, CLIMATE_DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -505,9 +504,9 @@ async def test_set_target_temperature_low_highpessimistic( async def test_receive_mqtt_temperature(hass, mqtt_mock_entry_with_yaml_config): """Test getting the current temperature via MQTT.""" - config = copy.deepcopy(DEFAULT_CONFIG) + config = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) config["climate"]["current_temperature_topic"] = "current_temperature" - assert await async_setup_component(hass, CLIMATE_DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -518,9 +517,9 @@ async def test_receive_mqtt_temperature(hass, mqtt_mock_entry_with_yaml_config): async def test_handle_action_received(hass, mqtt_mock_entry_with_yaml_config): """Test getting the action received via MQTT.""" - config = copy.deepcopy(DEFAULT_CONFIG) + config = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) config["climate"]["action_topic"] = "action" - assert await async_setup_component(hass, CLIMATE_DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -531,7 +530,7 @@ async def test_handle_action_received(hass, mqtt_mock_entry_with_yaml_config): assert hvac_action is None # Redefine actions according to https://developers.home-assistant.io/docs/core/entity/climate/#hvac-action actions = ["off", "heating", "cooling", "drying", "idle", "fan"] - assert all(elem in actions for elem in CURRENT_HVAC_ACTIONS) + assert all(elem in actions for elem in HVACAction) for action in actions: async_fire_mqtt_message(hass, "action", action) state = hass.states.get(ENTITY_CLIMATE) @@ -543,8 +542,8 @@ async def test_set_preset_mode_optimistic( hass, mqtt_mock_entry_with_yaml_config, caplog ): """Test setting of the preset mode.""" - config = copy.deepcopy(DEFAULT_CONFIG) - assert await async_setup_component(hass, CLIMATE_DOMAIN, config) + config = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -591,9 +590,9 @@ async def test_set_preset_mode_pessimistic( hass, mqtt_mock_entry_with_yaml_config, caplog ): """Test setting of the preset mode.""" - config = copy.deepcopy(DEFAULT_CONFIG) + config = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) config["climate"]["preset_mode_state_topic"] = "preset-mode-state" - assert await async_setup_component(hass, CLIMATE_DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -636,9 +635,9 @@ async def test_set_preset_mode_pessimistic( async def test_set_aux_pessimistic(hass, mqtt_mock_entry_with_yaml_config): """Test setting of the aux heating in pessimistic mode.""" - config = copy.deepcopy(DEFAULT_CONFIG) + config = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) config["climate"]["aux_state_topic"] = "aux-state" - assert await async_setup_component(hass, CLIMATE_DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -664,7 +663,7 @@ async def test_set_aux_pessimistic(hass, mqtt_mock_entry_with_yaml_config): async def test_set_aux(hass, mqtt_mock_entry_with_yaml_config): """Test setting of the aux heating.""" - assert await async_setup_component(hass, CLIMATE_DOMAIN, DEFAULT_CONFIG) + assert await async_setup_component(hass, mqtt.DOMAIN, DEFAULT_CONFIG) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -687,28 +686,28 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, CLIMATE_DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, climate.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, CLIMATE_DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, climate.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by default payload with defined topic.""" await help_test_default_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, CLIMATE_DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, climate.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by custom payload with defined topic.""" await help_test_custom_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, CLIMATE_DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, climate.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -716,13 +715,13 @@ async def test_get_target_temperature_low_high_with_templates( hass, mqtt_mock_entry_with_yaml_config, caplog ): """Test getting temperature high/low with templates.""" - config = copy.deepcopy(DEFAULT_CONFIG) + config = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) config["climate"]["temperature_low_state_topic"] = "temperature-state" config["climate"]["temperature_high_state_topic"] = "temperature-state" config["climate"]["temperature_low_state_template"] = "{{ value_json.temp_low }}" config["climate"]["temperature_high_state_template"] = "{{ value_json.temp_high }}" - assert await async_setup_component(hass, CLIMATE_DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -751,7 +750,7 @@ async def test_get_target_temperature_low_high_with_templates( async def test_get_with_templates(hass, mqtt_mock_entry_with_yaml_config, caplog): """Test getting various attributes with templates.""" - config = copy.deepcopy(DEFAULT_CONFIG) + config = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) # By default, just unquote the JSON-strings config["climate"]["value_template"] = "{{ value_json }}" config["climate"]["action_template"] = "{{ value_json }}" @@ -768,7 +767,7 @@ async def test_get_with_templates(hass, mqtt_mock_entry_with_yaml_config, caplog config["climate"]["aux_state_topic"] = "aux-state" config["climate"]["current_temperature_topic"] = "current-temperature" config["climate"]["preset_mode_state_topic"] = "current-preset-mode" - assert await async_setup_component(hass, CLIMATE_DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -850,7 +849,7 @@ async def test_get_with_templates(hass, mqtt_mock_entry_with_yaml_config, caplog async def test_set_and_templates(hass, mqtt_mock_entry_with_yaml_config, caplog): """Test setting various attributes with templates.""" - config = copy.deepcopy(DEFAULT_CONFIG) + config = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) # Create simple templates config["climate"]["fan_mode_command_template"] = "fan_mode: {{ value }}" config["climate"]["preset_mode_command_template"] = "preset_mode: {{ value }}" @@ -860,7 +859,7 @@ async def test_set_and_templates(hass, mqtt_mock_entry_with_yaml_config, caplog) config["climate"]["temperature_high_command_template"] = "temp_hi: {{ value }}" config["climate"]["temperature_low_command_template"] = "temp_lo: {{ value }}" - assert await async_setup_component(hass, CLIMATE_DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -928,10 +927,10 @@ async def test_set_and_templates(hass, mqtt_mock_entry_with_yaml_config, caplog) async def test_min_temp_custom(hass, mqtt_mock_entry_with_yaml_config): """Test a custom min temp.""" - config = copy.deepcopy(DEFAULT_CONFIG) + config = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) config["climate"]["min_temp"] = 26 - assert await async_setup_component(hass, CLIMATE_DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -944,10 +943,10 @@ async def test_min_temp_custom(hass, mqtt_mock_entry_with_yaml_config): async def test_max_temp_custom(hass, mqtt_mock_entry_with_yaml_config): """Test a custom max temp.""" - config = copy.deepcopy(DEFAULT_CONFIG) + config = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) config["climate"]["max_temp"] = 60 - assert await async_setup_component(hass, CLIMATE_DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -960,10 +959,10 @@ async def test_max_temp_custom(hass, mqtt_mock_entry_with_yaml_config): async def test_temp_step_custom(hass, mqtt_mock_entry_with_yaml_config): """Test a custom temp step.""" - config = copy.deepcopy(DEFAULT_CONFIG) + config = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) config["climate"]["temp_step"] = 0.01 - assert await async_setup_component(hass, CLIMATE_DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -976,11 +975,11 @@ async def test_temp_step_custom(hass, mqtt_mock_entry_with_yaml_config): async def test_temperature_unit(hass, mqtt_mock_entry_with_yaml_config): """Test that setting temperature unit converts temperature values.""" - config = copy.deepcopy(DEFAULT_CONFIG) + config = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) config["climate"]["temperature_unit"] = "F" config["climate"]["current_temperature_topic"] = "current_temperature" - assert await async_setup_component(hass, CLIMATE_DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -995,7 +994,7 @@ async def test_setting_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_with_yaml_config, CLIMATE_DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, climate.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -1006,8 +1005,8 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( await help_test_setting_blocked_attribute_via_mqtt_json_message( hass, mqtt_mock_entry_no_yaml_config, - CLIMATE_DOMAIN, - DEFAULT_CONFIG, + climate.DOMAIN, + DEFAULT_CONFIG_LEGACY, MQTT_CLIMATE_ATTRIBUTES_BLOCKED, ) @@ -1015,7 +1014,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_with_template( - hass, mqtt_mock_entry_with_yaml_config, CLIMATE_DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, climate.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -1024,7 +1023,11 @@ async def test_update_with_json_attrs_not_dict( ): """Test attributes get extracted from a JSON result.""" await help_test_update_with_json_attrs_not_dict( - hass, mqtt_mock_entry_with_yaml_config, caplog, CLIMATE_DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_with_yaml_config, + caplog, + climate.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) @@ -1033,21 +1036,29 @@ async def test_update_with_json_attrs_bad_JSON( ): """Test attributes get extracted from a JSON result.""" await help_test_update_with_json_attrs_bad_JSON( - hass, mqtt_mock_entry_with_yaml_config, caplog, CLIMATE_DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_with_yaml_config, + caplog, + climate.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test update of discovered MQTTAttributes.""" await help_test_discovery_update_attr( - hass, mqtt_mock_entry_no_yaml_config, caplog, CLIMATE_DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_no_yaml_config, + caplog, + climate.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) async def test_unique_id(hass, mqtt_mock_entry_with_yaml_config): """Test unique id option only creates one climate per unique_id.""" config = { - CLIMATE_DOMAIN: [ + climate.DOMAIN: [ { "platform": "mqtt", "name": "Test 1", @@ -1065,7 +1076,7 @@ async def test_unique_id(hass, mqtt_mock_entry_with_yaml_config): ] } await help_test_unique_id( - hass, mqtt_mock_entry_with_yaml_config, CLIMATE_DOMAIN, config + hass, mqtt_mock_entry_with_yaml_config, climate.DOMAIN, config ) @@ -1095,12 +1106,12 @@ async def test_encoding_subscribable_topics( attribute_value, ): """Test handling of incoming encoded payload.""" - config = copy.deepcopy(DEFAULT_CONFIG[CLIMATE_DOMAIN]) + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[climate.DOMAIN]) await help_test_encoding_subscribable_topics( hass, mqtt_mock_entry_with_yaml_config, caplog, - CLIMATE_DOMAIN, + climate.DOMAIN, config, topic, value, @@ -1111,9 +1122,9 @@ async def test_encoding_subscribable_topics( async def test_discovery_removal_climate(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test removal of discovered climate.""" - data = json.dumps(DEFAULT_CONFIG[CLIMATE_DOMAIN]) + data = json.dumps(DEFAULT_CONFIG_LEGACY[climate.DOMAIN]) await help_test_discovery_removal( - hass, mqtt_mock_entry_no_yaml_config, caplog, CLIMATE_DOMAIN, data + hass, mqtt_mock_entry_no_yaml_config, caplog, climate.DOMAIN, data ) @@ -1122,7 +1133,7 @@ async def test_discovery_update_climate(hass, mqtt_mock_entry_no_yaml_config, ca config1 = {"name": "Beer"} config2 = {"name": "Milk"} await help_test_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, caplog, CLIMATE_DOMAIN, config1, config2 + hass, mqtt_mock_entry_no_yaml_config, caplog, climate.DOMAIN, config1, config2 ) @@ -1138,7 +1149,7 @@ async def test_discovery_update_unchanged_climate( hass, mqtt_mock_entry_no_yaml_config, caplog, - CLIMATE_DOMAIN, + climate.DOMAIN, data1, discovery_update, ) @@ -1150,42 +1161,42 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): data1 = '{ "name": "Beer", "power_command_topic": "test_topic#" }' data2 = '{ "name": "Milk", "power_command_topic": "test_topic" }' await help_test_discovery_broken( - hass, mqtt_mock_entry_no_yaml_config, caplog, CLIMATE_DOMAIN, data1, data2 + hass, mqtt_mock_entry_no_yaml_config, caplog, climate.DOMAIN, data1, data2 ) async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT climate device registry integration.""" await help_test_entity_device_info_with_connection( - hass, mqtt_mock_entry_no_yaml_config, CLIMATE_DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, climate.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT climate device registry integration.""" await help_test_entity_device_info_with_identifier( - hass, mqtt_mock_entry_no_yaml_config, CLIMATE_DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, climate.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): """Test device registry update.""" await help_test_entity_device_info_update( - hass, mqtt_mock_entry_no_yaml_config, CLIMATE_DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, climate.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test device registry remove.""" await help_test_entity_device_info_remove( - hass, mqtt_mock_entry_no_yaml_config, CLIMATE_DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, climate.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_config): """Test MQTT subscriptions are managed when entity_id is updated.""" config = { - CLIMATE_DOMAIN: { + climate.DOMAIN: { "platform": "mqtt", "name": "test", "mode_state_topic": "test-topic", @@ -1195,7 +1206,7 @@ async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_co await help_test_entity_id_update_subscriptions( hass, mqtt_mock_entry_with_yaml_config, - CLIMATE_DOMAIN, + climate.DOMAIN, config, ["test-topic", "avty-topic"], ) @@ -1204,14 +1215,14 @@ async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_co async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, CLIMATE_DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, climate.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT debug info.""" config = { - CLIMATE_DOMAIN: { + climate.DOMAIN: { "platform": "mqtt", "name": "test", "mode_command_topic": "command-topic", @@ -1221,7 +1232,7 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): await help_test_entity_debug_info_message( hass, mqtt_mock_entry_no_yaml_config, - CLIMATE_DOMAIN, + climate.DOMAIN, config, climate.SERVICE_TURN_ON, command_topic="command-topic", @@ -1232,7 +1243,7 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): async def test_precision_default(hass, mqtt_mock_entry_with_yaml_config): """Test that setting precision to tenths works as intended.""" - assert await async_setup_component(hass, CLIMATE_DOMAIN, DEFAULT_CONFIG) + assert await async_setup_component(hass, mqtt.DOMAIN, DEFAULT_CONFIG) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -1246,9 +1257,9 @@ async def test_precision_default(hass, mqtt_mock_entry_with_yaml_config): async def test_precision_halves(hass, mqtt_mock_entry_with_yaml_config): """Test that setting precision to halves works as intended.""" - config = copy.deepcopy(DEFAULT_CONFIG) + config = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) config["climate"]["precision"] = 0.5 - assert await async_setup_component(hass, CLIMATE_DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -1262,9 +1273,9 @@ async def test_precision_halves(hass, mqtt_mock_entry_with_yaml_config): async def test_precision_whole(hass, mqtt_mock_entry_with_yaml_config): """Test that setting precision to whole works as intended.""" - config = copy.deepcopy(DEFAULT_CONFIG) + config = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) config["climate"]["precision"] = 1.0 - assert await async_setup_component(hass, CLIMATE_DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -1364,7 +1375,7 @@ async def test_publishing_with_custom_encoding( ): """Test publishing MQTT payload with different encoding.""" domain = climate.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG[domain]) + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[domain]) if topic != "preset_mode_command_topic": del config["preset_mode_command_topic"] del config["preset_modes"] @@ -1385,8 +1396,8 @@ async def test_publishing_with_custom_encoding( async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" - domain = CLIMATE_DOMAIN - config = DEFAULT_CONFIG[domain] + domain = climate.DOMAIN + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) @@ -1394,15 +1405,15 @@ async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_pa async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" - domain = CLIMATE_DOMAIN - config = DEFAULT_CONFIG[domain] + domain = climate.DOMAIN + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable_late(hass, caplog, tmp_path, domain, config) async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" - platform = CLIMATE_DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG[platform]) + platform = climate.DOMAIN + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) config["name"] = "test" del config["platform"] await help_test_setup_manual_entity_from_yaml(hass, platform, config) @@ -1412,7 +1423,20 @@ async def test_setup_manual_entity_from_yaml(hass): async def test_unload_entry(hass, mqtt_mock_entry_with_yaml_config, tmp_path): """Test unloading the config entry.""" domain = climate.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry_with_yaml_config, tmp_path, domain, config ) + + +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +async def test_setup_with_legacy_schema(hass, mqtt_mock_entry_with_yaml_config): + """Test a setup with deprecated yaml platform schema.""" + domain = climate.DOMAIN + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[domain]) + config["name"] = "test" + assert await async_setup_component(hass, domain, {domain: config}) + await hass.async_block_till_done() + await mqtt_mock_entry_with_yaml_config() + assert hass.states.get(f"{domain}.test") is not None diff --git a/tests/components/mqtt/test_cover.py b/tests/components/mqtt/test_cover.py index b1c162073edfe..a91f0ecc6cab5 100644 --- a/tests/components/mqtt/test_cover.py +++ b/tests/components/mqtt/test_cover.py @@ -5,7 +5,7 @@ import pytest -from homeassistant.components import cover +from homeassistant.components import cover, mqtt from homeassistant.components.cover import ( ATTR_CURRENT_POSITION, ATTR_CURRENT_TILT_POSITION, @@ -81,9 +81,14 @@ from tests.common import async_fire_mqtt_message DEFAULT_CONFIG = { - cover.DOMAIN: {"platform": "mqtt", "name": "test", "state_topic": "test-topic"} + mqtt.DOMAIN: {cover.DOMAIN: {"name": "test", "state_topic": "test-topic"}} } +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +DEFAULT_CONFIG_LEGACY = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) +DEFAULT_CONFIG_LEGACY[cover.DOMAIN]["platform"] = mqtt.DOMAIN + @pytest.fixture(autouse=True) def cover_platform_only(): @@ -96,17 +101,18 @@ async def test_state_via_state_topic(hass, mqtt_mock_entry_with_yaml_config): """Test the controlling state via topic.""" assert await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "qos": 0, - "payload_open": "OPEN", - "payload_close": "CLOSE", - "payload_stop": "STOP", + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "qos": 0, + "payload_open": "OPEN", + "payload_close": "CLOSE", + "payload_stop": "STOP", + } } }, ) @@ -134,19 +140,20 @@ async def test_opening_and_closing_state_via_custom_state_payload( """Test the controlling opening and closing state via a custom payload.""" assert await async_setup_component( hass, - cover.DOMAIN, - { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "qos": 0, - "payload_open": "OPEN", - "payload_close": "CLOSE", - "payload_stop": "STOP", - "state_opening": "34", - "state_closing": "--43", + mqtt.DOMAIN, + { + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "qos": 0, + "payload_open": "OPEN", + "payload_close": "CLOSE", + "payload_stop": "STOP", + "state_opening": "34", + "state_closing": "--43", + } } }, ) @@ -179,18 +186,19 @@ async def test_open_closed_state_from_position_optimistic( """Test the state after setting the position using optimistic mode.""" assert await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "position_topic": "position-topic", - "set_position_topic": "set-position-topic", - "qos": 0, - "payload_open": "OPEN", - "payload_close": "CLOSE", - "payload_stop": "STOP", - "optimistic": True, + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "position_topic": "position-topic", + "set_position_topic": "set-position-topic", + "qos": 0, + "payload_open": "OPEN", + "payload_close": "CLOSE", + "payload_stop": "STOP", + "optimistic": True, + } } }, ) @@ -227,19 +235,20 @@ async def test_position_via_position_topic(hass, mqtt_mock_entry_with_yaml_confi """Test the controlling state via topic.""" assert await async_setup_component( hass, - cover.DOMAIN, - { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "position_topic": "get-position-topic", - "position_open": 100, - "position_closed": 0, - "command_topic": "command-topic", - "qos": 0, - "payload_open": "OPEN", - "payload_close": "CLOSE", - "payload_stop": "STOP", + mqtt.DOMAIN, + { + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "position_topic": "get-position-topic", + "position_open": 100, + "position_closed": 0, + "command_topic": "command-topic", + "qos": 0, + "payload_open": "OPEN", + "payload_close": "CLOSE", + "payload_stop": "STOP", + } } }, ) @@ -265,20 +274,21 @@ async def test_state_via_template(hass, mqtt_mock_entry_with_yaml_config): """Test the controlling state via topic.""" assert await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "qos": 0, - "value_template": "\ + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "qos": 0, + "value_template": "\ {% if (value | multiply(0.01) | int) == 0 %}\ closed\ {% else %}\ open\ {% endif %}", + } } }, ) @@ -303,20 +313,21 @@ async def test_state_via_template_and_entity_id(hass, mqtt_mock_entry_with_yaml_ """Test the controlling state via topic.""" assert await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "qos": 0, - "value_template": '\ + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "qos": 0, + "value_template": '\ {% if value == "open" or value == "closed" %}\ {{ value }}\ {% else %}\ {{ states(entity_id) }}\ {% endif %}', + } } }, ) @@ -345,15 +356,16 @@ async def test_state_via_template_with_json_value( """Test the controlling state via topic with JSON value.""" assert await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "qos": 0, - "value_template": "{{ value_json.Var1 }}", + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "qos": 0, + "value_template": "{{ value_json.Var1 }}", + } } }, ) @@ -387,20 +399,21 @@ async def test_position_via_template_and_entity_id( """Test the controlling state via topic.""" assert await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "position_topic": "get-position-topic", - "command_topic": "command-topic", - "qos": 0, - "position_template": '\ + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "position_topic": "get-position-topic", + "command_topic": "command-topic", + "qos": 0, + "position_template": '\ {% if state_attr(entity_id, "current_position") == None %}\ {{ value }}\ {% else %}\ {{ state_attr(entity_id, "current_position") + value | int }}\ {% endif %}', + } } }, ) @@ -442,8 +455,8 @@ async def test_optimistic_flag( """Test assumed_state is set correctly.""" assert await async_setup_component( hass, - cover.DOMAIN, - {cover.DOMAIN: {**config, "platform": "mqtt", "name": "test", "qos": 0}}, + mqtt.DOMAIN, + {mqtt.DOMAIN: {cover.DOMAIN: {**config, "name": "test", "qos": 0}}}, ) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -460,13 +473,14 @@ async def test_optimistic_state_change(hass, mqtt_mock_entry_with_yaml_config): """Test changing state optimistically.""" assert await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "command_topic": "command-topic", - "qos": 0, + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "command_topic": "command-topic", + "qos": 0, + } } }, ) @@ -519,15 +533,16 @@ async def test_optimistic_state_change_with_position( """Test changing state optimistically.""" assert await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "optimistic": True, - "command_topic": "command-topic", - "position_topic": "position-topic", - "qos": 0, + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "optimistic": True, + "command_topic": "command-topic", + "position_topic": "position-topic", + "qos": 0, + } } }, ) @@ -583,14 +598,15 @@ async def test_send_open_cover_command(hass, mqtt_mock_entry_with_yaml_config): """Test the sending of open_cover.""" assert await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "qos": 2, + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "qos": 2, + } } }, ) @@ -613,14 +629,15 @@ async def test_send_close_cover_command(hass, mqtt_mock_entry_with_yaml_config): """Test the sending of close_cover.""" assert await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "qos": 2, + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "qos": 2, + } } }, ) @@ -643,14 +660,15 @@ async def test_send_stop__cover_command(hass, mqtt_mock_entry_with_yaml_config): """Test the sending of stop_cover.""" assert await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "qos": 2, + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "qos": 2, + } } }, ) @@ -673,18 +691,19 @@ async def test_current_cover_position(hass, mqtt_mock_entry_with_yaml_config): """Test the current cover position.""" assert await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "position_topic": "get-position-topic", - "command_topic": "command-topic", - "position_open": 100, - "position_closed": 0, - "payload_open": "OPEN", - "payload_close": "CLOSE", - "payload_stop": "STOP", + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "position_topic": "get-position-topic", + "command_topic": "command-topic", + "position_open": 100, + "position_closed": 0, + "payload_open": "OPEN", + "payload_close": "CLOSE", + "payload_stop": "STOP", + } } }, ) @@ -725,18 +744,19 @@ async def test_current_cover_position_inverted(hass, mqtt_mock_entry_with_yaml_c """Test the current cover position.""" assert await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "position_topic": "get-position-topic", - "command_topic": "command-topic", - "position_open": 0, - "position_closed": 100, - "payload_open": "OPEN", - "payload_close": "CLOSE", - "payload_stop": "STOP", + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "position_topic": "get-position-topic", + "command_topic": "command-topic", + "position_open": 0, + "position_closed": 100, + "payload_open": "OPEN", + "payload_close": "CLOSE", + "payload_stop": "STOP", + } } }, ) @@ -784,44 +804,45 @@ async def test_current_cover_position_inverted(hass, mqtt_mock_entry_with_yaml_c assert hass.states.get("cover.test").state == STATE_CLOSED -async def test_optimistic_position(hass, mqtt_mock_entry_no_yaml_config): +async def test_optimistic_position(hass, caplog): """Test optimistic position is not supported.""" - assert await async_setup_component( + assert not await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "command_topic": "command-topic", - "set_position_topic": "set-position-topic", + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "command_topic": "command-topic", + "set_position_topic": "set-position-topic", + } } }, ) - await hass.async_block_till_done() - await mqtt_mock_entry_no_yaml_config() - - state = hass.states.get("cover.test") - assert state is None + assert ( + "Invalid config for [mqtt]: 'set_position_topic' must be set together with 'position_topic'" + in caplog.text + ) async def test_position_update(hass, mqtt_mock_entry_with_yaml_config): """Test cover position update from received MQTT message.""" assert await async_setup_component( hass, - cover.DOMAIN, - { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "position_topic": "get-position-topic", - "command_topic": "command-topic", - "set_position_topic": "set-position-topic", - "position_open": 100, - "position_closed": 0, - "payload_open": "OPEN", - "payload_close": "CLOSE", - "payload_stop": "STOP", + mqtt.DOMAIN, + { + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "position_topic": "get-position-topic", + "command_topic": "command-topic", + "set_position_topic": "set-position-topic", + "position_open": 100, + "position_closed": 0, + "payload_open": "OPEN", + "payload_close": "CLOSE", + "payload_stop": "STOP", + } } }, ) @@ -853,20 +874,21 @@ async def test_set_position_templated( """Test setting cover position via template.""" assert await async_setup_component( hass, - cover.DOMAIN, - { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "position_topic": "get-position-topic", - "command_topic": "command-topic", - "position_open": 100, - "position_closed": 0, - "set_position_topic": "set-position-topic", - "set_position_template": pos_template, - "payload_open": "OPEN", - "payload_close": "CLOSE", - "payload_stop": "STOP", + mqtt.DOMAIN, + { + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "position_topic": "get-position-topic", + "command_topic": "command-topic", + "position_open": 100, + "position_closed": 0, + "set_position_topic": "set-position-topic", + "set_position_template": pos_template, + "payload_open": "OPEN", + "payload_close": "CLOSE", + "payload_stop": "STOP", + } } }, ) @@ -891,17 +913,17 @@ async def test_set_position_templated_and_attributes( """Test setting cover position via template and using entities attributes.""" assert await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "position_topic": "get-position-topic", - "command_topic": "command-topic", - "position_open": 100, - "position_closed": 0, - "set_position_topic": "set-position-topic", - "set_position_template": '\ + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "position_topic": "get-position-topic", + "command_topic": "command-topic", + "position_open": 100, + "position_closed": 0, + "set_position_topic": "set-position-topic", + "set_position_template": '\ {% if position > 99 %}\ {% if state_attr(entity_id, "current_position") == None %}\ {{ 5 }}\ @@ -911,9 +933,10 @@ async def test_set_position_templated_and_attributes( {% else %}\ {{ 42 }}\ {% endif %}', - "payload_open": "OPEN", - "payload_close": "CLOSE", - "payload_stop": "STOP", + "payload_open": "OPEN", + "payload_close": "CLOSE", + "payload_stop": "STOP", + } } }, ) @@ -934,22 +957,23 @@ async def test_set_tilt_templated(hass, mqtt_mock_entry_with_yaml_config): """Test setting cover tilt position via template.""" assert await async_setup_component( hass, - cover.DOMAIN, - { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "position_topic": "get-position-topic", - "command_topic": "command-topic", - "tilt_command_topic": "tilt-command-topic", - "position_open": 100, - "position_closed": 0, - "set_position_topic": "set-position-topic", - "set_position_template": "{{position-1}}", - "tilt_command_template": "{{tilt_position+1}}", - "payload_open": "OPEN", - "payload_close": "CLOSE", - "payload_stop": "STOP", + mqtt.DOMAIN, + { + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "position_topic": "get-position-topic", + "command_topic": "command-topic", + "tilt_command_topic": "tilt-command-topic", + "position_open": 100, + "position_closed": 0, + "set_position_topic": "set-position-topic", + "set_position_template": "{{position-1}}", + "tilt_command_template": "{{tilt_position+1}}", + "payload_open": "OPEN", + "payload_close": "CLOSE", + "payload_stop": "STOP", + } } }, ) @@ -974,26 +998,27 @@ async def test_set_tilt_templated_and_attributes( """Test setting cover tilt position via template and using entities attributes.""" assert await async_setup_component( hass, - cover.DOMAIN, - { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "position_topic": "get-position-topic", - "command_topic": "command-topic", - "tilt_command_topic": "tilt-command-topic", - "position_open": 100, - "position_closed": 0, - "set_position_topic": "set-position-topic", - "set_position_template": "{{position-1}}", - "tilt_command_template": "{" - '"entity_id": "{{ entity_id }}",' - '"value": {{ value }},' - '"tilt_position": {{ tilt_position }}' - "}", - "payload_open": "OPEN", - "payload_close": "CLOSE", - "payload_stop": "STOP", + mqtt.DOMAIN, + { + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "position_topic": "get-position-topic", + "command_topic": "command-topic", + "tilt_command_topic": "tilt-command-topic", + "position_open": 100, + "position_closed": 0, + "set_position_topic": "set-position-topic", + "set_position_template": "{{position-1}}", + "tilt_command_template": "{" + '"entity_id": "{{ entity_id }}",' + '"value": {{ value }},' + '"tilt_position": {{ tilt_position }}' + "}", + "payload_open": "OPEN", + "payload_close": "CLOSE", + "payload_stop": "STOP", + } } }, ) @@ -1061,17 +1086,18 @@ async def test_set_position_untemplated(hass, mqtt_mock_entry_with_yaml_config): """Test setting cover position via template.""" assert await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "position_topic": "state-topic", - "command_topic": "command-topic", - "set_position_topic": "position-topic", - "payload_open": "OPEN", - "payload_close": "CLOSE", - "payload_stop": "STOP", + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "position_topic": "state-topic", + "command_topic": "command-topic", + "set_position_topic": "position-topic", + "payload_open": "OPEN", + "payload_close": "CLOSE", + "payload_stop": "STOP", + } } }, ) @@ -1094,19 +1120,20 @@ async def test_set_position_untemplated_custom_percentage_range( """Test setting cover position via template.""" assert await async_setup_component( hass, - cover.DOMAIN, - { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "position_topic": "state-topic", - "command_topic": "command-topic", - "set_position_topic": "position-topic", - "position_open": 0, - "position_closed": 100, - "payload_open": "OPEN", - "payload_close": "CLOSE", - "payload_stop": "STOP", + mqtt.DOMAIN, + { + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "position_topic": "state-topic", + "command_topic": "command-topic", + "set_position_topic": "position-topic", + "position_open": 0, + "position_closed": 100, + "payload_open": "OPEN", + "payload_close": "CLOSE", + "payload_stop": "STOP", + } } }, ) @@ -1127,17 +1154,18 @@ async def test_no_command_topic(hass, mqtt_mock_entry_with_yaml_config): """Test with no command topic.""" assert await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "qos": 0, - "payload_open": "OPEN", - "payload_close": "CLOSE", - "payload_stop": "STOP", - "tilt_command_topic": "tilt-command", - "tilt_status_topic": "tilt-status", + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "qos": 0, + "payload_open": "OPEN", + "payload_close": "CLOSE", + "payload_stop": "STOP", + "tilt_command_topic": "tilt-command", + "tilt_status_topic": "tilt-status", + } } }, ) @@ -1151,16 +1179,17 @@ async def test_no_payload_close(hass, mqtt_mock_entry_with_yaml_config): """Test with no close payload.""" assert await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "command_topic": "command-topic", - "qos": 0, - "payload_open": "OPEN", - "payload_close": None, - "payload_stop": "STOP", + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "command_topic": "command-topic", + "qos": 0, + "payload_open": "OPEN", + "payload_close": None, + "payload_stop": "STOP", + } } }, ) @@ -1174,16 +1203,17 @@ async def test_no_payload_open(hass, mqtt_mock_entry_with_yaml_config): """Test with no open payload.""" assert await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "command_topic": "command-topic", - "qos": 0, - "payload_open": None, - "payload_close": "CLOSE", - "payload_stop": "STOP", + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "command_topic": "command-topic", + "qos": 0, + "payload_open": None, + "payload_close": "CLOSE", + "payload_stop": "STOP", + } } }, ) @@ -1197,16 +1227,17 @@ async def test_no_payload_stop(hass, mqtt_mock_entry_with_yaml_config): """Test with no stop payload.""" assert await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "command_topic": "command-topic", - "qos": 0, - "payload_open": "OPEN", - "payload_close": "CLOSE", - "payload_stop": None, + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "command_topic": "command-topic", + "qos": 0, + "payload_open": "OPEN", + "payload_close": "CLOSE", + "payload_stop": None, + } } }, ) @@ -1220,18 +1251,19 @@ async def test_with_command_topic_and_tilt(hass, mqtt_mock_entry_with_yaml_confi """Test with command topic and tilt config.""" assert await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "command_topic": "test", - "platform": "mqtt", - "name": "test", - "qos": 0, - "payload_open": "OPEN", - "payload_close": "CLOSE", - "payload_stop": "STOP", - "tilt_command_topic": "tilt-command", - "tilt_status_topic": "tilt-status", + mqtt.DOMAIN: { + cover.DOMAIN: { + "command_topic": "test", + "name": "test", + "qos": 0, + "payload_open": "OPEN", + "payload_close": "CLOSE", + "payload_stop": "STOP", + "tilt_command_topic": "tilt-command", + "tilt_status_topic": "tilt-status", + } } }, ) @@ -1245,19 +1277,20 @@ async def test_tilt_defaults(hass, mqtt_mock_entry_with_yaml_config): """Test the defaults.""" assert await async_setup_component( hass, - cover.DOMAIN, - { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "qos": 0, - "payload_open": "OPEN", - "payload_close": "CLOSE", - "payload_stop": "STOP", - "tilt_command_topic": "tilt-command", - "tilt_status_topic": "tilt-status", + mqtt.DOMAIN, + { + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "qos": 0, + "payload_open": "OPEN", + "payload_close": "CLOSE", + "payload_stop": "STOP", + "tilt_command_topic": "tilt-command", + "tilt_status_topic": "tilt-status", + } } }, ) @@ -1273,19 +1306,20 @@ async def test_tilt_via_invocation_defaults(hass, mqtt_mock_entry_with_yaml_conf """Test tilt defaults on close/open.""" assert await async_setup_component( hass, - cover.DOMAIN, - { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "qos": 0, - "payload_open": "OPEN", - "payload_close": "CLOSE", - "payload_stop": "STOP", - "tilt_command_topic": "tilt-command-topic", - "tilt_status_topic": "tilt-status-topic", + mqtt.DOMAIN, + { + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "qos": 0, + "payload_open": "OPEN", + "payload_close": "CLOSE", + "payload_stop": "STOP", + "tilt_command_topic": "tilt-command-topic", + "tilt_status_topic": "tilt-status-topic", + } } }, ) @@ -1356,21 +1390,22 @@ async def test_tilt_given_value(hass, mqtt_mock_entry_with_yaml_config): """Test tilting to a given value.""" assert await async_setup_component( hass, - cover.DOMAIN, - { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "qos": 0, - "payload_open": "OPEN", - "payload_close": "CLOSE", - "payload_stop": "STOP", - "tilt_command_topic": "tilt-command-topic", - "tilt_status_topic": "tilt-status-topic", - "tilt_opened_value": 80, - "tilt_closed_value": 25, + mqtt.DOMAIN, + { + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "qos": 0, + "payload_open": "OPEN", + "payload_close": "CLOSE", + "payload_stop": "STOP", + "tilt_command_topic": "tilt-command-topic", + "tilt_status_topic": "tilt-status-topic", + "tilt_opened_value": 80, + "tilt_closed_value": 25, + } } }, ) @@ -1445,22 +1480,23 @@ async def test_tilt_given_value_optimistic(hass, mqtt_mock_entry_with_yaml_confi """Test tilting to a given value.""" assert await async_setup_component( hass, - cover.DOMAIN, - { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "qos": 0, - "payload_open": "OPEN", - "payload_close": "CLOSE", - "payload_stop": "STOP", - "tilt_command_topic": "tilt-command-topic", - "tilt_status_topic": "tilt-status-topic", - "tilt_opened_value": 80, - "tilt_closed_value": 25, - "tilt_optimistic": True, + mqtt.DOMAIN, + { + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "qos": 0, + "payload_open": "OPEN", + "payload_close": "CLOSE", + "payload_stop": "STOP", + "tilt_command_topic": "tilt-command-topic", + "tilt_status_topic": "tilt-status-topic", + "tilt_opened_value": 80, + "tilt_closed_value": 25, + "tilt_optimistic": True, + } } }, ) @@ -1522,24 +1558,25 @@ async def test_tilt_given_value_altered_range(hass, mqtt_mock_entry_with_yaml_co """Test tilting to a given value.""" assert await async_setup_component( hass, - cover.DOMAIN, - { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "qos": 0, - "payload_open": "OPEN", - "payload_close": "CLOSE", - "payload_stop": "STOP", - "tilt_command_topic": "tilt-command-topic", - "tilt_status_topic": "tilt-status-topic", - "tilt_opened_value": 25, - "tilt_closed_value": 0, - "tilt_min": 0, - "tilt_max": 50, - "tilt_optimistic": True, + mqtt.DOMAIN, + { + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "qos": 0, + "payload_open": "OPEN", + "payload_close": "CLOSE", + "payload_stop": "STOP", + "tilt_command_topic": "tilt-command-topic", + "tilt_status_topic": "tilt-status-topic", + "tilt_opened_value": 25, + "tilt_closed_value": 0, + "tilt_min": 0, + "tilt_max": 50, + "tilt_optimistic": True, + } } }, ) @@ -1599,19 +1636,20 @@ async def test_tilt_via_topic(hass, mqtt_mock_entry_with_yaml_config): """Test tilt by updating status via MQTT.""" assert await async_setup_component( hass, - cover.DOMAIN, - { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "qos": 0, - "payload_open": "OPEN", - "payload_close": "CLOSE", - "payload_stop": "STOP", - "tilt_command_topic": "tilt-command-topic", - "tilt_status_topic": "tilt-status-topic", + mqtt.DOMAIN, + { + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "qos": 0, + "payload_open": "OPEN", + "payload_close": "CLOSE", + "payload_stop": "STOP", + "tilt_command_topic": "tilt-command-topic", + "tilt_status_topic": "tilt-status-topic", + } } }, ) @@ -1637,22 +1675,23 @@ async def test_tilt_via_topic_template(hass, mqtt_mock_entry_with_yaml_config): """Test tilt by updating status via MQTT and template.""" assert await async_setup_component( hass, - cover.DOMAIN, - { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "qos": 0, - "payload_open": "OPEN", - "payload_close": "CLOSE", - "payload_stop": "STOP", - "tilt_command_topic": "tilt-command-topic", - "tilt_status_topic": "tilt-status-topic", - "tilt_status_template": "{{ (value | multiply(0.01)) | int }}", - "tilt_opened_value": 400, - "tilt_closed_value": 125, + mqtt.DOMAIN, + { + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "qos": 0, + "payload_open": "OPEN", + "payload_close": "CLOSE", + "payload_stop": "STOP", + "tilt_command_topic": "tilt-command-topic", + "tilt_status_topic": "tilt-status-topic", + "tilt_status_template": "{{ (value | multiply(0.01)) | int }}", + "tilt_opened_value": 400, + "tilt_closed_value": 125, + } } }, ) @@ -1680,22 +1719,23 @@ async def test_tilt_via_topic_template_json_value( """Test tilt by updating status via MQTT and template with JSON value.""" assert await async_setup_component( hass, - cover.DOMAIN, - { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "qos": 0, - "payload_open": "OPEN", - "payload_close": "CLOSE", - "payload_stop": "STOP", - "tilt_command_topic": "tilt-command-topic", - "tilt_status_topic": "tilt-status-topic", - "tilt_status_template": "{{ value_json.Var1 }}", - "tilt_opened_value": 400, - "tilt_closed_value": 125, + mqtt.DOMAIN, + { + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "qos": 0, + "payload_open": "OPEN", + "payload_close": "CLOSE", + "payload_stop": "STOP", + "tilt_command_topic": "tilt-command-topic", + "tilt_status_topic": "tilt-status-topic", + "tilt_status_template": "{{ value_json.Var1 }}", + "tilt_opened_value": 400, + "tilt_closed_value": 125, + } } }, ) @@ -1727,21 +1767,22 @@ async def test_tilt_via_topic_altered_range(hass, mqtt_mock_entry_with_yaml_conf """Test tilt status via MQTT with altered tilt range.""" assert await async_setup_component( hass, - cover.DOMAIN, - { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "qos": 0, - "payload_open": "OPEN", - "payload_close": "CLOSE", - "payload_stop": "STOP", - "tilt_command_topic": "tilt-command-topic", - "tilt_status_topic": "tilt-status-topic", - "tilt_min": 0, - "tilt_max": 50, + mqtt.DOMAIN, + { + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "qos": 0, + "payload_open": "OPEN", + "payload_close": "CLOSE", + "payload_stop": "STOP", + "tilt_command_topic": "tilt-command-topic", + "tilt_status_topic": "tilt-status-topic", + "tilt_min": 0, + "tilt_max": 50, + } } }, ) @@ -1776,21 +1817,22 @@ async def test_tilt_status_out_of_range_warning( """Test tilt status via MQTT tilt out of range warning message.""" assert await async_setup_component( hass, - cover.DOMAIN, - { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "qos": 0, - "payload_open": "OPEN", - "payload_close": "CLOSE", - "payload_stop": "STOP", - "tilt_command_topic": "tilt-command-topic", - "tilt_status_topic": "tilt-status-topic", - "tilt_min": 0, - "tilt_max": 50, + mqtt.DOMAIN, + { + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "qos": 0, + "payload_open": "OPEN", + "payload_close": "CLOSE", + "payload_stop": "STOP", + "tilt_command_topic": "tilt-command-topic", + "tilt_status_topic": "tilt-status-topic", + "tilt_min": 0, + "tilt_max": 50, + } } }, ) @@ -1810,21 +1852,22 @@ async def test_tilt_status_not_numeric_warning( """Test tilt status via MQTT tilt not numeric warning message.""" assert await async_setup_component( hass, - cover.DOMAIN, - { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "qos": 0, - "payload_open": "OPEN", - "payload_close": "CLOSE", - "payload_stop": "STOP", - "tilt_command_topic": "tilt-command-topic", - "tilt_status_topic": "tilt-status-topic", - "tilt_min": 0, - "tilt_max": 50, + mqtt.DOMAIN, + { + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "qos": 0, + "payload_open": "OPEN", + "payload_close": "CLOSE", + "payload_stop": "STOP", + "tilt_command_topic": "tilt-command-topic", + "tilt_status_topic": "tilt-status-topic", + "tilt_min": 0, + "tilt_max": 50, + } } }, ) @@ -1842,21 +1885,22 @@ async def test_tilt_via_topic_altered_range_inverted( """Test tilt status via MQTT with altered tilt range and inverted tilt position.""" assert await async_setup_component( hass, - cover.DOMAIN, - { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "qos": 0, - "payload_open": "OPEN", - "payload_close": "CLOSE", - "payload_stop": "STOP", - "tilt_command_topic": "tilt-command-topic", - "tilt_status_topic": "tilt-status-topic", - "tilt_min": 50, - "tilt_max": 0, + mqtt.DOMAIN, + { + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "qos": 0, + "payload_open": "OPEN", + "payload_close": "CLOSE", + "payload_stop": "STOP", + "tilt_command_topic": "tilt-command-topic", + "tilt_status_topic": "tilt-status-topic", + "tilt_min": 50, + "tilt_max": 0, + } } }, ) @@ -1891,24 +1935,25 @@ async def test_tilt_via_topic_template_altered_range( """Test tilt status via MQTT and template with altered tilt range.""" assert await async_setup_component( hass, - cover.DOMAIN, - { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "qos": 0, - "payload_open": "OPEN", - "payload_close": "CLOSE", - "payload_stop": "STOP", - "tilt_command_topic": "tilt-command-topic", - "tilt_status_topic": "tilt-status-topic", - "tilt_status_template": "{{ (value | multiply(0.01)) | int }}", - "tilt_opened_value": 400, - "tilt_closed_value": 125, - "tilt_min": 0, - "tilt_max": 50, + mqtt.DOMAIN, + { + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "qos": 0, + "payload_open": "OPEN", + "payload_close": "CLOSE", + "payload_stop": "STOP", + "tilt_command_topic": "tilt-command-topic", + "tilt_status_topic": "tilt-status-topic", + "tilt_status_template": "{{ (value | multiply(0.01)) | int }}", + "tilt_opened_value": 400, + "tilt_closed_value": 125, + "tilt_min": 0, + "tilt_max": 50, + } } }, ) @@ -1941,19 +1986,20 @@ async def test_tilt_position(hass, mqtt_mock_entry_with_yaml_config): """Test tilt via method invocation.""" assert await async_setup_component( hass, - cover.DOMAIN, - { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "qos": 0, - "payload_open": "OPEN", - "payload_close": "CLOSE", - "payload_stop": "STOP", - "tilt_command_topic": "tilt-command-topic", - "tilt_status_topic": "tilt-status-topic", + mqtt.DOMAIN, + { + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "qos": 0, + "payload_open": "OPEN", + "payload_close": "CLOSE", + "payload_stop": "STOP", + "tilt_command_topic": "tilt-command-topic", + "tilt_status_topic": "tilt-status-topic", + } } }, ) @@ -1976,20 +2022,21 @@ async def test_tilt_position_templated(hass, mqtt_mock_entry_with_yaml_config): """Test tilt position via template.""" assert await async_setup_component( hass, - cover.DOMAIN, - { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "qos": 0, - "payload_open": "OPEN", - "payload_close": "CLOSE", - "payload_stop": "STOP", - "tilt_command_topic": "tilt-command-topic", - "tilt_status_topic": "tilt-status-topic", - "tilt_command_template": "{{100-32}}", + mqtt.DOMAIN, + { + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "qos": 0, + "payload_open": "OPEN", + "payload_close": "CLOSE", + "payload_stop": "STOP", + "tilt_command_topic": "tilt-command-topic", + "tilt_status_topic": "tilt-status-topic", + "tilt_command_template": "{{100-32}}", + } } }, ) @@ -2012,23 +2059,24 @@ async def test_tilt_position_altered_range(hass, mqtt_mock_entry_with_yaml_confi """Test tilt via method invocation with altered range.""" assert await async_setup_component( hass, - cover.DOMAIN, - { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "qos": 0, - "payload_open": "OPEN", - "payload_close": "CLOSE", - "payload_stop": "STOP", - "tilt_command_topic": "tilt-command-topic", - "tilt_status_topic": "tilt-status-topic", - "tilt_opened_value": 400, - "tilt_closed_value": 125, - "tilt_min": 0, - "tilt_max": 50, + mqtt.DOMAIN, + { + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "qos": 0, + "payload_open": "OPEN", + "payload_close": "CLOSE", + "payload_stop": "STOP", + "tilt_command_topic": "tilt-command-topic", + "tilt_status_topic": "tilt-status-topic", + "tilt_opened_value": 400, + "tilt_closed_value": 125, + "tilt_min": 0, + "tilt_max": 50, + } } }, ) @@ -2396,28 +2444,28 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, cover.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, cover.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, cover.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, cover.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by default payload with defined topic.""" await help_test_default_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, cover.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, cover.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by custom payload with defined topic.""" await help_test_custom_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, cover.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, cover.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -2425,13 +2473,14 @@ async def test_valid_device_class(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of a valid device class.""" assert await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "device_class": "garage", - "state_topic": "test-topic", + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "device_class": "garage", + "state_topic": "test-topic", + } } }, ) @@ -2442,25 +2491,22 @@ async def test_valid_device_class(hass, mqtt_mock_entry_with_yaml_config): assert state.attributes.get("device_class") == "garage" -async def test_invalid_device_class(hass, mqtt_mock_entry_no_yaml_config): +async def test_invalid_device_class(hass, caplog): """Test the setting of an invalid device class.""" - assert await async_setup_component( + assert not await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "device_class": "abc123", - "state_topic": "test-topic", + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "device_class": "abc123", + "state_topic": "test-topic", + } } }, ) - await hass.async_block_till_done() - await mqtt_mock_entry_no_yaml_config() - - state = hass.states.get("cover.test") - assert state is None + assert "Invalid config for [mqtt]: expected CoverDeviceClass" in caplog.text async def test_setting_attribute_via_mqtt_json_message( @@ -2468,7 +2514,7 @@ async def test_setting_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_with_yaml_config, cover.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, cover.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -2480,7 +2526,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( hass, mqtt_mock_entry_no_yaml_config, cover.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, MQTT_COVER_ATTRIBUTES_BLOCKED, ) @@ -2488,7 +2534,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_with_template( - hass, mqtt_mock_entry_with_yaml_config, cover.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, cover.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -2497,7 +2543,11 @@ async def test_update_with_json_attrs_not_dict( ): """Test attributes get extracted from a JSON result.""" await help_test_update_with_json_attrs_not_dict( - hass, mqtt_mock_entry_with_yaml_config, caplog, cover.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_with_yaml_config, + caplog, + cover.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) @@ -2506,14 +2556,22 @@ async def test_update_with_json_attrs_bad_json( ): """Test attributes get extracted from a JSON result.""" await help_test_update_with_json_attrs_bad_JSON( - hass, mqtt_mock_entry_with_yaml_config, caplog, cover.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_with_yaml_config, + caplog, + cover.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test update of discovered MQTTAttributes.""" await help_test_discovery_update_attr( - hass, mqtt_mock_entry_no_yaml_config, caplog, cover.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_no_yaml_config, + caplog, + cover.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) @@ -2588,42 +2646,42 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT cover device registry integration.""" await help_test_entity_device_info_with_connection( - hass, mqtt_mock_entry_no_yaml_config, cover.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, cover.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT cover device registry integration.""" await help_test_entity_device_info_with_identifier( - hass, mqtt_mock_entry_no_yaml_config, cover.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, cover.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): """Test device registry update.""" await help_test_entity_device_info_update( - hass, mqtt_mock_entry_no_yaml_config, cover.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, cover.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test device registry remove.""" await help_test_entity_device_info_remove( - hass, mqtt_mock_entry_no_yaml_config, cover.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, cover.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_config): """Test MQTT subscriptions are managed when entity_id is updated.""" await help_test_entity_id_update_subscriptions( - hass, mqtt_mock_entry_with_yaml_config, cover.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, cover.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, cover.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, cover.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -2633,7 +2691,7 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): hass, mqtt_mock_entry_no_yaml_config, cover.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, SERVICE_OPEN_COVER, command_payload="OPEN", ) @@ -2645,19 +2703,20 @@ async def test_state_and_position_topics_state_not_set_via_position_topic( """Test state is not set via position topic when both state and position topics are set.""" assert await async_setup_component( hass, - cover.DOMAIN, - { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "position_topic": "get-position-topic", - "position_open": 100, - "position_closed": 0, - "state_open": "OPEN", - "state_closed": "CLOSE", - "command_topic": "command-topic", - "qos": 0, + mqtt.DOMAIN, + { + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "position_topic": "get-position-topic", + "position_open": 100, + "position_closed": 0, + "state_open": "OPEN", + "state_closed": "CLOSE", + "command_topic": "command-topic", + "qos": 0, + } } }, ) @@ -2705,20 +2764,21 @@ async def test_set_state_via_position_using_stopped_state( """Test the controlling state via position topic using stopped state.""" assert await async_setup_component( hass, - cover.DOMAIN, - { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "position_topic": "get-position-topic", - "position_open": 100, - "position_closed": 0, - "state_open": "OPEN", - "state_closed": "CLOSE", - "state_stopped": "STOPPED", - "command_topic": "command-topic", - "qos": 0, + mqtt.DOMAIN, + { + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "position_topic": "get-position-topic", + "position_open": 100, + "position_closed": 0, + "state_open": "OPEN", + "state_closed": "CLOSE", + "state_stopped": "STOPPED", + "command_topic": "command-topic", + "qos": 0, + } } }, ) @@ -2761,16 +2821,17 @@ async def test_position_via_position_topic_template( """Test position by updating status via position template.""" assert await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "set_position_topic": "set-position-topic", - "position_topic": "get-position-topic", - "position_template": "{{ (value | multiply(0.01)) | int }}", + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "set_position_topic": "set-position-topic", + "position_topic": "get-position-topic", + "position_template": "{{ (value | multiply(0.01)) | int }}", + } } }, ) @@ -2798,16 +2859,17 @@ async def test_position_via_position_topic_template_json_value( """Test position by updating status via position template with a JSON value.""" assert await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "set_position_topic": "set-position-topic", - "position_topic": "get-position-topic", - "position_template": "{{ value_json.Var1 }}", + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "set_position_topic": "set-position-topic", + "position_topic": "get-position-topic", + "position_template": "{{ value_json.Var1 }}", + } } }, ) @@ -2839,21 +2901,22 @@ async def test_position_template_with_entity_id(hass, mqtt_mock_entry_with_yaml_ """Test position by updating status via position template.""" assert await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "set_position_topic": "set-position-topic", - "position_topic": "get-position-topic", - "position_template": '\ + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "set_position_topic": "set-position-topic", + "position_topic": "get-position-topic", + "position_template": '\ {% if state_attr(entity_id, "current_position") != None %}\ {{ value | int + state_attr(entity_id, "current_position") }} \ {% else %} \ {{ value }} \ {% endif %}', + } } }, ) @@ -2881,16 +2944,17 @@ async def test_position_via_position_topic_template_return_json( """Test position by updating status via position template and returning json.""" assert await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "set_position_topic": "set-position-topic", - "position_topic": "get-position-topic", - "position_template": '{{ {"position" : value} | tojson }}', + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "set_position_topic": "set-position-topic", + "position_topic": "get-position-topic", + "position_template": '{{ {"position" : value} | tojson }}', + } } }, ) @@ -2911,16 +2975,17 @@ async def test_position_via_position_topic_template_return_json_warning( """Test position by updating status via position template returning json without position attribute.""" assert await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "set_position_topic": "set-position-topic", - "position_topic": "get-position-topic", - "position_template": '{{ {"pos" : value} | tojson }}', + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "set_position_topic": "set-position-topic", + "position_topic": "get-position-topic", + "position_template": '{{ {"pos" : value} | tojson }}', + } } }, ) @@ -2941,17 +3006,18 @@ async def test_position_and_tilt_via_position_topic_template_return_json( """Test position and tilt by updating the position via position template.""" assert await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "set_position_topic": "set-position-topic", - "position_topic": "get-position-topic", - "position_template": '\ + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "set_position_topic": "set-position-topic", + "position_topic": "get-position-topic", + "position_template": '\ {{ {"position" : value, "tilt_position" : (value | int / 2)| int } | tojson }}', + } } }, ) @@ -2984,27 +3050,28 @@ async def test_position_via_position_topic_template_all_variables( """Test position by updating status via position template.""" assert await async_setup_component( hass, - cover.DOMAIN, - { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "set_position_topic": "set-position-topic", - "position_topic": "get-position-topic", - "tilt_command_topic": "tilt-command-topic", - "position_open": 99, - "position_closed": 1, - "tilt_min": 11, - "tilt_max": 22, - "position_template": "\ + mqtt.DOMAIN, + { + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "set_position_topic": "set-position-topic", + "position_topic": "get-position-topic", + "tilt_command_topic": "tilt-command-topic", + "position_open": 99, + "position_closed": 1, + "tilt_min": 11, + "tilt_max": 22, + "position_template": "\ {% if value | int < tilt_max %}\ {{ tilt_min }}\ {% endif %}\ {% if value | int > position_closed %}\ {{ position_open }}\ {% endif %}", + } } }, ) @@ -3031,20 +3098,21 @@ async def test_set_state_via_stopped_state_no_position_topic( """Test the controlling state via stopped state when no position topic.""" assert await async_setup_component( hass, - cover.DOMAIN, - { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "state_open": "OPEN", - "state_closed": "CLOSE", - "state_stopped": "STOPPED", - "state_opening": "OPENING", - "state_closing": "CLOSING", - "command_topic": "command-topic", - "qos": 0, - "optimistic": False, + mqtt.DOMAIN, + { + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "state_open": "OPEN", + "state_closed": "CLOSE", + "state_stopped": "STOPPED", + "state_opening": "OPENING", + "state_closing": "CLOSING", + "command_topic": "command-topic", + "qos": 0, + "optimistic": False, + } } }, ) @@ -3083,16 +3151,17 @@ async def test_position_via_position_topic_template_return_invalid_json( """Test position by updating status via position template and returning invalid json.""" assert await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "set_position_topic": "set-position-topic", - "position_topic": "get-position-topic", - "position_template": '{{ {"position" : invalid_json} }}', + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "set_position_topic": "set-position-topic", + "position_topic": "get-position-topic", + "position_template": '{{ {"position" : invalid_json} }}', + } } }, ) @@ -3104,74 +3173,65 @@ async def test_position_via_position_topic_template_return_invalid_json( assert ("Payload '{'position': Undefined}' is not numeric") in caplog.text -async def test_set_position_topic_without_get_position_topic_error( - hass, caplog, mqtt_mock_entry_no_yaml_config -): +async def test_set_position_topic_without_get_position_topic_error(hass, caplog): """Test error when set_position_topic is used without position_topic.""" - assert await async_setup_component( + assert not await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "command_topic": "command-topic", - "set_position_topic": "set-position-topic", - "value_template": "{{100-62}}", + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "command_topic": "command-topic", + "set_position_topic": "set-position-topic", + "value_template": "{{100-62}}", + } } }, ) - await hass.async_block_till_done() - await mqtt_mock_entry_no_yaml_config() - assert ( f"'{CONF_SET_POSITION_TOPIC}' must be set together with '{CONF_GET_POSITION_TOPIC}'." ) in caplog.text async def test_value_template_without_state_topic_error( - hass, caplog, mqtt_mock_entry_no_yaml_config + hass, + caplog, ): """Test error when value_template is used and state_topic is missing.""" - assert await async_setup_component( + assert not await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "command_topic": "command-topic", - "value_template": "{{100-62}}", + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "command_topic": "command-topic", + "value_template": "{{100-62}}", + } } }, ) - await hass.async_block_till_done() - await mqtt_mock_entry_no_yaml_config() - assert ( f"'{CONF_VALUE_TEMPLATE}' must be set together with '{CONF_STATE_TOPIC}'." ) in caplog.text -async def test_position_template_without_position_topic_error( - hass, caplog, mqtt_mock_entry_no_yaml_config -): +async def test_position_template_without_position_topic_error(hass, caplog): """Test error when position_template is used and position_topic is missing.""" - assert await async_setup_component( + assert not await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "command_topic": "command-topic", - "position_template": "{{100-52}}", + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "command_topic": "command-topic", + "position_template": "{{100-52}}", + } } }, ) - await hass.async_block_till_done() - await mqtt_mock_entry_no_yaml_config() - assert ( f"'{CONF_GET_POSITION_TEMPLATE}' must be set together with '{CONF_GET_POSITION_TOPIC}'." in caplog.text @@ -3179,74 +3239,65 @@ async def test_position_template_without_position_topic_error( async def test_set_position_template_without_set_position_topic( - hass, caplog, mqtt_mock_entry_no_yaml_config + hass, + caplog, ): """Test error when set_position_template is used and set_position_topic is missing.""" - assert await async_setup_component( + assert not await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "command_topic": "command-topic", - "set_position_template": "{{100-42}}", + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "command_topic": "command-topic", + "set_position_template": "{{100-42}}", + } } }, ) - await hass.async_block_till_done() - await mqtt_mock_entry_no_yaml_config() - assert ( f"'{CONF_SET_POSITION_TEMPLATE}' must be set together with '{CONF_SET_POSITION_TOPIC}'." in caplog.text ) -async def test_tilt_command_template_without_tilt_command_topic( - hass, caplog, mqtt_mock_entry_no_yaml_config -): +async def test_tilt_command_template_without_tilt_command_topic(hass, caplog): """Test error when tilt_command_template is used and tilt_command_topic is missing.""" - assert await async_setup_component( + assert not await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "command_topic": "command-topic", - "tilt_command_template": "{{100-32}}", + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "command_topic": "command-topic", + "tilt_command_template": "{{100-32}}", + } } }, ) - await hass.async_block_till_done() - await mqtt_mock_entry_no_yaml_config() - assert ( f"'{CONF_TILT_COMMAND_TEMPLATE}' must be set together with '{CONF_TILT_COMMAND_TOPIC}'." in caplog.text ) -async def test_tilt_status_template_without_tilt_status_topic_topic( - hass, caplog, mqtt_mock_entry_no_yaml_config -): +async def test_tilt_status_template_without_tilt_status_topic_topic(hass, caplog): """Test error when tilt_status_template is used and tilt_status_topic is missing.""" - assert await async_setup_component( + assert not await async_setup_component( hass, - cover.DOMAIN, + mqtt.DOMAIN, { - cover.DOMAIN: { - "platform": "mqtt", - "name": "test", - "command_topic": "command-topic", - "tilt_status_template": "{{100-22}}", + mqtt.DOMAIN: { + cover.DOMAIN: { + "name": "test", + "command_topic": "command-topic", + "tilt_status_template": "{{100-22}}", + } } }, ) - await hass.async_block_till_done() - await mqtt_mock_entry_no_yaml_config() - assert ( f"'{CONF_TILT_STATUS_TEMPLATE}' must be set together with '{CONF_TILT_STATUS_TOPIC}'." in caplog.text @@ -3291,7 +3342,7 @@ async def test_publishing_with_custom_encoding( ): """Test publishing MQTT payload with different encoding.""" domain = cover.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] config["position_topic"] = "some-position-topic" await help_test_publishing_with_custom_encoding( @@ -3311,7 +3362,7 @@ async def test_publishing_with_custom_encoding( async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = cover.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) @@ -3320,7 +3371,7 @@ async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_pa async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = cover.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable_late(hass, caplog, tmp_path, domain, config) @@ -3348,7 +3399,7 @@ async def test_encoding_subscribable_topics( mqtt_mock_entry_with_yaml_config, caplog, cover.DOMAIN, - DEFAULT_CONFIG[cover.DOMAIN], + DEFAULT_CONFIG_LEGACY[cover.DOMAIN], topic, value, attribute, @@ -3360,7 +3411,7 @@ async def test_encoding_subscribable_topics( async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = cover.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG[platform]) + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) config["name"] = "test" del config["platform"] await help_test_setup_manual_entity_from_yaml(hass, platform, config) @@ -3370,7 +3421,20 @@ async def test_setup_manual_entity_from_yaml(hass): async def test_unload_entry(hass, mqtt_mock_entry_with_yaml_config, tmp_path): """Test unloading the config entry.""" domain = cover.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry_with_yaml_config, tmp_path, domain, config ) + + +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +async def test_setup_with_legacy_schema(hass, mqtt_mock_entry_with_yaml_config): + """Test a setup with deprecated yaml platform schema.""" + domain = cover.DOMAIN + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[domain]) + config["name"] = "test" + assert await async_setup_component(hass, domain, {domain: config}) + await hass.async_block_till_done() + await mqtt_mock_entry_with_yaml_config() + assert hass.states.get(f"{domain}.test") is not None diff --git a/tests/components/mqtt/test_device_tracker.py b/tests/components/mqtt/test_device_tracker.py index 6708703ddbb0c..db6e0a292d779 100644 --- a/tests/components/mqtt/test_device_tracker.py +++ b/tests/components/mqtt/test_device_tracker.py @@ -1,10 +1,11 @@ -"""The tests for the MQTT device tracker platform using configuration.yaml.""" +"""The tests for the MQTT device tracker platform using configuration.yaml with legacy schema.""" import json from unittest.mock import patch import pytest -from homeassistant.components.device_tracker.const import DOMAIN, SOURCE_TYPE_BLUETOOTH +from homeassistant.components import device_tracker +from homeassistant.components.device_tracker import SourceType from homeassistant.config_entries import ConfigEntryDisabler from homeassistant.const import CONF_PLATFORM, STATE_HOME, STATE_NOT_HOME, Platform from homeassistant.setup import async_setup_component @@ -12,7 +13,6 @@ from .test_common import ( MockConfigEntry, help_test_entry_reload_with_new_config, - help_test_setup_manual_entity_from_yaml, help_test_unload_config_entry, ) @@ -45,7 +45,14 @@ async def mock_setup_scanner(hass, config, see, discovery_info=None): dev_id = "paulus" topic = "/location/paulus" assert await async_setup_component( - hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "mqtt", "devices": {dev_id: topic}}} + hass, + device_tracker.DOMAIN, + { + device_tracker.DOMAIN: { + CONF_PLATFORM: "mqtt", + "devices": {dev_id: topic}, + } + }, ) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -59,13 +66,15 @@ async def test_legacy_new_message( """Test new message.""" await mqtt_mock_entry_no_yaml_config() dev_id = "paulus" - entity_id = f"{DOMAIN}.{dev_id}" + entity_id = f"{device_tracker.DOMAIN}.{dev_id}" topic = "/location/paulus" location = "work" hass.config.components = {"mqtt", "zone"} assert await async_setup_component( - hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "mqtt", "devices": {dev_id: topic}}} + hass, + device_tracker.DOMAIN, + {device_tracker.DOMAIN: {CONF_PLATFORM: "mqtt", "devices": {dev_id: topic}}}, ) async_fire_mqtt_message(hass, topic, location) await hass.async_block_till_done() @@ -79,7 +88,7 @@ async def test_legacy_single_level_wildcard_topic( """Test single level wildcard topic.""" await mqtt_mock_entry_no_yaml_config() dev_id = "paulus" - entity_id = f"{DOMAIN}.{dev_id}" + entity_id = f"{device_tracker.DOMAIN}.{dev_id}" subscription = "/location/+/paulus" topic = "/location/room/paulus" location = "work" @@ -87,8 +96,13 @@ async def test_legacy_single_level_wildcard_topic( hass.config.components = {"mqtt", "zone"} assert await async_setup_component( hass, - DOMAIN, - {DOMAIN: {CONF_PLATFORM: "mqtt", "devices": {dev_id: subscription}}}, + device_tracker.DOMAIN, + { + device_tracker.DOMAIN: { + CONF_PLATFORM: "mqtt", + "devices": {dev_id: subscription}, + } + }, ) async_fire_mqtt_message(hass, topic, location) await hass.async_block_till_done() @@ -102,7 +116,7 @@ async def test_legacy_multi_level_wildcard_topic( """Test multi level wildcard topic.""" await mqtt_mock_entry_no_yaml_config() dev_id = "paulus" - entity_id = f"{DOMAIN}.{dev_id}" + entity_id = f"{device_tracker.DOMAIN}.{dev_id}" subscription = "/location/#" topic = "/location/room/paulus" location = "work" @@ -110,8 +124,13 @@ async def test_legacy_multi_level_wildcard_topic( hass.config.components = {"mqtt", "zone"} assert await async_setup_component( hass, - DOMAIN, - {DOMAIN: {CONF_PLATFORM: "mqtt", "devices": {dev_id: subscription}}}, + device_tracker.DOMAIN, + { + device_tracker.DOMAIN: { + CONF_PLATFORM: "mqtt", + "devices": {dev_id: subscription}, + } + }, ) async_fire_mqtt_message(hass, topic, location) await hass.async_block_till_done() @@ -125,7 +144,7 @@ async def test_legacy_single_level_wildcard_topic_not_matching( """Test not matching single level wildcard topic.""" await mqtt_mock_entry_no_yaml_config() dev_id = "paulus" - entity_id = f"{DOMAIN}.{dev_id}" + entity_id = f"{device_tracker.DOMAIN}.{dev_id}" subscription = "/location/+/paulus" topic = "/location/paulus" location = "work" @@ -133,8 +152,13 @@ async def test_legacy_single_level_wildcard_topic_not_matching( hass.config.components = {"mqtt", "zone"} assert await async_setup_component( hass, - DOMAIN, - {DOMAIN: {CONF_PLATFORM: "mqtt", "devices": {dev_id: subscription}}}, + device_tracker.DOMAIN, + { + device_tracker.DOMAIN: { + CONF_PLATFORM: "mqtt", + "devices": {dev_id: subscription}, + } + }, ) async_fire_mqtt_message(hass, topic, location) await hass.async_block_till_done() @@ -148,7 +172,7 @@ async def test_legacy_multi_level_wildcard_topic_not_matching( """Test not matching multi level wildcard topic.""" await mqtt_mock_entry_no_yaml_config() dev_id = "paulus" - entity_id = f"{DOMAIN}.{dev_id}" + entity_id = f"{device_tracker.DOMAIN}.{dev_id}" subscription = "/location/#" topic = "/somewhere/room/paulus" location = "work" @@ -156,8 +180,13 @@ async def test_legacy_multi_level_wildcard_topic_not_matching( hass.config.components = {"mqtt", "zone"} assert await async_setup_component( hass, - DOMAIN, - {DOMAIN: {CONF_PLATFORM: "mqtt", "devices": {dev_id: subscription}}}, + device_tracker.DOMAIN, + { + device_tracker.DOMAIN: { + CONF_PLATFORM: "mqtt", + "devices": {dev_id: subscription}, + } + }, ) async_fire_mqtt_message(hass, topic, location) await hass.async_block_till_done() @@ -171,7 +200,7 @@ async def test_legacy_matching_custom_payload_for_home_and_not_home( """Test custom payload_home sets state to home and custom payload_not_home sets state to not_home.""" await mqtt_mock_entry_no_yaml_config() dev_id = "paulus" - entity_id = f"{DOMAIN}.{dev_id}" + entity_id = f"{device_tracker.DOMAIN}.{dev_id}" topic = "/location/paulus" payload_home = "present" payload_not_home = "not present" @@ -179,9 +208,9 @@ async def test_legacy_matching_custom_payload_for_home_and_not_home( hass.config.components = {"mqtt", "zone"} assert await async_setup_component( hass, - DOMAIN, + device_tracker.DOMAIN, { - DOMAIN: { + device_tracker.DOMAIN: { CONF_PLATFORM: "mqtt", "devices": {dev_id: topic}, "payload_home": payload_home, @@ -205,7 +234,7 @@ async def test_legacy_not_matching_custom_payload_for_home_and_not_home( """Test not matching payload does not set state to home or not_home.""" await mqtt_mock_entry_no_yaml_config() dev_id = "paulus" - entity_id = f"{DOMAIN}.{dev_id}" + entity_id = f"{device_tracker.DOMAIN}.{dev_id}" topic = "/location/paulus" payload_home = "present" payload_not_home = "not present" @@ -214,9 +243,9 @@ async def test_legacy_not_matching_custom_payload_for_home_and_not_home( hass.config.components = {"mqtt", "zone"} assert await async_setup_component( hass, - DOMAIN, + device_tracker.DOMAIN, { - DOMAIN: { + device_tracker.DOMAIN: { CONF_PLATFORM: "mqtt", "devices": {dev_id: topic}, "payload_home": payload_home, @@ -237,17 +266,17 @@ async def test_legacy_matching_source_type( """Test setting source type.""" await mqtt_mock_entry_no_yaml_config() dev_id = "paulus" - entity_id = f"{DOMAIN}.{dev_id}" + entity_id = f"{device_tracker.DOMAIN}.{dev_id}" topic = "/location/paulus" - source_type = SOURCE_TYPE_BLUETOOTH + source_type = SourceType.BLUETOOTH location = "work" hass.config.components = {"mqtt", "zone"} assert await async_setup_component( hass, - DOMAIN, + device_tracker.DOMAIN, { - DOMAIN: { + device_tracker.DOMAIN: { CONF_PLATFORM: "mqtt", "devices": {dev_id: topic}, "source_type": source_type, @@ -257,23 +286,10 @@ async def test_legacy_matching_source_type( async_fire_mqtt_message(hass, topic, location) await hass.async_block_till_done() - assert hass.states.get(entity_id).attributes["source_type"] == SOURCE_TYPE_BLUETOOTH - - -async def test_setup_with_modern_schema(hass, mock_device_tracker_conf): - """Test setup using the modern schema.""" - dev_id = "jan" - entity_id = f"{DOMAIN}.{dev_id}" - topic = "/location/jan" - - hass.config.components = {"zone"} - config = {"name": dev_id, "state_topic": topic} - - await help_test_setup_manual_entity_from_yaml(hass, DOMAIN, config) - - assert hass.states.get(entity_id) is not None + assert hass.states.get(entity_id).attributes["source_type"] == SourceType.BLUETOOTH +# Deprecated in HA Core 2022.6 async def test_unload_entry( hass, mock_device_tracker_conf, mqtt_mock_entry_no_yaml_config, tmp_path ): @@ -281,13 +297,15 @@ async def test_unload_entry( # setup through configuration.yaml await mqtt_mock_entry_no_yaml_config() dev_id = "jan" - entity_id = f"{DOMAIN}.{dev_id}" + entity_id = f"{device_tracker.DOMAIN}.{dev_id}" topic = "/location/jan" location = "home" hass.config.components = {"mqtt", "zone"} assert await async_setup_component( - hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "mqtt", "devices": {dev_id: topic}}} + hass, + device_tracker.DOMAIN, + {device_tracker.DOMAIN: {CONF_PLATFORM: "mqtt", "devices": {dev_id: topic}}}, ) async_fire_mqtt_message(hass, topic, location) await hass.async_block_till_done() @@ -296,7 +314,7 @@ async def test_unload_entry( # setup through discovery dev_id = "piet" subscription = "/location/#" - domain = DOMAIN + domain = device_tracker.DOMAIN discovery_config = { "devices": {dev_id: subscription}, "state_topic": "some-state", @@ -330,21 +348,22 @@ async def test_unload_entry( assert discovery_setup_entity is None +# Deprecated in HA Core 2022.6 async def test_reload_entry_legacy( hass, mock_device_tracker_conf, mqtt_mock_entry_no_yaml_config, tmp_path ): """Test reloading the config entry with manual MQTT items.""" # setup through configuration.yaml await mqtt_mock_entry_no_yaml_config() - entity_id = f"{DOMAIN}.jan" + entity_id = f"{device_tracker.DOMAIN}.jan" topic = "location/jan" location = "home" config = { - DOMAIN: {CONF_PLATFORM: "mqtt", "devices": {"jan": topic}}, + device_tracker.DOMAIN: {CONF_PLATFORM: "mqtt", "devices": {"jan": topic}}, } hass.config.components = {"mqtt", "zone"} - assert await async_setup_component(hass, DOMAIN, config) + assert await async_setup_component(hass, device_tracker.DOMAIN, config) await hass.async_block_till_done() async_fire_mqtt_message(hass, topic, location) @@ -360,6 +379,7 @@ async def test_reload_entry_legacy( assert hass.states.get(entity_id).state == location +# Deprecated in HA Core 2022.6 async def test_setup_with_disabled_entry( hass, mock_device_tracker_conf, caplog ) -> None: @@ -372,11 +392,11 @@ async def test_setup_with_disabled_entry( topic = "location/jan" config = { - DOMAIN: {CONF_PLATFORM: "mqtt", "devices": {"jan": topic}}, + device_tracker.DOMAIN: {CONF_PLATFORM: "mqtt", "devices": {"jan": topic}}, } hass.config.components = {"mqtt", "zone"} - await async_setup_component(hass, DOMAIN, config) + await async_setup_component(hass, device_tracker.DOMAIN, config) await hass.async_block_till_done() assert ( diff --git a/tests/components/mqtt/test_device_tracker_discovery.py b/tests/components/mqtt/test_device_tracker_discovery.py index ac4058c9372ea..923ae7c9f757c 100644 --- a/tests/components/mqtt/test_device_tracker_discovery.py +++ b/tests/components/mqtt/test_device_tracker_discovery.py @@ -1,27 +1,37 @@ -"""The tests for the MQTT device_tracker discovery platform.""" +"""The tests for the MQTT device_tracker platform.""" +import copy from unittest.mock import patch import pytest -from homeassistant.components import device_tracker +from homeassistant.components import device_tracker, mqtt from homeassistant.components.mqtt.const import DOMAIN as MQTT_DOMAIN from homeassistant.components.mqtt.discovery import ALREADY_DISCOVERED from homeassistant.const import STATE_HOME, STATE_NOT_HOME, STATE_UNKNOWN, Platform from homeassistant.setup import async_setup_component -from .test_common import help_test_setting_blocked_attribute_via_mqtt_json_message +from .test_common import ( + help_test_setting_blocked_attribute_via_mqtt_json_message, + help_test_setup_manual_entity_from_yaml, +) from tests.common import async_fire_mqtt_message, mock_device_registry, mock_registry DEFAULT_CONFIG = { - device_tracker.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "test-topic", + mqtt.DOMAIN: { + device_tracker.DOMAIN: { + "name": "test", + "state_topic": "test-topic", + } } } +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +DEFAULT_CONFIG_LEGACY = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) +DEFAULT_CONFIG_LEGACY[device_tracker.DOMAIN]["platform"] = mqtt.DOMAIN + @pytest.fixture(autouse=True) def device_tracker_platform_only(): @@ -430,6 +440,19 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( hass, mqtt_mock_entry_no_yaml_config, device_tracker.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, None, ) + + +async def test_setup_with_modern_schema(hass, mock_device_tracker_conf): + """Test setup using the modern schema.""" + dev_id = "jan" + entity_id = f"{device_tracker.DOMAIN}.{dev_id}" + topic = "/location/jan" + + config = {"name": dev_id, "state_topic": topic} + + await help_test_setup_manual_entity_from_yaml(hass, device_tracker.DOMAIN, config) + + assert hass.states.get(entity_id) is not None diff --git a/tests/components/mqtt/test_fan.py b/tests/components/mqtt/test_fan.py index 37dcefc9d3f46..efe38234aeee0 100644 --- a/tests/components/mqtt/test_fan.py +++ b/tests/components/mqtt/test_fan.py @@ -5,7 +5,7 @@ import pytest from voluptuous.error import MultipleInvalid -from homeassistant.components import fan +from homeassistant.components import fan, mqtt from homeassistant.components.fan import ( ATTR_OSCILLATING, ATTR_PERCENTAGE, @@ -67,14 +67,20 @@ from tests.components.fan import common DEFAULT_CONFIG = { - fan.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", + mqtt.DOMAIN: { + fan.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + } } } +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +DEFAULT_CONFIG_LEGACY = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) +DEFAULT_CONFIG_LEGACY[fan.DOMAIN]["platform"] = mqtt.DOMAIN + @pytest.fixture(autouse=True) def fan_platform_only(): @@ -83,18 +89,15 @@ def fan_platform_only(): yield -async def test_fail_setup_if_no_command_topic( - hass, caplog, mqtt_mock_entry_no_yaml_config -): +async def test_fail_setup_if_no_command_topic(hass, caplog): """Test if command fails with command topic.""" - assert await async_setup_component( - hass, fan.DOMAIN, {fan.DOMAIN: {"platform": "mqtt", "name": "test"}} + assert not await async_setup_component( + hass, + mqtt.DOMAIN, + {mqtt.DOMAIN: {fan.DOMAIN: {"name": "test"}}}, ) - await hass.async_block_till_done() - await mqtt_mock_entry_no_yaml_config() - assert hass.states.get("fan.test") is None assert ( - "Invalid config for [fan.mqtt]: required key not provided @ data['command_topic']" + "Invalid config for [mqtt]: required key not provided @ data['mqtt']['fan'][0]['command_topic']" in caplog.text ) @@ -105,35 +108,36 @@ async def test_controlling_state_via_topic( """Test the controlling state via topic.""" assert await async_setup_component( hass, - fan.DOMAIN, + mqtt.DOMAIN, { - fan.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "payload_off": "StAtE_OfF", - "payload_on": "StAtE_On", - "oscillation_state_topic": "oscillation-state-topic", - "oscillation_command_topic": "oscillation-command-topic", - "payload_oscillation_off": "OsC_OfF", - "payload_oscillation_on": "OsC_On", - "percentage_state_topic": "percentage-state-topic", - "percentage_command_topic": "percentage-command-topic", - "preset_mode_state_topic": "preset-mode-state-topic", - "preset_mode_command_topic": "preset-mode-command-topic", - "preset_modes": [ - "auto", - "smart", - "whoosh", - "eco", - "breeze", - "silent", - ], - "speed_range_min": 1, - "speed_range_max": 200, - "payload_reset_percentage": "rEset_percentage", - "payload_reset_preset_mode": "rEset_preset_mode", + mqtt.DOMAIN: { + fan.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "payload_off": "StAtE_OfF", + "payload_on": "StAtE_On", + "oscillation_state_topic": "oscillation-state-topic", + "oscillation_command_topic": "oscillation-command-topic", + "payload_oscillation_off": "OsC_OfF", + "payload_oscillation_on": "OsC_On", + "percentage_state_topic": "percentage-state-topic", + "percentage_command_topic": "percentage-command-topic", + "preset_mode_state_topic": "preset-mode-state-topic", + "preset_mode_command_topic": "preset-mode-command-topic", + "preset_modes": [ + "auto", + "smart", + "whoosh", + "eco", + "breeze", + "silent", + ], + "speed_range_min": 1, + "speed_range_max": 200, + "payload_reset_percentage": "rEset_percentage", + "payload_reset_preset_mode": "rEset_preset_mode", + } } }, ) @@ -226,37 +230,36 @@ async def test_controlling_state_via_topic_with_different_speed_range( """Test the controlling state via topic using an alternate speed range.""" assert await async_setup_component( hass, - fan.DOMAIN, + mqtt.DOMAIN, { - fan.DOMAIN: [ - { - "platform": "mqtt", - "name": "test1", - "command_topic": "command-topic", - "percentage_state_topic": "percentage-state-topic1", - "percentage_command_topic": "percentage-command-topic1", - "speed_range_min": 1, - "speed_range_max": 100, - }, - { - "platform": "mqtt", - "name": "test2", - "command_topic": "command-topic", - "percentage_state_topic": "percentage-state-topic2", - "percentage_command_topic": "percentage-command-topic2", - "speed_range_min": 1, - "speed_range_max": 200, - }, - { - "platform": "mqtt", - "name": "test3", - "command_topic": "command-topic", - "percentage_state_topic": "percentage-state-topic3", - "percentage_command_topic": "percentage-command-topic3", - "speed_range_min": 81, - "speed_range_max": 1023, - }, - ] + mqtt.DOMAIN: { + fan.DOMAIN: [ + { + "name": "test1", + "command_topic": "command-topic", + "percentage_state_topic": "percentage-state-topic1", + "percentage_command_topic": "percentage-command-topic1", + "speed_range_min": 1, + "speed_range_max": 100, + }, + { + "name": "test2", + "command_topic": "command-topic", + "percentage_state_topic": "percentage-state-topic2", + "percentage_command_topic": "percentage-command-topic2", + "speed_range_min": 1, + "speed_range_max": 200, + }, + { + "name": "test3", + "command_topic": "command-topic", + "percentage_state_topic": "percentage-state-topic3", + "percentage_command_topic": "percentage-command-topic3", + "speed_range_min": 81, + "speed_range_max": 1023, + }, + ] + } }, ) await hass.async_block_till_done() @@ -289,22 +292,23 @@ async def test_controlling_state_via_topic_no_percentage_topics( """Test the controlling state via topic without percentage topics.""" assert await async_setup_component( hass, - fan.DOMAIN, + mqtt.DOMAIN, { - fan.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "preset_mode_state_topic": "preset-mode-state-topic", - "preset_mode_command_topic": "preset-mode-command-topic", - "preset_modes": [ - "auto", - "smart", - "whoosh", - "eco", - "breeze", - ], + mqtt.DOMAIN: { + fan.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "preset_mode_state_topic": "preset-mode-state-topic", + "preset_mode_command_topic": "preset-mode-command-topic", + "preset_modes": [ + "auto", + "smart", + "whoosh", + "eco", + "breeze", + ], + } } }, ) @@ -345,33 +349,34 @@ async def test_controlling_state_via_topic_and_json_message( """Test the controlling state via topic and JSON message (percentage mode).""" assert await async_setup_component( hass, - fan.DOMAIN, + mqtt.DOMAIN, { - fan.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "oscillation_state_topic": "oscillation-state-topic", - "oscillation_command_topic": "oscillation-command-topic", - "percentage_state_topic": "percentage-state-topic", - "percentage_command_topic": "percentage-command-topic", - "preset_mode_state_topic": "preset-mode-state-topic", - "preset_mode_command_topic": "preset-mode-command-topic", - "preset_modes": [ - "auto", - "smart", - "whoosh", - "eco", - "breeze", - "silent", - ], - "state_value_template": "{{ value_json.val }}", - "oscillation_value_template": "{{ value_json.val }}", - "percentage_value_template": "{{ value_json.val }}", - "preset_mode_value_template": "{{ value_json.val }}", - "speed_range_min": 1, - "speed_range_max": 100, + mqtt.DOMAIN: { + fan.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "oscillation_state_topic": "oscillation-state-topic", + "oscillation_command_topic": "oscillation-command-topic", + "percentage_state_topic": "percentage-state-topic", + "percentage_command_topic": "percentage-command-topic", + "preset_mode_state_topic": "preset-mode-state-topic", + "preset_mode_command_topic": "preset-mode-command-topic", + "preset_modes": [ + "auto", + "smart", + "whoosh", + "eco", + "breeze", + "silent", + ], + "state_value_template": "{{ value_json.val }}", + "oscillation_value_template": "{{ value_json.val }}", + "percentage_value_template": "{{ value_json.val }}", + "preset_mode_value_template": "{{ value_json.val }}", + "speed_range_min": 1, + "speed_range_max": 100, + } } }, ) @@ -450,33 +455,34 @@ async def test_controlling_state_via_topic_and_json_message_shared_topic( """Test the controlling state via topic and JSON message using a shared topic.""" assert await async_setup_component( hass, - fan.DOMAIN, + mqtt.DOMAIN, { - fan.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "shared-state-topic", - "command_topic": "command-topic", - "oscillation_state_topic": "shared-state-topic", - "oscillation_command_topic": "oscillation-command-topic", - "percentage_state_topic": "shared-state-topic", - "percentage_command_topic": "percentage-command-topic", - "preset_mode_state_topic": "shared-state-topic", - "preset_mode_command_topic": "preset-mode-command-topic", - "preset_modes": [ - "auto", - "smart", - "whoosh", - "eco", - "breeze", - "silent", - ], - "state_value_template": "{{ value_json.state }}", - "oscillation_value_template": "{{ value_json.oscillation }}", - "percentage_value_template": "{{ value_json.percentage }}", - "preset_mode_value_template": "{{ value_json.preset_mode }}", - "speed_range_min": 1, - "speed_range_max": 100, + mqtt.DOMAIN: { + fan.DOMAIN: { + "name": "test", + "state_topic": "shared-state-topic", + "command_topic": "command-topic", + "oscillation_state_topic": "shared-state-topic", + "oscillation_command_topic": "oscillation-command-topic", + "percentage_state_topic": "shared-state-topic", + "percentage_command_topic": "percentage-command-topic", + "preset_mode_state_topic": "shared-state-topic", + "preset_mode_command_topic": "preset-mode-command-topic", + "preset_modes": [ + "auto", + "smart", + "whoosh", + "eco", + "breeze", + "silent", + ], + "state_value_template": "{{ value_json.state }}", + "oscillation_value_template": "{{ value_json.oscillation }}", + "percentage_value_template": "{{ value_json.percentage }}", + "preset_mode_value_template": "{{ value_json.preset_mode }}", + "speed_range_min": 1, + "speed_range_max": 100, + } } }, ) @@ -540,24 +546,25 @@ async def test_sending_mqtt_commands_and_optimistic( """Test optimistic mode without state topic.""" assert await async_setup_component( hass, - fan.DOMAIN, + mqtt.DOMAIN, { - fan.DOMAIN: { - "platform": "mqtt", - "name": "test", - "command_topic": "command-topic", - "payload_off": "StAtE_OfF", - "payload_on": "StAtE_On", - "oscillation_command_topic": "oscillation-command-topic", - "payload_oscillation_off": "OsC_OfF", - "payload_oscillation_on": "OsC_On", - "percentage_command_topic": "percentage-command-topic", - "preset_mode_command_topic": "preset-mode-command-topic", - "preset_modes": [ - "whoosh", - "breeze", - "silent", - ], + mqtt.DOMAIN: { + fan.DOMAIN: { + "name": "test", + "command_topic": "command-topic", + "payload_off": "StAtE_OfF", + "payload_on": "StAtE_On", + "oscillation_command_topic": "oscillation-command-topic", + "payload_oscillation_off": "OsC_OfF", + "payload_oscillation_on": "OsC_On", + "percentage_command_topic": "percentage-command-topic", + "preset_mode_command_topic": "preset-mode-command-topic", + "preset_modes": [ + "whoosh", + "breeze", + "silent", + ], + } } }, ) @@ -664,37 +671,36 @@ async def test_sending_mqtt_commands_with_alternate_speed_range( """Test the controlling state via topic using an alternate speed range.""" assert await async_setup_component( hass, - fan.DOMAIN, + mqtt.DOMAIN, { - fan.DOMAIN: [ - { - "platform": "mqtt", - "name": "test1", - "command_topic": "command-topic", - "percentage_state_topic": "percentage-state-topic1", - "percentage_command_topic": "percentage-command-topic1", - "speed_range_min": 1, - "speed_range_max": 3, - }, - { - "platform": "mqtt", - "name": "test2", - "command_topic": "command-topic", - "percentage_state_topic": "percentage-state-topic2", - "percentage_command_topic": "percentage-command-topic2", - "speed_range_min": 1, - "speed_range_max": 200, - }, - { - "platform": "mqtt", - "name": "test3", - "command_topic": "command-topic", - "percentage_state_topic": "percentage-state-topic3", - "percentage_command_topic": "percentage-command-topic3", - "speed_range_min": 81, - "speed_range_max": 1023, - }, - ] + mqtt.DOMAIN: { + fan.DOMAIN: [ + { + "name": "test1", + "command_topic": "command-topic", + "percentage_state_topic": "percentage-state-topic1", + "percentage_command_topic": "percentage-command-topic1", + "speed_range_min": 1, + "speed_range_max": 3, + }, + { + "name": "test2", + "command_topic": "command-topic", + "percentage_state_topic": "percentage-state-topic2", + "percentage_command_topic": "percentage-command-topic2", + "speed_range_min": 1, + "speed_range_max": 200, + }, + { + "name": "test3", + "command_topic": "command-topic", + "percentage_state_topic": "percentage-state-topic3", + "percentage_command_topic": "percentage-command-topic3", + "speed_range_min": 81, + "speed_range_max": 1023, + }, + ] + } }, ) await hass.async_block_till_done() @@ -771,19 +777,20 @@ async def test_sending_mqtt_commands_and_optimistic_no_legacy( """Test optimistic mode without state topic without legacy speed command topic.""" assert await async_setup_component( hass, - fan.DOMAIN, + mqtt.DOMAIN, { - fan.DOMAIN: { - "platform": "mqtt", - "name": "test", - "command_topic": "command-topic", - "percentage_command_topic": "percentage-command-topic", - "preset_mode_command_topic": "preset-mode-command-topic", - "preset_modes": [ - "whoosh", - "breeze", - "silent", - ], + mqtt.DOMAIN: { + fan.DOMAIN: { + "name": "test", + "command_topic": "command-topic", + "percentage_command_topic": "percentage-command-topic", + "preset_mode_command_topic": "preset-mode-command-topic", + "preset_modes": [ + "whoosh", + "breeze", + "silent", + ], + } } }, ) @@ -902,24 +909,25 @@ async def test_sending_mqtt_command_templates_( """Test optimistic mode without state topic without legacy speed command topic.""" assert await async_setup_component( hass, - fan.DOMAIN, + mqtt.DOMAIN, { - fan.DOMAIN: { - "platform": "mqtt", - "name": "test", - "command_topic": "command-topic", - "command_template": "state: {{ value }}", - "oscillation_command_topic": "oscillation-command-topic", - "oscillation_command_template": "oscillation: {{ value }}", - "percentage_command_topic": "percentage-command-topic", - "percentage_command_template": "percentage: {{ value }}", - "preset_mode_command_topic": "preset-mode-command-topic", - "preset_mode_command_template": "preset_mode: {{ value }}", - "preset_modes": [ - "whoosh", - "breeze", - "silent", - ], + mqtt.DOMAIN: { + fan.DOMAIN: { + "name": "test", + "command_topic": "command-topic", + "command_template": "state: {{ value }}", + "oscillation_command_topic": "oscillation-command-topic", + "oscillation_command_template": "oscillation: {{ value }}", + "percentage_command_topic": "percentage-command-topic", + "percentage_command_template": "percentage: {{ value }}", + "preset_mode_command_topic": "preset-mode-command-topic", + "preset_mode_command_template": "preset_mode: {{ value }}", + "preset_modes": [ + "whoosh", + "breeze", + "silent", + ], + } } }, ) @@ -1044,20 +1052,21 @@ async def test_sending_mqtt_commands_and_optimistic_no_percentage_topic( """Test optimistic mode without state topic without percentage command topic.""" assert await async_setup_component( hass, - fan.DOMAIN, + mqtt.DOMAIN, { - fan.DOMAIN: { - "platform": "mqtt", - "name": "test", - "command_topic": "command-topic", - "preset_mode_command_topic": "preset-mode-command-topic", - "preset_mode_state_topic": "preset-mode-state-topic", - "preset_modes": [ - "whoosh", - "breeze", - "silent", - "high", - ], + mqtt.DOMAIN: { + fan.DOMAIN: { + "name": "test", + "command_topic": "command-topic", + "preset_mode_command_topic": "preset-mode-command-topic", + "preset_mode_state_topic": "preset-mode-state-topic", + "preset_modes": [ + "whoosh", + "breeze", + "silent", + "high", + ], + } } }, ) @@ -1105,25 +1114,26 @@ async def test_sending_mqtt_commands_and_explicit_optimistic( """Test optimistic mode with state topic and turn on attributes.""" assert await async_setup_component( hass, - fan.DOMAIN, + mqtt.DOMAIN, { - fan.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "oscillation_state_topic": "oscillation-state-topic", - "oscillation_command_topic": "oscillation-command-topic", - "percentage_state_topic": "percentage-state-topic", - "percentage_command_topic": "percentage-command-topic", - "preset_mode_command_topic": "preset-mode-command-topic", - "preset_mode_state_topic": "preset-mode-state-topic", - "preset_modes": [ - "whoosh", - "breeze", - "silent", - ], - "optimistic": True, + mqtt.DOMAIN: { + fan.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "oscillation_state_topic": "oscillation-state-topic", + "oscillation_command_topic": "oscillation-command-topic", + "percentage_state_topic": "percentage-state-topic", + "percentage_command_topic": "percentage-command-topic", + "preset_mode_command_topic": "preset-mode-command-topic", + "preset_mode_state_topic": "preset-mode-state-topic", + "preset_modes": [ + "whoosh", + "breeze", + "silent", + ], + "optimistic": True, + } } }, ) @@ -1355,7 +1365,7 @@ async def test_encoding_subscribable_topics( attribute_value, ): """Test handling of incoming encoded payload.""" - config = copy.deepcopy(DEFAULT_CONFIG[fan.DOMAIN]) + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[fan.DOMAIN]) config[ATTR_PRESET_MODES] = ["eco", "auto"] config[CONF_PRESET_MODE_COMMAND_TOPIC] = "fan/some_preset_mode_command_topic" config[CONF_PERCENTAGE_COMMAND_TOPIC] = "fan/some_percentage_command_topic" @@ -1377,19 +1387,20 @@ async def test_attributes(hass, mqtt_mock_entry_with_yaml_config, caplog): """Test attributes.""" assert await async_setup_component( hass, - fan.DOMAIN, + mqtt.DOMAIN, { - fan.DOMAIN: { - "platform": "mqtt", - "name": "test", - "command_topic": "command-topic", - "oscillation_command_topic": "oscillation-command-topic", - "preset_mode_command_topic": "preset-mode-command-topic", - "percentage_command_topic": "percentage-command-topic", - "preset_modes": [ - "breeze", - "silent", - ], + mqtt.DOMAIN: { + fan.DOMAIN: { + "name": "test", + "command_topic": "command-topic", + "oscillation_command_topic": "oscillation-command-topic", + "preset_mode_command_topic": "preset-mode-command-topic", + "percentage_command_topic": "percentage-command-topic", + "preset_modes": [ + "breeze", + "silent", + ], + } } }, ) @@ -1424,177 +1435,203 @@ async def test_attributes(hass, mqtt_mock_entry_with_yaml_config, caplog): assert state.attributes.get(fan.ATTR_OSCILLATING) is False -async def test_supported_features(hass, mqtt_mock_entry_with_yaml_config): +@pytest.mark.parametrize( + "name,config,success,features", + [ + ( + "test1", + { + "name": "test1", + "command_topic": "command-topic", + }, + True, + 0, + ), + ( + "test2", + { + "name": "test2", + "command_topic": "command-topic", + "oscillation_command_topic": "oscillation-command-topic", + }, + True, + fan.SUPPORT_OSCILLATE, + ), + ( + "test3", + { + "name": "test3", + "command_topic": "command-topic", + "percentage_command_topic": "percentage-command-topic", + }, + True, + fan.SUPPORT_SET_SPEED, + ), + ( + "test4", + { + "name": "test4", + "command_topic": "command-topic", + "preset_mode_command_topic": "preset-mode-command-topic", + }, + False, + None, + ), + ( + "test5", + { + "name": "test5", + "command_topic": "command-topic", + "preset_mode_command_topic": "preset-mode-command-topic", + "preset_modes": ["eco", "auto"], + }, + True, + fan.SUPPORT_PRESET_MODE, + ), + ( + "test6", + { + "name": "test6", + "command_topic": "command-topic", + "preset_mode_command_topic": "preset-mode-command-topic", + "preset_modes": ["eco", "smart", "auto"], + }, + True, + fan.SUPPORT_PRESET_MODE, + ), + ( + "test7", + { + "name": "test7", + "command_topic": "command-topic", + "percentage_command_topic": "percentage-command-topic", + }, + True, + fan.SUPPORT_SET_SPEED, + ), + ( + "test8", + { + "name": "test8", + "command_topic": "command-topic", + "oscillation_command_topic": "oscillation-command-topic", + "percentage_command_topic": "percentage-command-topic", + }, + True, + fan.SUPPORT_OSCILLATE | fan.SUPPORT_SET_SPEED, + ), + ( + "test9", + { + "name": "test9", + "command_topic": "command-topic", + "preset_mode_command_topic": "preset-mode-command-topic", + "preset_modes": ["Mode1", "Mode2", "Mode3"], + }, + True, + fan.SUPPORT_PRESET_MODE, + ), + ( + "test10", + { + "name": "test10", + "command_topic": "command-topic", + "preset_mode_command_topic": "preset-mode-command-topic", + "preset_modes": ["whoosh", "silent", "auto"], + }, + True, + fan.SUPPORT_PRESET_MODE, + ), + ( + "test11", + { + "name": "test11", + "command_topic": "command-topic", + "oscillation_command_topic": "oscillation-command-topic", + "preset_mode_command_topic": "preset-mode-command-topic", + "preset_modes": ["Mode1", "Mode2", "Mode3"], + }, + True, + fan.SUPPORT_PRESET_MODE | fan.SUPPORT_OSCILLATE, + ), + ( + "test12", + { + "name": "test12", + "command_topic": "command-topic", + "percentage_command_topic": "percentage-command-topic", + "speed_range_min": 1, + "speed_range_max": 40, + }, + True, + fan.SUPPORT_SET_SPEED, + ), + ( + "test13", + { + "name": "test13", + "command_topic": "command-topic", + "percentage_command_topic": "percentage-command-topic", + "speed_range_min": 50, + "speed_range_max": 40, + }, + False, + None, + ), + ( + "test14", + { + "name": "test14", + "command_topic": "command-topic", + "percentage_command_topic": "percentage-command-topic", + "speed_range_min": 0, + "speed_range_max": 40, + }, + False, + None, + ), + ( + "test15", + { + "name": "test7reset_payload_in_preset_modes_a", + "command_topic": "command-topic", + "preset_mode_command_topic": "preset-mode-command-topic", + "preset_modes": ["auto", "smart", "normal", "None"], + }, + False, + None, + ), + ( + "test16", + { + "name": "test16", + "command_topic": "command-topic", + "preset_mode_command_topic": "preset-mode-command-topic", + "preset_modes": ["whoosh", "silent", "auto", "None"], + "payload_reset_preset_mode": "normal", + }, + True, + fan.SUPPORT_PRESET_MODE, + ), + ], +) +async def test_supported_features( + hass, mqtt_mock_entry_with_yaml_config, name, config, success, features +): """Test optimistic mode without state topic.""" - assert await async_setup_component( - hass, - fan.DOMAIN, - { - fan.DOMAIN: [ - { - "platform": "mqtt", - "name": "test1", - "command_topic": "command-topic", - }, - { - "platform": "mqtt", - "name": "test2", - "command_topic": "command-topic", - "oscillation_command_topic": "oscillation-command-topic", - }, - { - "platform": "mqtt", - "name": "test3b", - "command_topic": "command-topic", - "percentage_command_topic": "percentage-command-topic", - }, - { - "platform": "mqtt", - "name": "test3c1", - "command_topic": "command-topic", - "preset_mode_command_topic": "preset-mode-command-topic", - }, - { - "platform": "mqtt", - "name": "test3c2", - "command_topic": "command-topic", - "preset_mode_command_topic": "preset-mode-command-topic", - "preset_modes": ["eco", "auto"], - }, - { - "platform": "mqtt", - "name": "test3c3", - "command_topic": "command-topic", - "preset_mode_command_topic": "preset-mode-command-topic", - "preset_modes": ["eco", "smart", "auto"], - }, - { - "platform": "mqtt", - "name": "test4pcta", - "command_topic": "command-topic", - "percentage_command_topic": "percentage-command-topic", - }, - { - "platform": "mqtt", - "name": "test4pctb", - "command_topic": "command-topic", - "oscillation_command_topic": "oscillation-command-topic", - "percentage_command_topic": "percentage-command-topic", - }, - { - "platform": "mqtt", - "name": "test5pr_ma", - "command_topic": "command-topic", - "preset_mode_command_topic": "preset-mode-command-topic", - "preset_modes": ["Mode1", "Mode2", "Mode3"], - }, - { - "platform": "mqtt", - "name": "test5pr_mb", - "command_topic": "command-topic", - "preset_mode_command_topic": "preset-mode-command-topic", - "preset_modes": ["whoosh", "silent", "auto"], - }, - { - "platform": "mqtt", - "name": "test5pr_mc", - "command_topic": "command-topic", - "oscillation_command_topic": "oscillation-command-topic", - "preset_mode_command_topic": "preset-mode-command-topic", - "preset_modes": ["Mode1", "Mode2", "Mode3"], - }, - { - "platform": "mqtt", - "name": "test6spd_range_a", - "command_topic": "command-topic", - "percentage_command_topic": "percentage-command-topic", - "speed_range_min": 1, - "speed_range_max": 40, - }, - { - "platform": "mqtt", - "name": "test6spd_range_b", - "command_topic": "command-topic", - "percentage_command_topic": "percentage-command-topic", - "speed_range_min": 50, - "speed_range_max": 40, - }, - { - "platform": "mqtt", - "name": "test6spd_range_c", - "command_topic": "command-topic", - "percentage_command_topic": "percentage-command-topic", - "speed_range_min": 0, - "speed_range_max": 40, - }, - { - "platform": "mqtt", - "name": "test7reset_payload_in_preset_modes_a", - "command_topic": "command-topic", - "preset_mode_command_topic": "preset-mode-command-topic", - "preset_modes": ["auto", "smart", "normal", "None"], - }, - { - "platform": "mqtt", - "name": "test7reset_payload_in_preset_modes_b", - "command_topic": "command-topic", - "preset_mode_command_topic": "preset-mode-command-topic", - "preset_modes": ["whoosh", "silent", "auto", "None"], - "payload_reset_preset_mode": "normal", - }, - ] - }, - ) - await hass.async_block_till_done() - await mqtt_mock_entry_with_yaml_config() - - state = hass.states.get("fan.test1") - assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == 0 - state = hass.states.get("fan.test2") - assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == fan.SUPPORT_OSCILLATE - - state = hass.states.get("fan.test3b") - assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == fan.SUPPORT_SET_SPEED - - state = hass.states.get("fan.test3c1") - assert state is None - - state = hass.states.get("fan.test3c2") - assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == fan.SUPPORT_PRESET_MODE - state = hass.states.get("fan.test3c3") - assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == fan.SUPPORT_PRESET_MODE - - state = hass.states.get("fan.test4pcta") - assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == fan.SUPPORT_SET_SPEED - state = hass.states.get("fan.test4pctb") - assert ( - state.attributes.get(ATTR_SUPPORTED_FEATURES) - == fan.SUPPORT_OSCILLATE | fan.SUPPORT_SET_SPEED - ) - - state = hass.states.get("fan.test5pr_ma") - assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == fan.SUPPORT_PRESET_MODE - state = hass.states.get("fan.test5pr_mb") - assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == fan.SUPPORT_PRESET_MODE - state = hass.states.get("fan.test5pr_mc") assert ( - state.attributes.get(ATTR_SUPPORTED_FEATURES) - == fan.SUPPORT_OSCILLATE | fan.SUPPORT_PRESET_MODE + await async_setup_component( + hass, mqtt.DOMAIN, {mqtt.DOMAIN: {fan.DOMAIN: config}} + ) + is success ) + if success: + await hass.async_block_till_done() + await mqtt_mock_entry_with_yaml_config() - state = hass.states.get("fan.test6spd_range_a") - assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == fan.SUPPORT_SET_SPEED - assert state.attributes.get("percentage_step") == 2.5 - state = hass.states.get("fan.test6spd_range_b") - assert state is None - state = hass.states.get("fan.test6spd_range_c") - assert state is None - - state = hass.states.get("fan.test7reset_payload_in_preset_modes_a") - assert state is None - state = hass.states.get("fan.test7reset_payload_in_preset_modes_b") - assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == fan.SUPPORT_PRESET_MODE + state = hass.states.get(f"fan.{name}") + assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == features async def test_availability_when_connection_lost( @@ -1602,14 +1639,14 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, fan.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, fan.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, fan.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, fan.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -1619,7 +1656,7 @@ async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_conf hass, mqtt_mock_entry_with_yaml_config, fan.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, True, "state-topic", "1", @@ -1632,7 +1669,7 @@ async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_confi hass, mqtt_mock_entry_with_yaml_config, fan.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, True, "state-topic", "1", @@ -1644,7 +1681,7 @@ async def test_setting_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_with_yaml_config, fan.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, fan.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -1656,7 +1693,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( hass, mqtt_mock_entry_no_yaml_config, fan.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, MQTT_FAN_ATTRIBUTES_BLOCKED, ) @@ -1664,7 +1701,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_with_template( - hass, mqtt_mock_entry_with_yaml_config, fan.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, fan.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -1673,7 +1710,11 @@ async def test_update_with_json_attrs_not_dict( ): """Test attributes get extracted from a JSON result.""" await help_test_update_with_json_attrs_not_dict( - hass, mqtt_mock_entry_with_yaml_config, caplog, fan.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_with_yaml_config, + caplog, + fan.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) @@ -1682,14 +1723,18 @@ async def test_update_with_json_attrs_bad_json( ): """Test attributes get extracted from a JSON result.""" await help_test_update_with_json_attrs_bad_JSON( - hass, mqtt_mock_entry_with_yaml_config, caplog, fan.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_with_yaml_config, + caplog, + fan.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test update of discovered MQTTAttributes.""" await help_test_discovery_update_attr( - hass, mqtt_mock_entry_no_yaml_config, caplog, fan.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, caplog, fan.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -1767,42 +1812,42 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT fan device registry integration.""" await help_test_entity_device_info_with_connection( - hass, mqtt_mock_entry_no_yaml_config, fan.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, fan.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT fan device registry integration.""" await help_test_entity_device_info_with_identifier( - hass, mqtt_mock_entry_no_yaml_config, fan.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, fan.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): """Test device registry update.""" await help_test_entity_device_info_update( - hass, mqtt_mock_entry_no_yaml_config, fan.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, fan.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test device registry remove.""" await help_test_entity_device_info_remove( - hass, mqtt_mock_entry_no_yaml_config, fan.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, fan.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_config): """Test MQTT subscriptions are managed when entity_id is updated.""" await help_test_entity_id_update_subscriptions( - hass, mqtt_mock_entry_with_yaml_config, fan.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, fan.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, fan.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, fan.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -1812,7 +1857,7 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): hass, mqtt_mock_entry_no_yaml_config, fan.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, fan.SERVICE_TURN_ON, ) @@ -1869,7 +1914,7 @@ async def test_publishing_with_custom_encoding( ): """Test publishing MQTT payload with different encoding.""" domain = fan.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG[domain]) + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[domain]) if topic == "preset_mode_command_topic": config["preset_modes"] = ["auto", "eco"] @@ -1890,7 +1935,7 @@ async def test_publishing_with_custom_encoding( async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = fan.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) @@ -1899,14 +1944,14 @@ async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_pa async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = fan.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable_late(hass, caplog, tmp_path, domain, config) async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = fan.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG[platform]) + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) config["name"] = "test" del config["platform"] await help_test_setup_manual_entity_from_yaml(hass, platform, config) @@ -1916,7 +1961,20 @@ async def test_setup_manual_entity_from_yaml(hass): async def test_unload_entry(hass, mqtt_mock_entry_with_yaml_config, tmp_path): """Test unloading the config entry.""" domain = fan.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry_with_yaml_config, tmp_path, domain, config ) + + +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +async def test_setup_with_legacy_schema(hass, mqtt_mock_entry_with_yaml_config): + """Test a setup with deprecated yaml platform schema.""" + domain = fan.DOMAIN + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[domain]) + config["name"] = "test" + assert await async_setup_component(hass, domain, {domain: config}) + await hass.async_block_till_done() + await mqtt_mock_entry_with_yaml_config() + assert hass.states.get(f"{domain}.test") is not None diff --git a/tests/components/mqtt/test_humidifier.py b/tests/components/mqtt/test_humidifier.py index 38dc634578fd6..0cc2be638bfb3 100644 --- a/tests/components/mqtt/test_humidifier.py +++ b/tests/components/mqtt/test_humidifier.py @@ -5,7 +5,7 @@ import pytest from voluptuous.error import MultipleInvalid -from homeassistant.components import humidifier +from homeassistant.components import humidifier, mqtt from homeassistant.components.humidifier import ( ATTR_HUMIDITY, ATTR_MODE, @@ -68,15 +68,21 @@ from tests.common import async_fire_mqtt_message DEFAULT_CONFIG = { - humidifier.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "target_humidity_command_topic": "humidity-command-topic", + mqtt.DOMAIN: { + humidifier.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "target_humidity_command_topic": "humidity-command-topic", + } } } +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +DEFAULT_CONFIG_LEGACY = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) +DEFAULT_CONFIG_LEGACY[humidifier.DOMAIN]["platform"] = mqtt.DOMAIN + @pytest.fixture(autouse=True) def humidifer_platform_only(): @@ -126,16 +132,17 @@ async def async_set_humidity( await hass.services.async_call(DOMAIN, SERVICE_SET_HUMIDITY, data, blocking=True) -async def test_fail_setup_if_no_command_topic(hass, mqtt_mock_entry_no_yaml_config): +async def test_fail_setup_if_no_command_topic(hass, caplog): """Test if command fails with command topic.""" - assert await async_setup_component( + assert not await async_setup_component( hass, - humidifier.DOMAIN, - {humidifier.DOMAIN: {"platform": "mqtt", "name": "test"}}, + mqtt.DOMAIN, + {mqtt.DOMAIN: {humidifier.DOMAIN: {"name": "test"}}}, + ) + assert ( + "Invalid config for [mqtt]: required key not provided @ data['mqtt']['humidifier'][0]['command_topic']. Got None" + in caplog.text ) - await hass.async_block_till_done() - await mqtt_mock_entry_no_yaml_config() - assert hass.states.get("humidifier.test") is None async def test_controlling_state_via_topic( @@ -144,29 +151,30 @@ async def test_controlling_state_via_topic( """Test the controlling state via topic.""" assert await async_setup_component( hass, - humidifier.DOMAIN, + mqtt.DOMAIN, { - humidifier.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "payload_off": "StAtE_OfF", - "payload_on": "StAtE_On", - "target_humidity_state_topic": "humidity-state-topic", - "target_humidity_command_topic": "humidity-command-topic", - "mode_state_topic": "mode-state-topic", - "mode_command_topic": "mode-command-topic", - "modes": [ - "auto", - "comfort", - "home", - "eco", - "sleep", - "baby", - ], - "payload_reset_humidity": "rEset_humidity", - "payload_reset_mode": "rEset_mode", + mqtt.DOMAIN: { + humidifier.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "payload_off": "StAtE_OfF", + "payload_on": "StAtE_On", + "target_humidity_state_topic": "humidity-state-topic", + "target_humidity_command_topic": "humidity-command-topic", + "mode_state_topic": "mode-state-topic", + "mode_command_topic": "mode-command-topic", + "modes": [ + "auto", + "comfort", + "home", + "eco", + "sleep", + "baby", + ], + "payload_reset_humidity": "rEset_humidity", + "payload_reset_mode": "rEset_mode", + } } }, ) @@ -248,25 +256,26 @@ async def test_controlling_state_via_topic_and_json_message( """Test the controlling state via topic and JSON message.""" assert await async_setup_component( hass, - humidifier.DOMAIN, + mqtt.DOMAIN, { - humidifier.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "target_humidity_state_topic": "humidity-state-topic", - "target_humidity_command_topic": "humidity-command-topic", - "mode_state_topic": "mode-state-topic", - "mode_command_topic": "mode-command-topic", - "modes": [ - "auto", - "eco", - "baby", - ], - "state_value_template": "{{ value_json.val }}", - "target_humidity_state_template": "{{ value_json.val }}", - "mode_state_template": "{{ value_json.val }}", + mqtt.DOMAIN: { + humidifier.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "target_humidity_state_topic": "humidity-state-topic", + "target_humidity_command_topic": "humidity-command-topic", + "mode_state_topic": "mode-state-topic", + "mode_command_topic": "mode-command-topic", + "modes": [ + "auto", + "eco", + "baby", + ], + "state_value_template": "{{ value_json.val }}", + "target_humidity_state_template": "{{ value_json.val }}", + "mode_state_template": "{{ value_json.val }}", + } } }, ) @@ -336,25 +345,26 @@ async def test_controlling_state_via_topic_and_json_message_shared_topic( """Test the controlling state via topic and JSON message using a shared topic.""" assert await async_setup_component( hass, - humidifier.DOMAIN, + mqtt.DOMAIN, { - humidifier.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "shared-state-topic", - "command_topic": "command-topic", - "target_humidity_state_topic": "shared-state-topic", - "target_humidity_command_topic": "percentage-command-topic", - "mode_state_topic": "shared-state-topic", - "mode_command_topic": "mode-command-topic", - "modes": [ - "auto", - "eco", - "baby", - ], - "state_value_template": "{{ value_json.state }}", - "target_humidity_state_template": "{{ value_json.humidity }}", - "mode_state_template": "{{ value_json.mode }}", + mqtt.DOMAIN: { + humidifier.DOMAIN: { + "name": "test", + "state_topic": "shared-state-topic", + "command_topic": "command-topic", + "target_humidity_state_topic": "shared-state-topic", + "target_humidity_command_topic": "percentage-command-topic", + "mode_state_topic": "shared-state-topic", + "mode_command_topic": "mode-command-topic", + "modes": [ + "auto", + "eco", + "baby", + ], + "state_value_template": "{{ value_json.state }}", + "target_humidity_state_template": "{{ value_json.humidity }}", + "mode_state_template": "{{ value_json.mode }}", + } } }, ) @@ -414,21 +424,22 @@ async def test_sending_mqtt_commands_and_optimistic( """Test optimistic mode without state topic.""" assert await async_setup_component( hass, - humidifier.DOMAIN, + mqtt.DOMAIN, { - humidifier.DOMAIN: { - "platform": "mqtt", - "name": "test", - "command_topic": "command-topic", - "payload_off": "StAtE_OfF", - "payload_on": "StAtE_On", - "target_humidity_command_topic": "humidity-command-topic", - "mode_command_topic": "mode-command-topic", - "modes": [ - "eco", - "auto", - "baby", - ], + mqtt.DOMAIN: { + humidifier.DOMAIN: { + "name": "test", + "command_topic": "command-topic", + "payload_off": "StAtE_OfF", + "payload_on": "StAtE_On", + "target_humidity_command_topic": "humidity-command-topic", + "mode_command_topic": "mode-command-topic", + "modes": [ + "eco", + "auto", + "baby", + ], + } } }, ) @@ -510,22 +521,23 @@ async def test_sending_mqtt_command_templates_( """Testing command templates with optimistic mode without state topic.""" assert await async_setup_component( hass, - humidifier.DOMAIN, + mqtt.DOMAIN, { - humidifier.DOMAIN: { - "platform": "mqtt", - "name": "test", - "command_topic": "command-topic", - "command_template": "state: {{ value }}", - "target_humidity_command_topic": "humidity-command-topic", - "target_humidity_command_template": "humidity: {{ value }}", - "mode_command_topic": "mode-command-topic", - "mode_command_template": "mode: {{ value }}", - "modes": [ - "auto", - "eco", - "sleep", - ], + mqtt.DOMAIN: { + humidifier.DOMAIN: { + "name": "test", + "command_topic": "command-topic", + "command_template": "state: {{ value }}", + "target_humidity_command_topic": "humidity-command-topic", + "target_humidity_command_template": "humidity: {{ value }}", + "mode_command_topic": "mode-command-topic", + "mode_command_template": "mode: {{ value }}", + "modes": [ + "auto", + "eco", + "sleep", + ], + } } }, ) @@ -607,23 +619,24 @@ async def test_sending_mqtt_commands_and_explicit_optimistic( """Test optimistic mode with state topic and turn on attributes.""" assert await async_setup_component( hass, - humidifier.DOMAIN, + mqtt.DOMAIN, { - humidifier.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "target_humidity_state_topic": "humidity-state-topic", - "target_humidity_command_topic": "humidity-command-topic", - "mode_command_topic": "mode-command-topic", - "mode_state_topic": "mode-state-topic", - "modes": [ - "auto", - "eco", - "baby", - ], - "optimistic": True, + mqtt.DOMAIN: { + humidifier.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "target_humidity_state_topic": "humidity-state-topic", + "target_humidity_command_topic": "humidity-command-topic", + "mode_command_topic": "mode-command-topic", + "mode_state_topic": "mode-state-topic", + "modes": [ + "auto", + "eco", + "baby", + ], + "optimistic": True, + } } }, ) @@ -737,7 +750,7 @@ async def test_encoding_subscribable_topics( attribute_value, ): """Test handling of incoming encoded payload.""" - config = copy.deepcopy(DEFAULT_CONFIG[humidifier.DOMAIN]) + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[humidifier.DOMAIN]) config["modes"] = ["eco", "auto"] config[CONF_MODE_COMMAND_TOPIC] = "humidifier/some_mode_command_topic" await help_test_encoding_subscribable_topics( @@ -757,18 +770,19 @@ async def test_attributes(hass, mqtt_mock_entry_with_yaml_config, caplog): """Test attributes.""" assert await async_setup_component( hass, - humidifier.DOMAIN, + mqtt.DOMAIN, { - humidifier.DOMAIN: { - "platform": "mqtt", - "name": "test", - "command_topic": "command-topic", - "mode_command_topic": "mode-command-topic", - "target_humidity_command_topic": "humidity-command-topic", - "modes": [ - "eco", - "baby", - ], + mqtt.DOMAIN: { + humidifier.DOMAIN: { + "name": "test", + "command_topic": "command-topic", + "mode_command_topic": "mode-command-topic", + "target_humidity_command_topic": "humidity-command-topic", + "modes": [ + "eco", + "baby", + ], + } } }, ) @@ -799,157 +813,182 @@ async def test_attributes(hass, mqtt_mock_entry_with_yaml_config, caplog): assert state.attributes.get(humidifier.ATTR_MODE) is None -async def test_invalid_configurations(hass, mqtt_mock_entry_with_yaml_config, caplog): - """Test invalid configurations.""" - assert await async_setup_component( - hass, - humidifier.DOMAIN, - { - humidifier.DOMAIN: [ - { - "platform": "mqtt", - "name": "test_valid_1", - "command_topic": "command-topic", - "target_humidity_command_topic": "humidity-command-topic", - }, - { - "platform": "mqtt", - "name": "test_valid_2", - "command_topic": "command-topic", - "target_humidity_command_topic": "humidity-command-topic", - "device_class": "humidifier", - }, - { - "platform": "mqtt", - "name": "test_valid_3", - "command_topic": "command-topic", - "target_humidity_command_topic": "humidity-command-topic", - "device_class": "dehumidifier", - }, - { - "platform": "mqtt", - "name": "test_invalid_device_class", - "command_topic": "command-topic", - "target_humidity_command_topic": "humidity-command-topic", - "device_class": "notsupporedSpeci@l", - }, - { - "platform": "mqtt", - "name": "test_mode_command_without_modes", - "command_topic": "command-topic", - "target_humidity_command_topic": "humidity-command-topic", - "mode_command_topic": "mode-command-topic", - }, - { - "platform": "mqtt", - "name": "test_invalid_humidity_min_max_1", - "command_topic": "command-topic", - "target_humidity_command_topic": "humidity-command-topic", - "min_humidity": 0, - "max_humidity": 101, - }, - { - "platform": "mqtt", - "name": "test_invalid_humidity_min_max_2", - "command_topic": "command-topic", - "target_humidity_command_topic": "humidity-command-topic", - "max_humidity": 20, - "min_humidity": 40, - }, - { - "platform": "mqtt", - "name": "test_invalid_mode_is_reset", - "command_topic": "command-topic", - "target_humidity_command_topic": "humidity-command-topic", - "mode_command_topic": "mode-command-topic", - "modes": ["eco", "None"], - }, - ] - }, +@pytest.mark.parametrize( + "config,valid", + [ + ( + { + "name": "test_valid_1", + "command_topic": "command-topic", + "target_humidity_command_topic": "humidity-command-topic", + }, + True, + ), + ( + { + "name": "test_valid_2", + "command_topic": "command-topic", + "target_humidity_command_topic": "humidity-command-topic", + "device_class": "humidifier", + }, + True, + ), + ( + { + "name": "test_valid_3", + "command_topic": "command-topic", + "target_humidity_command_topic": "humidity-command-topic", + "device_class": "dehumidifier", + }, + True, + ), + ( + { + "name": "test_invalid_device_class", + "command_topic": "command-topic", + "target_humidity_command_topic": "humidity-command-topic", + "device_class": "notsupporedSpeci@l", + }, + False, + ), + ( + { + "name": "test_mode_command_without_modes", + "command_topic": "command-topic", + "target_humidity_command_topic": "humidity-command-topic", + "mode_command_topic": "mode-command-topic", + }, + False, + ), + ( + { + "name": "test_invalid_humidity_min_max_1", + "command_topic": "command-topic", + "target_humidity_command_topic": "humidity-command-topic", + "min_humidity": 0, + "max_humidity": 101, + }, + False, + ), + ( + { + "name": "test_invalid_humidity_min_max_2", + "command_topic": "command-topic", + "target_humidity_command_topic": "humidity-command-topic", + "max_humidity": 20, + "min_humidity": 40, + }, + False, + ), + ( + { + "name": "test_invalid_mode_is_reset", + "command_topic": "command-topic", + "target_humidity_command_topic": "humidity-command-topic", + "mode_command_topic": "mode-command-topic", + "modes": ["eco", "None"], + }, + False, + ), + ], +) +async def test_validity_configurations(hass, config, valid): + """Test validity of configurations.""" + assert ( + await async_setup_component( + hass, + mqtt.DOMAIN, + {mqtt.DOMAIN: {humidifier.DOMAIN: config}}, + ) + is valid ) - await hass.async_block_till_done() - await mqtt_mock_entry_with_yaml_config() - assert hass.states.get("humidifier.test_valid_1") is not None - assert hass.states.get("humidifier.test_valid_2") is not None - assert hass.states.get("humidifier.test_valid_3") is not None - assert hass.states.get("humidifier.test_invalid_device_class") is None - assert hass.states.get("humidifier.test_mode_command_without_modes") is None - assert "not all values in the same group of inclusion" in caplog.text - caplog.clear() - assert hass.states.get("humidifier.test_invalid_humidity_min_max_1") is None - assert hass.states.get("humidifier.test_invalid_humidity_min_max_2") is None - assert hass.states.get("humidifier.test_invalid_mode_is_reset") is None - -async def test_supported_features(hass, mqtt_mock_entry_with_yaml_config): +@pytest.mark.parametrize( + "name,config,success,features", + [ + ( + "test1", + { + "name": "test1", + "command_topic": "command-topic", + "target_humidity_command_topic": "humidity-command-topic", + }, + True, + 0, + ), + ( + "test2", + { + "name": "test2", + "command_topic": "command-topic", + "target_humidity_command_topic": "humidity-command-topic", + "mode_command_topic": "mode-command-topic", + "modes": ["eco", "auto"], + }, + True, + humidifier.SUPPORT_MODES, + ), + ( + "test3", + { + "name": "test3", + "command_topic": "command-topic", + "target_humidity_command_topic": "humidity-command-topic", + }, + True, + 0, + ), + ( + "test4", + { + "name": "test4", + "command_topic": "command-topic", + "target_humidity_command_topic": "humidity-command-topic", + "mode_command_topic": "mode-command-topic", + "modes": ["eco", "auto"], + }, + True, + humidifier.SUPPORT_MODES, + ), + ( + "test5", + { + "name": "test5", + "command_topic": "command-topic", + }, + False, + None, + ), + ( + "test6", + { + "name": "test6", + "target_humidity_command_topic": "humidity-command-topic", + }, + False, + None, + ), + ], +) +async def test_supported_features( + hass, mqtt_mock_entry_with_yaml_config, name, config, success, features +): """Test supported features.""" - assert await async_setup_component( - hass, - humidifier.DOMAIN, - { - humidifier.DOMAIN: [ - { - "platform": "mqtt", - "name": "test1", - "command_topic": "command-topic", - "target_humidity_command_topic": "humidity-command-topic", - }, - { - "platform": "mqtt", - "name": "test2", - "command_topic": "command-topic", - "target_humidity_command_topic": "humidity-command-topic", - "mode_command_topic": "mode-command-topic", - "modes": ["eco", "auto"], - }, - { - "platform": "mqtt", - "name": "test3", - "command_topic": "command-topic", - "target_humidity_command_topic": "humidity-command-topic", - }, - { - "platform": "mqtt", - "name": "test4", - "command_topic": "command-topic", - "target_humidity_command_topic": "humidity-command-topic", - "mode_command_topic": "mode-command-topic", - "modes": ["eco", "auto"], - }, - { - "platform": "mqtt", - "name": "test5", - "command_topic": "command-topic", - }, - { - "platform": "mqtt", - "name": "test6", - "target_humidity_command_topic": "humidity-command-topic", - }, - ] - }, + assert ( + await async_setup_component( + hass, + mqtt.DOMAIN, + {mqtt.DOMAIN: {humidifier.DOMAIN: config}}, + ) + is success ) - await hass.async_block_till_done() - await mqtt_mock_entry_with_yaml_config() - - state = hass.states.get("humidifier.test1") - assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == 0 - - state = hass.states.get("humidifier.test2") - assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == humidifier.SUPPORT_MODES - - state = hass.states.get("humidifier.test3") - assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == 0 + if success: + await hass.async_block_till_done() + await mqtt_mock_entry_with_yaml_config() - state = hass.states.get("humidifier.test4") - assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == humidifier.SUPPORT_MODES - - state = hass.states.get("humidifier.test5") - assert state is None - - state = hass.states.get("humidifier.test6") - assert state is None + state = hass.states.get(f"humidifier.{name}") + assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == features async def test_availability_when_connection_lost( @@ -957,14 +996,14 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -974,7 +1013,7 @@ async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_conf hass, mqtt_mock_entry_with_yaml_config, humidifier.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, True, "state-topic", "1", @@ -987,7 +1026,7 @@ async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_confi hass, mqtt_mock_entry_with_yaml_config, humidifier.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, True, "state-topic", "1", @@ -999,7 +1038,7 @@ async def test_setting_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_with_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -1011,7 +1050,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( hass, mqtt_mock_entry_no_yaml_config, humidifier.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, MQTT_HUMIDIFIER_ATTRIBUTES_BLOCKED, ) @@ -1019,7 +1058,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_with_template( - hass, mqtt_mock_entry_with_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -1032,7 +1071,7 @@ async def test_update_with_json_attrs_not_dict( mqtt_mock_entry_with_yaml_config, caplog, humidifier.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, ) @@ -1045,14 +1084,18 @@ async def test_update_with_json_attrs_bad_json( mqtt_mock_entry_with_yaml_config, caplog, humidifier.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, ) async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test update of discovered MQTTAttributes.""" await help_test_discovery_update_attr( - hass, mqtt_mock_entry_no_yaml_config, caplog, humidifier.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_no_yaml_config, + caplog, + humidifier.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) @@ -1148,42 +1191,42 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT fan device registry integration.""" await help_test_entity_device_info_with_connection( - hass, mqtt_mock_entry_no_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT fan device registry integration.""" await help_test_entity_device_info_with_identifier( - hass, mqtt_mock_entry_no_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): """Test device registry update.""" await help_test_entity_device_info_update( - hass, mqtt_mock_entry_no_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test device registry remove.""" await help_test_entity_device_info_remove( - hass, mqtt_mock_entry_no_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_config): """Test MQTT subscriptions are managed when entity_id is updated.""" await help_test_entity_id_update_subscriptions( - hass, mqtt_mock_entry_with_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -1193,7 +1236,7 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): hass, mqtt_mock_entry_no_yaml_config, humidifier.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, humidifier.SERVICE_TURN_ON, ) @@ -1243,7 +1286,7 @@ async def test_publishing_with_custom_encoding( ): """Test publishing MQTT payload with different encoding.""" domain = humidifier.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG[domain]) + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[domain]) if topic == "mode_command_topic": config["modes"] = ["auto", "eco"] @@ -1264,7 +1307,7 @@ async def test_publishing_with_custom_encoding( async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = humidifier.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) @@ -1273,14 +1316,14 @@ async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_pa async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = humidifier.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable_late(hass, caplog, tmp_path, domain, config) async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = humidifier.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG[platform]) + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) config["name"] = "test" del config["platform"] await help_test_setup_manual_entity_from_yaml(hass, platform, config) @@ -1288,21 +1331,33 @@ async def test_setup_manual_entity_from_yaml(hass): async def test_config_schema_validation(hass): - """Test invalid platform options in the config schema do pass the config validation.""" + """Test invalid platform options in the config schema do not pass the config validation.""" platform = humidifier.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG[platform]) + config = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][platform]) config["name"] = "test" - del config["platform"] - CONFIG_SCHEMA({DOMAIN: {platform: config}}) - CONFIG_SCHEMA({DOMAIN: {platform: [config]}}) + CONFIG_SCHEMA({mqtt.DOMAIN: {platform: config}}) + CONFIG_SCHEMA({mqtt.DOMAIN: {platform: [config]}}) with pytest.raises(MultipleInvalid): - CONFIG_SCHEMA({"mqtt": {"humidifier": [{"bla": "bla"}]}}) + CONFIG_SCHEMA({mqtt.DOMAIN: {platform: [{"bla": "bla"}]}}) async def test_unload_config_entry(hass, mqtt_mock_entry_with_yaml_config, tmp_path): """Test unloading the config entry.""" domain = humidifier.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry_with_yaml_config, tmp_path, domain, config ) + + +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +async def test_setup_with_legacy_schema(hass, mqtt_mock_entry_with_yaml_config): + """Test a setup with deprecated yaml platform schema.""" + domain = humidifier.DOMAIN + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[domain]) + config["name"] = "test" + assert await async_setup_component(hass, domain, {domain: config}) + await hass.async_block_till_done() + await mqtt_mock_entry_with_yaml_config() + assert hass.states.get(f"{domain}.test") is not None diff --git a/tests/components/mqtt/test_init.py b/tests/components/mqtt/test_init.py index 020fae1732be4..b794d9260ba7f 100644 --- a/tests/components/mqtt/test_init.py +++ b/tests/components/mqtt/test_init.py @@ -281,6 +281,7 @@ async def test_command_template_value(hass): assert cmd_tpl.async_render(None, variables=variables) == "beer" +@patch("homeassistant.components.mqtt.PLATFORMS", [Platform.SELECT]) async def test_command_template_variables(hass, mqtt_mock_entry_with_yaml_config): """Test the rendering of entity variables.""" topic = "test/select" @@ -290,14 +291,15 @@ async def test_command_template_variables(hass, mqtt_mock_entry_with_yaml_config assert await async_setup_component( hass, - "select", + mqtt.DOMAIN, { - "select": { - "platform": "mqtt", - "command_topic": topic, - "name": "Test Select", - "options": ["milk", "beer"], - "command_template": '{"option": "{{ value }}", "entity_id": "{{ entity_id }}", "name": "{{ name }}", "this_object_state": "{{ this.state }}"}', + mqtt.DOMAIN: { + "select": { + "command_topic": topic, + "name": "Test Select", + "options": ["milk", "beer"], + "command_template": '{"option": "{{ value }}", "entity_id": "{{ entity_id }}", "name": "{{ name }}", "this_object_state": "{{ this.state }}"}', + } } }, ) @@ -2087,20 +2089,19 @@ async def test_mqtt_ws_get_device_debug_info( await mqtt_mock_entry_no_yaml_config() config_sensor = { "device": {"identifiers": ["0AFFD2"]}, - "platform": "mqtt", "state_topic": "foobar/sensor", "unique_id": "unique", } config_trigger = { "automation_type": "trigger", "device": {"identifiers": ["0AFFD2"]}, - "platform": "mqtt", "topic": "test-topic1", "type": "foo", "subtype": "bar", } data_sensor = json.dumps(config_sensor) data_trigger = json.dumps(config_trigger) + config_sensor["platform"] = config_trigger["platform"] = mqtt.DOMAIN async_fire_mqtt_message(hass, "homeassistant/sensor/bla/config", data_sensor) async_fire_mqtt_message( @@ -2151,11 +2152,11 @@ async def test_mqtt_ws_get_device_debug_info_binary( await mqtt_mock_entry_no_yaml_config() config = { "device": {"identifiers": ["0AFFD2"]}, - "platform": "mqtt", "topic": "foobar/image", "unique_id": "unique", } data = json.dumps(config) + config["platform"] = mqtt.DOMAIN async_fire_mqtt_message(hass, "homeassistant/camera/bla/config", data) await hass.async_block_till_done() @@ -2397,7 +2398,9 @@ async def test_debug_info_non_mqtt( device_id=device_entry.id, ) - assert await async_setup_component(hass, DOMAIN, {DOMAIN: {"platform": "test"}}) + assert await async_setup_component( + hass, mqtt.DOMAIN, {mqtt.DOMAIN: {DOMAIN: {"platform": "test"}}} + ) debug_info_data = debug_info.info_for_device(hass, device_entry.id) assert len(debug_info_data["entities"]) == 0 @@ -2409,7 +2412,6 @@ async def test_debug_info_wildcard(hass, mqtt_mock_entry_no_yaml_config): await mqtt_mock_entry_no_yaml_config() config = { "device": {"identifiers": ["helloworld"]}, - "platform": "mqtt", "name": "test", "state_topic": "sensor/#", "unique_id": "veryunique", @@ -2456,7 +2458,6 @@ async def test_debug_info_filter_same(hass, mqtt_mock_entry_no_yaml_config): await mqtt_mock_entry_no_yaml_config() config = { "device": {"identifiers": ["helloworld"]}, - "platform": "mqtt", "name": "test", "state_topic": "sensor/#", "unique_id": "veryunique", @@ -2515,7 +2516,6 @@ async def test_debug_info_same_topic(hass, mqtt_mock_entry_no_yaml_config): await mqtt_mock_entry_no_yaml_config() config = { "device": {"identifiers": ["helloworld"]}, - "platform": "mqtt", "name": "test", "state_topic": "sensor/status", "availability_topic": "sensor/status", @@ -2568,7 +2568,6 @@ async def test_debug_info_qos_retain(hass, mqtt_mock_entry_no_yaml_config): await mqtt_mock_entry_no_yaml_config() config = { "device": {"identifiers": ["helloworld"]}, - "platform": "mqtt", "name": "test", "state_topic": "sensor/#", "unique_id": "veryunique", @@ -2708,6 +2707,8 @@ async def async_mqtt_connected(status): assert mqtt_connected_calls[1] is False +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 async def test_one_deprecation_warning_per_platform( hass, mqtt_mock_entry_with_yaml_config, caplog ): @@ -2801,6 +2802,8 @@ async def test_reload_entry_with_new_config(hass, tmp_path): "mqtt": { "light": [{"name": "test_new_modern", "command_topic": "test-topic_new"}] }, + # Test deprecated YAML configuration under the platform key + # Scheduled to be removed in HA core 2022.12 "light": [ { "platform": "mqtt", @@ -2826,6 +2829,8 @@ async def test_disabling_and_enabling_entry(hass, tmp_path, caplog): "mqtt": { "light": [{"name": "test_new_modern", "command_topic": "test-topic_new"}] }, + # Test deprecated YAML configuration under the platform key + # Scheduled to be removed in HA core 2022.12 "light": [ { "platform": "mqtt", diff --git a/tests/components/mqtt/test_legacy_vacuum.py b/tests/components/mqtt/test_legacy_vacuum.py index 224e81781cff2..ffe9183fe4cf3 100644 --- a/tests/components/mqtt/test_legacy_vacuum.py +++ b/tests/components/mqtt/test_legacy_vacuum.py @@ -5,7 +5,7 @@ import pytest -from homeassistant.components import vacuum +from homeassistant.components import mqtt, vacuum from homeassistant.components.mqtt.const import CONF_COMMAND_TOPIC from homeassistant.components.mqtt.vacuum import schema_legacy as mqttvacuum from homeassistant.components.mqtt.vacuum.schema import services_to_strings @@ -66,27 +66,37 @@ from tests.components.vacuum import common DEFAULT_CONFIG = { - CONF_PLATFORM: "mqtt", - CONF_NAME: "mqtttest", - CONF_COMMAND_TOPIC: "vacuum/command", - mqttvacuum.CONF_SEND_COMMAND_TOPIC: "vacuum/send_command", - mqttvacuum.CONF_BATTERY_LEVEL_TOPIC: "vacuum/state", - mqttvacuum.CONF_BATTERY_LEVEL_TEMPLATE: "{{ value_json.battery_level }}", - mqttvacuum.CONF_CHARGING_TOPIC: "vacuum/state", - mqttvacuum.CONF_CHARGING_TEMPLATE: "{{ value_json.charging }}", - mqttvacuum.CONF_CLEANING_TOPIC: "vacuum/state", - mqttvacuum.CONF_CLEANING_TEMPLATE: "{{ value_json.cleaning }}", - mqttvacuum.CONF_DOCKED_TOPIC: "vacuum/state", - mqttvacuum.CONF_DOCKED_TEMPLATE: "{{ value_json.docked }}", - mqttvacuum.CONF_ERROR_TOPIC: "vacuum/state", - mqttvacuum.CONF_ERROR_TEMPLATE: "{{ value_json.error }}", - mqttvacuum.CONF_FAN_SPEED_TOPIC: "vacuum/state", - mqttvacuum.CONF_FAN_SPEED_TEMPLATE: "{{ value_json.fan_speed }}", - mqttvacuum.CONF_SET_FAN_SPEED_TOPIC: "vacuum/set_fan_speed", - mqttvacuum.CONF_FAN_SPEED_LIST: ["min", "medium", "high", "max"], + mqtt.DOMAIN: { + vacuum.DOMAIN: { + CONF_NAME: "mqtttest", + CONF_COMMAND_TOPIC: "vacuum/command", + mqttvacuum.CONF_SEND_COMMAND_TOPIC: "vacuum/send_command", + mqttvacuum.CONF_BATTERY_LEVEL_TOPIC: "vacuum/state", + mqttvacuum.CONF_BATTERY_LEVEL_TEMPLATE: "{{ value_json.battery_level }}", + mqttvacuum.CONF_CHARGING_TOPIC: "vacuum/state", + mqttvacuum.CONF_CHARGING_TEMPLATE: "{{ value_json.charging }}", + mqttvacuum.CONF_CLEANING_TOPIC: "vacuum/state", + mqttvacuum.CONF_CLEANING_TEMPLATE: "{{ value_json.cleaning }}", + mqttvacuum.CONF_DOCKED_TOPIC: "vacuum/state", + mqttvacuum.CONF_DOCKED_TEMPLATE: "{{ value_json.docked }}", + mqttvacuum.CONF_ERROR_TOPIC: "vacuum/state", + mqttvacuum.CONF_ERROR_TEMPLATE: "{{ value_json.error }}", + mqttvacuum.CONF_FAN_SPEED_TOPIC: "vacuum/state", + mqttvacuum.CONF_FAN_SPEED_TEMPLATE: "{{ value_json.fan_speed }}", + mqttvacuum.CONF_SET_FAN_SPEED_TOPIC: "vacuum/set_fan_speed", + mqttvacuum.CONF_FAN_SPEED_LIST: ["min", "medium", "high", "max"], + } + } } -DEFAULT_CONFIG_2 = {vacuum.DOMAIN: {"platform": "mqtt", "name": "test"}} +DEFAULT_CONFIG_2 = {mqtt.DOMAIN: {vacuum.DOMAIN: {"name": "test"}}} + +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +DEFAULT_CONFIG_LEGACY = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) +DEFAULT_CONFIG_LEGACY[vacuum.DOMAIN][CONF_PLATFORM] = mqtt.DOMAIN +DEFAULT_CONFIG_2_LEGACY = deepcopy(DEFAULT_CONFIG_2[mqtt.DOMAIN]) +DEFAULT_CONFIG_2_LEGACY[vacuum.DOMAIN][CONF_PLATFORM] = mqtt.DOMAIN @pytest.fixture(autouse=True) @@ -98,9 +108,7 @@ def vacuum_platform_only(): async def test_default_supported_features(hass, mqtt_mock_entry_with_yaml_config): """Test that the correct supported features.""" - assert await async_setup_component( - hass, vacuum.DOMAIN, {vacuum.DOMAIN: DEFAULT_CONFIG} - ) + assert await async_setup_component(hass, vacuum.DOMAIN, DEFAULT_CONFIG_LEGACY) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() entity = hass.states.get("vacuum.mqtttest") @@ -120,12 +128,14 @@ async def test_default_supported_features(hass, mqtt_mock_entry_with_yaml_config async def test_all_commands(hass, mqtt_mock_entry_with_yaml_config): """Test simple commands to the vacuum.""" - config = deepcopy(DEFAULT_CONFIG) + config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) config[mqttvacuum.CONF_SUPPORTED_FEATURES] = services_to_strings( ALL_SERVICES, SERVICE_TO_STRING ) - assert await async_setup_component(hass, vacuum.DOMAIN, {vacuum.DOMAIN: config}) + assert await async_setup_component( + hass, mqtt.DOMAIN, {mqtt.DOMAIN: {vacuum.DOMAIN: config}} + ) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -202,13 +212,15 @@ async def test_commands_without_supported_features( hass, mqtt_mock_entry_with_yaml_config ): """Test commands which are not supported by the vacuum.""" - config = deepcopy(DEFAULT_CONFIG) + config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) services = mqttvacuum.STRING_TO_SERVICE["status"] config[mqttvacuum.CONF_SUPPORTED_FEATURES] = services_to_strings( services, SERVICE_TO_STRING ) - assert await async_setup_component(hass, vacuum.DOMAIN, {vacuum.DOMAIN: config}) + assert await async_setup_component( + hass, mqtt.DOMAIN, {mqtt.DOMAIN: {vacuum.DOMAIN: config}} + ) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -253,13 +265,15 @@ async def test_attributes_without_supported_features( hass, mqtt_mock_entry_with_yaml_config ): """Test attributes which are not supported by the vacuum.""" - config = deepcopy(DEFAULT_CONFIG) + config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) services = mqttvacuum.STRING_TO_SERVICE["turn_on"] config[mqttvacuum.CONF_SUPPORTED_FEATURES] = services_to_strings( services, SERVICE_TO_STRING ) - assert await async_setup_component(hass, vacuum.DOMAIN, {vacuum.DOMAIN: config}) + assert await async_setup_component( + hass, mqtt.DOMAIN, {mqtt.DOMAIN: {vacuum.DOMAIN: config}} + ) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -281,12 +295,14 @@ async def test_attributes_without_supported_features( async def test_status(hass, mqtt_mock_entry_with_yaml_config): """Test status updates from the vacuum.""" - config = deepcopy(DEFAULT_CONFIG) + config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) config[mqttvacuum.CONF_SUPPORTED_FEATURES] = services_to_strings( ALL_SERVICES, SERVICE_TO_STRING ) - assert await async_setup_component(hass, vacuum.DOMAIN, {vacuum.DOMAIN: config}) + assert await async_setup_component( + hass, mqtt.DOMAIN, {mqtt.DOMAIN: {vacuum.DOMAIN: config}} + ) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -322,12 +338,14 @@ async def test_status(hass, mqtt_mock_entry_with_yaml_config): async def test_status_battery(hass, mqtt_mock_entry_with_yaml_config): """Test status updates from the vacuum.""" - config = deepcopy(DEFAULT_CONFIG) + config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) config[mqttvacuum.CONF_SUPPORTED_FEATURES] = services_to_strings( ALL_SERVICES, SERVICE_TO_STRING ) - assert await async_setup_component(hass, vacuum.DOMAIN, {vacuum.DOMAIN: config}) + assert await async_setup_component( + hass, mqtt.DOMAIN, {mqtt.DOMAIN: {vacuum.DOMAIN: config}} + ) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -341,12 +359,14 @@ async def test_status_battery(hass, mqtt_mock_entry_with_yaml_config): async def test_status_cleaning(hass, mqtt_mock_entry_with_yaml_config): """Test status updates from the vacuum.""" - config = deepcopy(DEFAULT_CONFIG) + config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) config[mqttvacuum.CONF_SUPPORTED_FEATURES] = services_to_strings( ALL_SERVICES, SERVICE_TO_STRING ) - assert await async_setup_component(hass, vacuum.DOMAIN, {vacuum.DOMAIN: config}) + assert await async_setup_component( + hass, mqtt.DOMAIN, {mqtt.DOMAIN: {vacuum.DOMAIN: config}} + ) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -360,12 +380,14 @@ async def test_status_cleaning(hass, mqtt_mock_entry_with_yaml_config): async def test_status_docked(hass, mqtt_mock_entry_with_yaml_config): """Test status updates from the vacuum.""" - config = deepcopy(DEFAULT_CONFIG) + config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) config[mqttvacuum.CONF_SUPPORTED_FEATURES] = services_to_strings( ALL_SERVICES, SERVICE_TO_STRING ) - assert await async_setup_component(hass, vacuum.DOMAIN, {vacuum.DOMAIN: config}) + assert await async_setup_component( + hass, mqtt.DOMAIN, {mqtt.DOMAIN: {vacuum.DOMAIN: config}} + ) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -379,12 +401,14 @@ async def test_status_docked(hass, mqtt_mock_entry_with_yaml_config): async def test_status_charging(hass, mqtt_mock_entry_with_yaml_config): """Test status updates from the vacuum.""" - config = deepcopy(DEFAULT_CONFIG) + config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) config[mqttvacuum.CONF_SUPPORTED_FEATURES] = services_to_strings( ALL_SERVICES, SERVICE_TO_STRING ) - assert await async_setup_component(hass, vacuum.DOMAIN, {vacuum.DOMAIN: config}) + assert await async_setup_component( + hass, mqtt.DOMAIN, {mqtt.DOMAIN: {vacuum.DOMAIN: config}} + ) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -398,12 +422,14 @@ async def test_status_charging(hass, mqtt_mock_entry_with_yaml_config): async def test_status_fan_speed(hass, mqtt_mock_entry_with_yaml_config): """Test status updates from the vacuum.""" - config = deepcopy(DEFAULT_CONFIG) + config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) config[mqttvacuum.CONF_SUPPORTED_FEATURES] = services_to_strings( ALL_SERVICES, SERVICE_TO_STRING ) - assert await async_setup_component(hass, vacuum.DOMAIN, {vacuum.DOMAIN: config}) + assert await async_setup_component( + hass, mqtt.DOMAIN, {mqtt.DOMAIN: {vacuum.DOMAIN: config}} + ) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -417,12 +443,14 @@ async def test_status_fan_speed(hass, mqtt_mock_entry_with_yaml_config): async def test_status_fan_speed_list(hass, mqtt_mock_entry_with_yaml_config): """Test status updates from the vacuum.""" - config = deepcopy(DEFAULT_CONFIG) + config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) config[mqttvacuum.CONF_SUPPORTED_FEATURES] = services_to_strings( ALL_SERVICES, SERVICE_TO_STRING ) - assert await async_setup_component(hass, vacuum.DOMAIN, {vacuum.DOMAIN: config}) + assert await async_setup_component( + hass, mqtt.DOMAIN, {mqtt.DOMAIN: {vacuum.DOMAIN: config}} + ) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -435,13 +463,15 @@ async def test_status_no_fan_speed_list(hass, mqtt_mock_entry_with_yaml_config): If the vacuum doesn't support fan speed, fan speed list should be None. """ - config = deepcopy(DEFAULT_CONFIG) + config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) services = ALL_SERVICES - VacuumEntityFeature.FAN_SPEED config[mqttvacuum.CONF_SUPPORTED_FEATURES] = services_to_strings( services, SERVICE_TO_STRING ) - assert await async_setup_component(hass, vacuum.DOMAIN, {vacuum.DOMAIN: config}) + assert await async_setup_component( + hass, mqtt.DOMAIN, {mqtt.DOMAIN: {vacuum.DOMAIN: config}} + ) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -451,12 +481,14 @@ async def test_status_no_fan_speed_list(hass, mqtt_mock_entry_with_yaml_config): async def test_status_error(hass, mqtt_mock_entry_with_yaml_config): """Test status updates from the vacuum.""" - config = deepcopy(DEFAULT_CONFIG) + config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) config[mqttvacuum.CONF_SUPPORTED_FEATURES] = services_to_strings( ALL_SERVICES, SERVICE_TO_STRING ) - assert await async_setup_component(hass, vacuum.DOMAIN, {vacuum.DOMAIN: config}) + assert await async_setup_component( + hass, mqtt.DOMAIN, {mqtt.DOMAIN: {vacuum.DOMAIN: config}} + ) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -477,7 +509,7 @@ async def test_status_error(hass, mqtt_mock_entry_with_yaml_config): async def test_battery_template(hass, mqtt_mock_entry_with_yaml_config): """Test that you can use non-default templates for battery_level.""" - config = deepcopy(DEFAULT_CONFIG) + config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) config.update( { mqttvacuum.CONF_SUPPORTED_FEATURES: services_to_strings( @@ -488,7 +520,9 @@ async def test_battery_template(hass, mqtt_mock_entry_with_yaml_config): } ) - assert await async_setup_component(hass, vacuum.DOMAIN, {vacuum.DOMAIN: config}) + assert await async_setup_component( + hass, mqtt.DOMAIN, {mqtt.DOMAIN: {vacuum.DOMAIN: config}} + ) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -500,12 +534,14 @@ async def test_battery_template(hass, mqtt_mock_entry_with_yaml_config): async def test_status_invalid_json(hass, mqtt_mock_entry_with_yaml_config): """Test to make sure nothing breaks if the vacuum sends bad JSON.""" - config = deepcopy(DEFAULT_CONFIG) + config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) config[mqttvacuum.CONF_SUPPORTED_FEATURES] = services_to_strings( ALL_SERVICES, SERVICE_TO_STRING ) - assert await async_setup_component(hass, vacuum.DOMAIN, {vacuum.DOMAIN: config}) + assert await async_setup_component( + hass, mqtt.DOMAIN, {mqtt.DOMAIN: {vacuum.DOMAIN: config}} + ) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -515,82 +551,64 @@ async def test_status_invalid_json(hass, mqtt_mock_entry_with_yaml_config): assert state.attributes.get(ATTR_STATUS) == "Stopped" -async def test_missing_battery_template(hass, mqtt_mock_entry_no_yaml_config): +async def test_missing_battery_template(hass): """Test to make sure missing template is not allowed.""" - config = deepcopy(DEFAULT_CONFIG) + config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) config.pop(mqttvacuum.CONF_BATTERY_LEVEL_TEMPLATE) - assert await async_setup_component(hass, vacuum.DOMAIN, {vacuum.DOMAIN: config}) - await hass.async_block_till_done() - await mqtt_mock_entry_no_yaml_config() - - state = hass.states.get("vacuum.mqtttest") - assert state is None + assert not await async_setup_component( + hass, mqtt.DOMAIN, {mqtt.DOMAIN: {vacuum.DOMAIN: config}} + ) -async def test_missing_charging_template(hass, mqtt_mock_entry_no_yaml_config): +async def test_missing_charging_template(hass): """Test to make sure missing template is not allowed.""" - config = deepcopy(DEFAULT_CONFIG) + config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) config.pop(mqttvacuum.CONF_CHARGING_TEMPLATE) - assert await async_setup_component(hass, vacuum.DOMAIN, {vacuum.DOMAIN: config}) - await hass.async_block_till_done() - await mqtt_mock_entry_no_yaml_config() - - state = hass.states.get("vacuum.mqtttest") - assert state is None + assert not await async_setup_component( + hass, mqtt.DOMAIN, {mqtt.DOMAIN: {vacuum.DOMAIN: config}} + ) -async def test_missing_cleaning_template(hass, mqtt_mock_entry_no_yaml_config): +async def test_missing_cleaning_template(hass): """Test to make sure missing template is not allowed.""" - config = deepcopy(DEFAULT_CONFIG) + config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) config.pop(mqttvacuum.CONF_CLEANING_TEMPLATE) - assert await async_setup_component(hass, vacuum.DOMAIN, {vacuum.DOMAIN: config}) - await hass.async_block_till_done() - await mqtt_mock_entry_no_yaml_config() - - state = hass.states.get("vacuum.mqtttest") - assert state is None + assert not await async_setup_component( + hass, mqtt.DOMAIN, {mqtt.DOMAIN: {vacuum.DOMAIN: config}} + ) -async def test_missing_docked_template(hass, mqtt_mock_entry_no_yaml_config): +async def test_missing_docked_template(hass): """Test to make sure missing template is not allowed.""" - config = deepcopy(DEFAULT_CONFIG) + config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) config.pop(mqttvacuum.CONF_DOCKED_TEMPLATE) - assert await async_setup_component(hass, vacuum.DOMAIN, {vacuum.DOMAIN: config}) - await hass.async_block_till_done() - await mqtt_mock_entry_no_yaml_config() - - state = hass.states.get("vacuum.mqtttest") - assert state is None + assert not await async_setup_component( + hass, mqtt.DOMAIN, {mqtt.DOMAIN: {vacuum.DOMAIN: config}} + ) -async def test_missing_error_template(hass, mqtt_mock_entry_no_yaml_config): +async def test_missing_error_template(hass): """Test to make sure missing template is not allowed.""" - config = deepcopy(DEFAULT_CONFIG) + config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) config.pop(mqttvacuum.CONF_ERROR_TEMPLATE) - assert await async_setup_component(hass, vacuum.DOMAIN, {vacuum.DOMAIN: config}) - await hass.async_block_till_done() - await mqtt_mock_entry_no_yaml_config() - - state = hass.states.get("vacuum.mqtttest") - assert state is None + assert not await async_setup_component( + hass, mqtt.DOMAIN, {mqtt.DOMAIN: {vacuum.DOMAIN: config}} + ) -async def test_missing_fan_speed_template(hass, mqtt_mock_entry_no_yaml_config): +async def test_missing_fan_speed_template(hass): """Test to make sure missing template is not allowed.""" - config = deepcopy(DEFAULT_CONFIG) + config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) config.pop(mqttvacuum.CONF_FAN_SPEED_TEMPLATE) - assert await async_setup_component(hass, vacuum.DOMAIN, {vacuum.DOMAIN: config}) - await hass.async_block_till_done() - await mqtt_mock_entry_no_yaml_config() - - state = hass.states.get("vacuum.mqtttest") - assert state is None + assert not await async_setup_component( + hass, mqtt.DOMAIN, {mqtt.DOMAIN: {vacuum.DOMAIN: config}} + ) async def test_availability_when_connection_lost( @@ -598,28 +616,28 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 + hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 + hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY ) async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by default payload with defined topic.""" await help_test_default_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 + hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY ) async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by custom payload with defined topic.""" await help_test_custom_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 + hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY ) @@ -628,7 +646,7 @@ async def test_setting_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 + hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY ) @@ -640,7 +658,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, - DEFAULT_CONFIG_2, + DEFAULT_CONFIG_2_LEGACY, MQTT_LEGACY_VACUUM_ATTRIBUTES_BLOCKED, ) @@ -648,7 +666,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_with_template( - hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 + hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY ) @@ -657,7 +675,11 @@ async def test_update_with_json_attrs_not_dict( ): """Test attributes get extracted from a JSON result.""" await help_test_update_with_json_attrs_not_dict( - hass, mqtt_mock_entry_with_yaml_config, caplog, vacuum.DOMAIN, DEFAULT_CONFIG_2 + hass, + mqtt_mock_entry_with_yaml_config, + caplog, + vacuum.DOMAIN, + DEFAULT_CONFIG_2_LEGACY, ) @@ -666,14 +688,22 @@ async def test_update_with_json_attrs_bad_JSON( ): """Test attributes get extracted from a JSON result.""" await help_test_update_with_json_attrs_bad_JSON( - hass, mqtt_mock_entry_with_yaml_config, caplog, vacuum.DOMAIN, DEFAULT_CONFIG_2 + hass, + mqtt_mock_entry_with_yaml_config, + caplog, + vacuum.DOMAIN, + DEFAULT_CONFIG_2_LEGACY, ) async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test update of discovered MQTTAttributes.""" await help_test_discovery_update_attr( - hass, mqtt_mock_entry_no_yaml_config, caplog, vacuum.DOMAIN, DEFAULT_CONFIG_2 + hass, + mqtt_mock_entry_no_yaml_config, + caplog, + vacuum.DOMAIN, + DEFAULT_CONFIG_2_LEGACY, ) @@ -702,7 +732,7 @@ async def test_unique_id(hass, mqtt_mock_entry_with_yaml_config): async def test_discovery_removal_vacuum(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test removal of discovered vacuum.""" - data = json.dumps(DEFAULT_CONFIG_2[vacuum.DOMAIN]) + data = json.dumps(DEFAULT_CONFIG_2_LEGACY[vacuum.DOMAIN]) await help_test_discovery_removal( hass, mqtt_mock_entry_no_yaml_config, caplog, vacuum.DOMAIN, data ) @@ -748,28 +778,28 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT vacuum device registry integration.""" await help_test_entity_device_info_with_connection( - hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 + hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY ) async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT vacuum device registry integration.""" await help_test_entity_device_info_with_identifier( - hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 + hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY ) async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): """Test device registry update.""" await help_test_entity_device_info_update( - hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 + hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY ) async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test device registry remove.""" await help_test_entity_device_info_remove( - hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 + hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY ) @@ -797,7 +827,7 @@ async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_co async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 + hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY ) @@ -874,7 +904,7 @@ async def test_publishing_with_custom_encoding( ): """Test publishing MQTT payload with different encoding.""" domain = vacuum.DOMAIN - config = deepcopy(DEFAULT_CONFIG) + config = deepcopy(DEFAULT_CONFIG_LEGACY[domain]) config["supported_features"] = [ "turn_on", "turn_off", @@ -900,7 +930,7 @@ async def test_publishing_with_custom_encoding( async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = vacuum.DOMAIN - config = DEFAULT_CONFIG + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) @@ -909,7 +939,7 @@ async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_pa async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = vacuum.DOMAIN - config = DEFAULT_CONFIG + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable_late(hass, caplog, tmp_path, domain, config) @@ -944,7 +974,8 @@ async def test_encoding_subscribable_topics( attribute_value, ): """Test handling of incoming encoded payload.""" - config = deepcopy(DEFAULT_CONFIG) + domain = vacuum.DOMAIN + config = deepcopy(DEFAULT_CONFIG_LEGACY[domain]) config[CONF_SUPPORTED_FEATURES] = [ "turn_on", "turn_off", @@ -976,8 +1007,21 @@ async def test_encoding_subscribable_topics( async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = vacuum.DOMAIN - config = deepcopy(DEFAULT_CONFIG) + config = deepcopy(DEFAULT_CONFIG_LEGACY[platform]) config["name"] = "test" del config["platform"] await help_test_setup_manual_entity_from_yaml(hass, platform, config) assert hass.states.get(f"{platform}.test") is not None + + +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +async def test_setup_with_legacy_schema(hass, mqtt_mock_entry_with_yaml_config): + """Test a setup with deprecated yaml platform schema.""" + domain = vacuum.DOMAIN + config = deepcopy(DEFAULT_CONFIG_LEGACY[domain]) + config["name"] = "test" + assert await async_setup_component(hass, domain, {domain: config}) + await hass.async_block_till_done() + await mqtt_mock_entry_with_yaml_config() + assert hass.states.get(f"{domain}.test") is not None From e7a616e8e4585402569434d124af08501941235e Mon Sep 17 00:00:00 2001 From: Jan Bouwhuis Date: Tue, 6 Sep 2022 11:03:02 +0200 Subject: [PATCH 03/23] Refactor MQTT tests to use modern platform schema part 2 (#77525) * Tests light json * Tests light template * Missed test light json * Tests light * Tests lock * Tests number * Tests scene * Tests select * Tests sensor * Tests siren * Tests state vacuuum * Tests switch * Derive DEFAULT_CONFIG_LEGACY from DEFAULT_CONFIG * Suggested comment changes --- tests/components/mqtt/test_light.py | 506 ++++++++-------- tests/components/mqtt/test_light_json.py | 601 ++++++++++--------- tests/components/mqtt/test_light_template.py | 335 ++++++----- tests/components/mqtt/test_lock.py | 306 +++++----- tests/components/mqtt/test_number.py | 255 ++++---- tests/components/mqtt/test_scene.py | 62 +- tests/components/mqtt/test_select.py | 213 ++++--- tests/components/mqtt/test_sensor.py | 419 +++++++------ tests/components/mqtt/test_siren.py | 193 +++--- tests/components/mqtt/test_state_vacuum.py | 135 +++-- tests/components/mqtt/test_switch.py | 171 +++--- 11 files changed, 1782 insertions(+), 1414 deletions(-) diff --git a/tests/components/mqtt/test_light.py b/tests/components/mqtt/test_light.py index e916276cb4a23..b34406f42bc31 100644 --- a/tests/components/mqtt/test_light.py +++ b/tests/components/mqtt/test_light.py @@ -2,169 +2,170 @@ Configuration for RGB Version with brightness: -light: - platform: mqtt - name: "Office Light RGB" - state_topic: "office/rgb1/light/status" - command_topic: "office/rgb1/light/switch" - brightness_state_topic: "office/rgb1/brightness/status" - brightness_command_topic: "office/rgb1/brightness/set" - rgb_state_topic: "office/rgb1/rgb/status" - rgb_command_topic: "office/rgb1/rgb/set" - qos: 0 - payload_on: "on" - payload_off: "off" +mqtt: + light: + - name: "Office Light RGB" + state_topic: "office/rgb1/light/status" + command_topic: "office/rgb1/light/switch" + brightness_state_topic: "office/rgb1/brightness/status" + brightness_command_topic: "office/rgb1/brightness/set" + rgb_state_topic: "office/rgb1/rgb/status" + rgb_command_topic: "office/rgb1/rgb/set" + qos: 0 + payload_on: "on" + payload_off: "off" Configuration for XY Version with brightness: -light: - platform: mqtt - name: "Office Light XY" - state_topic: "office/xy1/light/status" - command_topic: "office/xy1/light/switch" - brightness_state_topic: "office/xy1/brightness/status" - brightness_command_topic: "office/xy1/brightness/set" - xy_state_topic: "office/xy1/xy/status" - xy_command_topic: "office/xy1/xy/set" - qos: 0 - payload_on: "on" - payload_off: "off" +mqtt: + light: + - platform: mqtt + name: "Office Light XY" + state_topic: "office/xy1/light/status" + command_topic: "office/xy1/light/switch" + brightness_state_topic: "office/xy1/brightness/status" + brightness_command_topic: "office/xy1/brightness/set" + xy_state_topic: "office/xy1/xy/status" + xy_command_topic: "office/xy1/xy/set" + qos: 0 + payload_on: "on" + payload_off: "off" config without RGB: -light: - platform: mqtt - name: "Office Light" - state_topic: "office/rgb1/light/status" - command_topic: "office/rgb1/light/switch" - brightness_state_topic: "office/rgb1/brightness/status" - brightness_command_topic: "office/rgb1/brightness/set" - qos: 0 - payload_on: "on" - payload_off: "off" +mqtt: + light: + - name: "Office Light" + state_topic: "office/rgb1/light/status" + command_topic: "office/rgb1/light/switch" + brightness_state_topic: "office/rgb1/brightness/status" + brightness_command_topic: "office/rgb1/brightness/set" + qos: 0 + payload_on: "on" + payload_off: "off" config without RGB and brightness: -light: - platform: mqtt - name: "Office Light" - state_topic: "office/rgb1/light/status" - command_topic: "office/rgb1/light/switch" - qos: 0 - payload_on: "on" - payload_off: "off" +mqtt: + light: + - name: "Office Light" + state_topic: "office/rgb1/light/status" + command_topic: "office/rgb1/light/switch" + qos: 0 + payload_on: "on" + payload_off: "off" config for RGB Version with brightness and scale: -light: - platform: mqtt - name: "Office Light RGB" - state_topic: "office/rgb1/light/status" - command_topic: "office/rgb1/light/switch" - brightness_state_topic: "office/rgb1/brightness/status" - brightness_command_topic: "office/rgb1/brightness/set" - brightness_scale: 99 - rgb_state_topic: "office/rgb1/rgb/status" - rgb_command_topic: "office/rgb1/rgb/set" - rgb_scale: 99 - qos: 0 - payload_on: "on" - payload_off: "off" +mqtt: + light: + - name: "Office Light RGB" + state_topic: "office/rgb1/light/status" + command_topic: "office/rgb1/light/switch" + brightness_state_topic: "office/rgb1/brightness/status" + brightness_command_topic: "office/rgb1/brightness/set" + brightness_scale: 99 + rgb_state_topic: "office/rgb1/rgb/status" + rgb_command_topic: "office/rgb1/rgb/set" + rgb_scale: 99 + qos: 0 + payload_on: "on" + payload_off: "off" config with brightness and color temp -light: - platform: mqtt - name: "Office Light Color Temp" - state_topic: "office/rgb1/light/status" - command_topic: "office/rgb1/light/switch" - brightness_state_topic: "office/rgb1/brightness/status" - brightness_command_topic: "office/rgb1/brightness/set" - brightness_scale: 99 - color_temp_state_topic: "office/rgb1/color_temp/status" - color_temp_command_topic: "office/rgb1/color_temp/set" - qos: 0 - payload_on: "on" - payload_off: "off" +mqtt: + light: + - name: "Office Light Color Temp" + state_topic: "office/rgb1/light/status" + command_topic: "office/rgb1/light/switch" + brightness_state_topic: "office/rgb1/brightness/status" + brightness_command_topic: "office/rgb1/brightness/set" + brightness_scale: 99 + color_temp_state_topic: "office/rgb1/color_temp/status" + color_temp_command_topic: "office/rgb1/color_temp/set" + qos: 0 + payload_on: "on" + payload_off: "off" config with brightness and effect -light: - platform: mqtt - name: "Office Light Color Temp" - state_topic: "office/rgb1/light/status" - command_topic: "office/rgb1/light/switch" - brightness_state_topic: "office/rgb1/brightness/status" - brightness_command_topic: "office/rgb1/brightness/set" - brightness_scale: 99 - effect_state_topic: "office/rgb1/effect/status" - effect_command_topic: "office/rgb1/effect/set" - effect_list: - - rainbow - - colorloop - qos: 0 - payload_on: "on" - payload_off: "off" +mqtt: + light: + - name: "Office Light Color Temp" + state_topic: "office/rgb1/light/status" + command_topic: "office/rgb1/light/switch" + brightness_state_topic: "office/rgb1/brightness/status" + brightness_command_topic: "office/rgb1/brightness/set" + brightness_scale: 99 + effect_state_topic: "office/rgb1/effect/status" + effect_command_topic: "office/rgb1/effect/set" + effect_list: + - rainbow + - colorloop + qos: 0 + payload_on: "on" + payload_off: "off" config for RGB Version with RGB command template: -light: - platform: mqtt - name: "Office Light RGB" - state_topic: "office/rgb1/light/status" - command_topic: "office/rgb1/light/switch" - rgb_state_topic: "office/rgb1/rgb/status" - rgb_command_topic: "office/rgb1/rgb/set" - rgb_command_template: "{{ '#%02x%02x%02x' | format(red, green, blue)}}" - qos: 0 - payload_on: "on" - payload_off: "off" +mqtt: + light: + - name: "Office Light RGB" + state_topic: "office/rgb1/light/status" + command_topic: "office/rgb1/light/switch" + rgb_state_topic: "office/rgb1/rgb/status" + rgb_command_topic: "office/rgb1/rgb/set" + rgb_command_template: "{{ '#%02x%02x%02x' | format(red, green, blue)}}" + qos: 0 + payload_on: "on" + payload_off: "off" Configuration for HS Version with brightness: -light: - platform: mqtt - name: "Office Light HS" - state_topic: "office/hs1/light/status" - command_topic: "office/hs1/light/switch" - brightness_state_topic: "office/hs1/brightness/status" - brightness_command_topic: "office/hs1/brightness/set" - hs_state_topic: "office/hs1/hs/status" - hs_command_topic: "office/hs1/hs/set" - qos: 0 - payload_on: "on" - payload_off: "off" +mqtt: + light: + - name: "Office Light HS" + state_topic: "office/hs1/light/status" + command_topic: "office/hs1/light/switch" + brightness_state_topic: "office/hs1/brightness/status" + brightness_command_topic: "office/hs1/brightness/set" + hs_state_topic: "office/hs1/hs/status" + hs_command_topic: "office/hs1/hs/set" + qos: 0 + payload_on: "on" + payload_off: "off" Configuration with brightness command template: -light: - platform: mqtt - name: "Office Light" - state_topic: "office/rgb1/light/status" - command_topic: "office/rgb1/light/switch" - brightness_state_topic: "office/rgb1/brightness/status" - brightness_command_topic: "office/rgb1/brightness/set" - brightness_command_template: '{ "brightness": "{{ value }}" }' - qos: 0 - payload_on: "on" - payload_off: "off" +mqtt: + light: + - name: "Office Light" + state_topic: "office/rgb1/light/status" + command_topic: "office/rgb1/light/switch" + brightness_state_topic: "office/rgb1/brightness/status" + brightness_command_topic: "office/rgb1/brightness/set" + brightness_command_template: '{ "brightness": "{{ value }}" }' + qos: 0 + payload_on: "on" + payload_off: "off" Configuration with effect command template: -light: - platform: mqtt - name: "Office Light Color Temp" - state_topic: "office/rgb1/light/status" - command_topic: "office/rgb1/light/switch" - effect_state_topic: "office/rgb1/effect/status" - effect_command_topic: "office/rgb1/effect/set" - effect_command_template: '{ "effect": "{{ value }}" }' - effect_list: - - rainbow - - colorloop - qos: 0 - payload_on: "on" - payload_off: "off" +mqtt: + light: + - name: "Office Light Color Temp" + state_topic: "office/rgb1/light/status" + command_topic: "office/rgb1/light/switch" + effect_state_topic: "office/rgb1/effect/status" + effect_command_topic: "office/rgb1/effect/set" + effect_command_template: '{ "effect": "{{ value }}" }' + effect_list: + - rainbow + - colorloop + qos: 0 + payload_on: "on" + payload_off: "off" """ import copy @@ -172,7 +173,7 @@ import pytest -from homeassistant.components import light +from homeassistant.components import light, mqtt from homeassistant.components.mqtt.light.schema_basic import ( CONF_BRIGHTNESS_COMMAND_TOPIC, CONF_COLOR_TEMP_COMMAND_TOPIC, @@ -226,17 +227,18 @@ help_test_update_with_json_attrs_not_dict, ) -from tests.common import ( - assert_setup_component, - async_fire_mqtt_message, - mock_restore_cache, -) +from tests.common import async_fire_mqtt_message, mock_restore_cache from tests.components.light import common DEFAULT_CONFIG = { - light.DOMAIN: {"platform": "mqtt", "name": "test", "command_topic": "test-topic"} + mqtt.DOMAIN: {light.DOMAIN: {"name": "test", "command_topic": "test-topic"}} } +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +DEFAULT_CONFIG_LEGACY = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) +DEFAULT_CONFIG_LEGACY[light.DOMAIN]["platform"] = mqtt.DOMAIN + @pytest.fixture(autouse=True) def light_platform_only(): @@ -245,14 +247,15 @@ def light_platform_only(): yield -async def test_fail_setup_if_no_command_topic(hass, mqtt_mock_entry_no_yaml_config): +async def test_fail_setup_if_no_command_topic(hass, caplog): """Test if command fails with command topic.""" - assert await async_setup_component( - hass, light.DOMAIN, {light.DOMAIN: {"platform": "mqtt", "name": "test"}} + assert not await async_setup_component( + hass, mqtt.DOMAIN, {mqtt.DOMAIN: {light.DOMAIN: {"name": "test"}}} + ) + assert ( + "Invalid config for [mqtt]: required key not provided @ data['mqtt']['light'][0]['command_topic']. Got None." + in caplog.text ) - await hass.async_block_till_done() - await mqtt_mock_entry_no_yaml_config() - assert hass.states.get("light.test") is None async def test_no_color_brightness_color_temp_hs_white_xy_if_no_topics( @@ -261,13 +264,14 @@ async def test_no_color_brightness_color_temp_hs_white_xy_if_no_topics( """Test if there is no color and brightness if no topic.""" assert await async_setup_component( hass, - light.DOMAIN, + mqtt.DOMAIN, { - light.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "test_light_rgb/status", - "command_topic": "test_light_rgb/set", + mqtt.DOMAIN: { + light.DOMAIN: { + "name": "test", + "state_topic": "test_light_rgb/status", + "command_topic": "test_light_rgb/set", + } } }, ) @@ -317,7 +321,6 @@ async def test_controlling_state_via_topic(hass, mqtt_mock_entry_with_yaml_confi """Test the controlling of the state via topic.""" config = { light.DOMAIN: { - "platform": "mqtt", "name": "test", "state_topic": "test_light_rgb/status", "command_topic": "test_light_rgb/set", @@ -344,7 +347,7 @@ async def test_controlling_state_via_topic(hass, mqtt_mock_entry_with_yaml_confi } color_modes = ["color_temp", "hs", "rgb", "rgbw", "rgbww", "xy"] - assert await async_setup_component(hass, light.DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -437,7 +440,6 @@ async def test_invalid_state_via_topic(hass, mqtt_mock_entry_with_yaml_config, c """Test handling of empty data via topic.""" config = { light.DOMAIN: { - "platform": "mqtt", "name": "test", "state_topic": "test_light_rgb/status", "command_topic": "test_light_rgb/set", @@ -464,7 +466,7 @@ async def test_invalid_state_via_topic(hass, mqtt_mock_entry_with_yaml_config, c } } - assert await async_setup_component(hass, light.DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -570,13 +572,12 @@ async def test_invalid_state_via_topic(hass, mqtt_mock_entry_with_yaml_config, c async def test_brightness_controlling_scale(hass, mqtt_mock_entry_with_yaml_config): """Test the brightness controlling scale.""" - with assert_setup_component(1, light.DOMAIN): - assert await async_setup_component( - hass, - light.DOMAIN, - { + assert await async_setup_component( + hass, + mqtt.DOMAIN, + { + mqtt.DOMAIN: { light.DOMAIN: { - "platform": "mqtt", "name": "test", "state_topic": "test_scale/status", "command_topic": "test_scale/set", @@ -587,10 +588,11 @@ async def test_brightness_controlling_scale(hass, mqtt_mock_entry_with_yaml_conf "payload_on": "on", "payload_off": "off", } - }, - ) - await hass.async_block_till_done() - await mqtt_mock_entry_with_yaml_config() + } + }, + ) + await hass.async_block_till_done() + await mqtt_mock_entry_with_yaml_config() state = hass.states.get("light.test") assert state.state == STATE_UNKNOWN @@ -620,13 +622,12 @@ async def test_brightness_from_rgb_controlling_scale( hass, mqtt_mock_entry_with_yaml_config ): """Test the brightness controlling scale.""" - with assert_setup_component(1, light.DOMAIN): - assert await async_setup_component( - hass, - light.DOMAIN, - { + assert await async_setup_component( + hass, + mqtt.DOMAIN, + { + mqtt.DOMAIN: { light.DOMAIN: { - "platform": "mqtt", "name": "test", "state_topic": "test_scale_rgb/status", "command_topic": "test_scale_rgb/set", @@ -636,10 +637,11 @@ async def test_brightness_from_rgb_controlling_scale( "payload_on": "on", "payload_off": "off", } - }, - ) - await hass.async_block_till_done() - await mqtt_mock_entry_with_yaml_config() + } + }, + ) + await hass.async_block_till_done() + await mqtt_mock_entry_with_yaml_config() state = hass.states.get("light.test") assert state.state == STATE_UNKNOWN @@ -664,7 +666,6 @@ async def test_controlling_state_via_topic_with_templates( """Test the setting of the state with a template.""" config = { light.DOMAIN: { - "platform": "mqtt", "name": "test", "state_topic": "test_light_rgb/status", "command_topic": "test_light_rgb/set", @@ -697,7 +698,7 @@ async def test_controlling_state_via_topic_with_templates( } color_modes = ["color_temp", "hs", "rgb", "rgbw", "rgbww", "xy"] - assert await async_setup_component(hass, light.DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -767,7 +768,6 @@ async def test_sending_mqtt_commands_and_optimistic( """Test the sending of command in optimistic mode.""" config = { light.DOMAIN: { - "platform": "mqtt", "name": "test", "command_topic": "test_light_rgb/set", "brightness_command_topic": "test_light_rgb/brightness/set", @@ -798,10 +798,9 @@ async def test_sending_mqtt_commands_and_optimistic( ) mock_restore_cache(hass, (fake_state,)) - with assert_setup_component(1, light.DOMAIN): - assert await async_setup_component(hass, light.DOMAIN, config) - await hass.async_block_till_done() - mqtt_mock = await mqtt_mock_entry_with_yaml_config() + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) + await hass.async_block_till_done() + mqtt_mock = await mqtt_mock_entry_with_yaml_config() state = hass.states.get("light.test") assert state.state == STATE_ON @@ -958,7 +957,6 @@ async def test_sending_mqtt_rgb_command_with_template( """Test the sending of RGB command with template.""" config = { light.DOMAIN: { - "platform": "mqtt", "name": "test", "command_topic": "test_light_rgb/set", "rgb_command_topic": "test_light_rgb/rgb/set", @@ -970,7 +968,7 @@ async def test_sending_mqtt_rgb_command_with_template( } } - assert await async_setup_component(hass, light.DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -998,7 +996,6 @@ async def test_sending_mqtt_rgbw_command_with_template( """Test the sending of RGBW command with template.""" config = { light.DOMAIN: { - "platform": "mqtt", "name": "test", "command_topic": "test_light_rgb/set", "rgbw_command_topic": "test_light_rgb/rgbw/set", @@ -1010,7 +1007,7 @@ async def test_sending_mqtt_rgbw_command_with_template( } } - assert await async_setup_component(hass, light.DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -1038,7 +1035,6 @@ async def test_sending_mqtt_rgbww_command_with_template( """Test the sending of RGBWW command with template.""" config = { light.DOMAIN: { - "platform": "mqtt", "name": "test", "command_topic": "test_light_rgb/set", "rgbww_command_topic": "test_light_rgb/rgbww/set", @@ -1050,7 +1046,7 @@ async def test_sending_mqtt_rgbww_command_with_template( } } - assert await async_setup_component(hass, light.DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -1078,7 +1074,6 @@ async def test_sending_mqtt_color_temp_command_with_template( """Test the sending of Color Temp command with template.""" config = { light.DOMAIN: { - "platform": "mqtt", "name": "test", "command_topic": "test_light_color_temp/set", "color_temp_command_topic": "test_light_color_temp/color_temp/set", @@ -1089,7 +1084,7 @@ async def test_sending_mqtt_color_temp_command_with_template( } } - assert await async_setup_component(hass, light.DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -1115,7 +1110,6 @@ async def test_on_command_first(hass, mqtt_mock_entry_with_yaml_config): """Test on command being sent before brightness.""" config = { light.DOMAIN: { - "platform": "mqtt", "name": "test", "command_topic": "test_light/set", "brightness_command_topic": "test_light/bright", @@ -1123,7 +1117,7 @@ async def test_on_command_first(hass, mqtt_mock_entry_with_yaml_config): } } - assert await async_setup_component(hass, light.DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -1152,14 +1146,13 @@ async def test_on_command_last(hass, mqtt_mock_entry_with_yaml_config): """Test on command being sent after brightness.""" config = { light.DOMAIN: { - "platform": "mqtt", "name": "test", "command_topic": "test_light/set", "brightness_command_topic": "test_light/bright", } } - assert await async_setup_component(hass, light.DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -1188,7 +1181,6 @@ async def test_on_command_brightness(hass, mqtt_mock_entry_with_yaml_config): """Test on command being sent as only brightness.""" config = { light.DOMAIN: { - "platform": "mqtt", "name": "test", "command_topic": "test_light/set", "brightness_command_topic": "test_light/bright", @@ -1197,7 +1189,7 @@ async def test_on_command_brightness(hass, mqtt_mock_entry_with_yaml_config): } } - assert await async_setup_component(hass, light.DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -1244,7 +1236,6 @@ async def test_on_command_brightness_scaled(hass, mqtt_mock_entry_with_yaml_conf """Test brightness scale.""" config = { light.DOMAIN: { - "platform": "mqtt", "name": "test", "command_topic": "test_light/set", "brightness_command_topic": "test_light/bright", @@ -1254,7 +1245,7 @@ async def test_on_command_brightness_scaled(hass, mqtt_mock_entry_with_yaml_conf } } - assert await async_setup_component(hass, light.DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -1315,14 +1306,13 @@ async def test_on_command_rgb(hass, mqtt_mock_entry_with_yaml_config): """Test on command in RGB brightness mode.""" config = { light.DOMAIN: { - "platform": "mqtt", "name": "test", "command_topic": "test_light/set", "rgb_command_topic": "test_light/rgb", } } - assert await async_setup_component(hass, light.DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -1406,14 +1396,13 @@ async def test_on_command_rgbw(hass, mqtt_mock_entry_with_yaml_config): """Test on command in RGBW brightness mode.""" config = { light.DOMAIN: { - "platform": "mqtt", "name": "test", "command_topic": "test_light/set", "rgbw_command_topic": "test_light/rgbw", } } - assert await async_setup_component(hass, light.DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -1497,14 +1486,13 @@ async def test_on_command_rgbww(hass, mqtt_mock_entry_with_yaml_config): """Test on command in RGBWW brightness mode.""" config = { light.DOMAIN: { - "platform": "mqtt", "name": "test", "command_topic": "test_light/set", "rgbww_command_topic": "test_light/rgbww", } } - assert await async_setup_component(hass, light.DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -1588,7 +1576,6 @@ async def test_on_command_rgb_template(hass, mqtt_mock_entry_with_yaml_config): """Test on command in RGB brightness mode with RGB template.""" config = { light.DOMAIN: { - "platform": "mqtt", "name": "test", "command_topic": "test_light/set", "rgb_command_topic": "test_light/rgb", @@ -1596,7 +1583,7 @@ async def test_on_command_rgb_template(hass, mqtt_mock_entry_with_yaml_config): } } - assert await async_setup_component(hass, light.DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -1626,7 +1613,6 @@ async def test_on_command_rgbw_template(hass, mqtt_mock_entry_with_yaml_config): """Test on command in RGBW brightness mode with RGBW template.""" config = { light.DOMAIN: { - "platform": "mqtt", "name": "test", "command_topic": "test_light/set", "rgbw_command_topic": "test_light/rgbw", @@ -1634,7 +1620,7 @@ async def test_on_command_rgbw_template(hass, mqtt_mock_entry_with_yaml_config): } } - assert await async_setup_component(hass, light.DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -1663,7 +1649,6 @@ async def test_on_command_rgbww_template(hass, mqtt_mock_entry_with_yaml_config) """Test on command in RGBWW brightness mode with RGBWW template.""" config = { light.DOMAIN: { - "platform": "mqtt", "name": "test", "command_topic": "test_light/set", "rgbww_command_topic": "test_light/rgbww", @@ -1671,7 +1656,7 @@ async def test_on_command_rgbww_template(hass, mqtt_mock_entry_with_yaml_config) } } - assert await async_setup_component(hass, light.DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -1701,7 +1686,6 @@ async def test_on_command_white(hass, mqtt_mock_entry_with_yaml_config): """Test sending commands for RGB + white light.""" config = { light.DOMAIN: { - "platform": "mqtt", "name": "test", "command_topic": "tasmota_B94927/cmnd/POWER", "state_value_template": "{{ value_json.POWER }}", @@ -1721,7 +1705,7 @@ async def test_on_command_white(hass, mqtt_mock_entry_with_yaml_config): } color_modes = ["rgb", "white"] - assert await async_setup_component(hass, light.DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -1779,7 +1763,6 @@ async def test_explicit_color_mode(hass, mqtt_mock_entry_with_yaml_config): """Test explicit color mode over mqtt.""" config = { light.DOMAIN: { - "platform": "mqtt", "name": "test", "state_topic": "test_light_rgb/status", "command_topic": "test_light_rgb/set", @@ -1807,7 +1790,7 @@ async def test_explicit_color_mode(hass, mqtt_mock_entry_with_yaml_config): } color_modes = ["color_temp", "hs", "rgb", "rgbw", "rgbww", "xy"] - assert await async_setup_component(hass, light.DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -1928,7 +1911,6 @@ async def test_explicit_color_mode_templated(hass, mqtt_mock_entry_with_yaml_con """Test templated explicit color mode over mqtt.""" config = { light.DOMAIN: { - "platform": "mqtt", "name": "test", "state_topic": "test_light_rgb/status", "command_topic": "test_light_rgb/set", @@ -1947,7 +1929,7 @@ async def test_explicit_color_mode_templated(hass, mqtt_mock_entry_with_yaml_con } color_modes = ["color_temp", "hs"] - assert await async_setup_component(hass, light.DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -2010,7 +1992,6 @@ async def test_white_state_update(hass, mqtt_mock_entry_with_yaml_config): """Test state updates for RGB + white light.""" config = { light.DOMAIN: { - "platform": "mqtt", "name": "test", "state_topic": "tasmota_B94927/tele/STATE", "command_topic": "tasmota_B94927/cmnd/POWER", @@ -2034,7 +2015,7 @@ async def test_white_state_update(hass, mqtt_mock_entry_with_yaml_config): } color_modes = ["rgb", "white"] - assert await async_setup_component(hass, light.DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -2075,7 +2056,6 @@ async def test_effect(hass, mqtt_mock_entry_with_yaml_config): """Test effect.""" config = { light.DOMAIN: { - "platform": "mqtt", "name": "test", "command_topic": "test_light/set", "effect_command_topic": "test_light/effect/set", @@ -2083,7 +2063,7 @@ async def test_effect(hass, mqtt_mock_entry_with_yaml_config): } } - assert await async_setup_component(hass, light.DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -2114,28 +2094,28 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by default payload with defined topic.""" await help_test_default_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by custom payload with defined topic.""" await help_test_custom_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -2144,7 +2124,7 @@ async def test_setting_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -2156,7 +2136,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, MQTT_LIGHT_ATTRIBUTES_BLOCKED, ) @@ -2164,7 +2144,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_with_template( - hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -2173,7 +2153,11 @@ async def test_update_with_json_attrs_not_dict( ): """Test attributes get extracted from a JSON result.""" await help_test_update_with_json_attrs_not_dict( - hass, mqtt_mock_entry_with_yaml_config, caplog, light.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_with_yaml_config, + caplog, + light.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) @@ -2182,14 +2166,22 @@ async def test_update_with_json_attrs_bad_JSON( ): """Test attributes get extracted from a JSON result.""" await help_test_update_with_json_attrs_bad_JSON( - hass, mqtt_mock_entry_with_yaml_config, caplog, light.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_with_yaml_config, + caplog, + light.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test update of discovered MQTTAttributes.""" await help_test_discovery_update_attr( - hass, mqtt_mock_entry_no_yaml_config, caplog, light.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_no_yaml_config, + caplog, + light.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) @@ -2230,6 +2222,8 @@ async def test_discovery_removal_light(hass, mqtt_mock_entry_no_yaml_config, cap ) +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 async def test_discovery_deprecated(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test discovery of mqtt light with deprecated platform option.""" await mqtt_mock_entry_no_yaml_config() @@ -2750,42 +2744,42 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT light device registry integration.""" await help_test_entity_device_info_with_connection( - hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT light device registry integration.""" await help_test_entity_device_info_with_identifier( - hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): """Test device registry update.""" await help_test_entity_device_info_update( - hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test device registry remove.""" await help_test_entity_device_info_remove( - hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_config): """Test MQTT subscriptions are managed when entity_id is updated.""" await help_test_entity_id_update_subscriptions( - hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -2795,7 +2789,7 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, light.SERVICE_TURN_ON, ) @@ -2804,7 +2798,6 @@ async def test_max_mireds(hass, mqtt_mock_entry_with_yaml_config): """Test setting min_mireds and max_mireds.""" config = { light.DOMAIN: { - "platform": "mqtt", "name": "test", "command_topic": "test_max_mireds/set", "color_temp_command_topic": "test_max_mireds/color_temp/set", @@ -2812,7 +2805,7 @@ async def test_max_mireds(hass, mqtt_mock_entry_with_yaml_config): } } - assert await async_setup_component(hass, light.DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -2921,7 +2914,7 @@ async def test_publishing_with_custom_encoding( ): """Test publishing MQTT payload with different encoding.""" domain = light.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG[domain]) + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[domain]) if topic == "effect_command_topic": config["effect_list"] = ["random", "color_loop"] elif topic == "white_command_topic": @@ -2946,7 +2939,7 @@ async def test_publishing_with_custom_encoding( async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = light.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) @@ -2955,7 +2948,7 @@ async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_pa async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = light.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable_late(hass, caplog, tmp_path, domain, config) @@ -3000,7 +2993,7 @@ async def test_encoding_subscribable_topics( init_payload, ): """Test handling of incoming encoded payload.""" - config = copy.deepcopy(DEFAULT_CONFIG[light.DOMAIN]) + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[light.DOMAIN]) config[CONF_EFFECT_COMMAND_TOPIC] = "light/CONF_EFFECT_COMMAND_TOPIC" config[CONF_RGB_COMMAND_TOPIC] = "light/CONF_RGB_COMMAND_TOPIC" config[CONF_BRIGHTNESS_COMMAND_TOPIC] = "light/CONF_BRIGHTNESS_COMMAND_TOPIC" @@ -3043,7 +3036,7 @@ async def test_encoding_subscribable_topics_brightness( init_payload, ): """Test handling of incoming encoded payload for a brightness only light.""" - config = copy.deepcopy(DEFAULT_CONFIG[light.DOMAIN]) + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[light.DOMAIN]) config[CONF_BRIGHTNESS_COMMAND_TOPIC] = "light/CONF_BRIGHTNESS_COMMAND_TOPIC" await help_test_encoding_subscribable_topics( @@ -3066,7 +3059,6 @@ async def test_sending_mqtt_brightness_command_with_template( """Test the sending of Brightness command with template.""" config = { light.DOMAIN: { - "platform": "mqtt", "name": "test", "command_topic": "test_light_brightness/set", "brightness_command_topic": "test_light_brightness/brightness/set", @@ -3077,7 +3069,7 @@ async def test_sending_mqtt_brightness_command_with_template( } } - assert await async_setup_component(hass, light.DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -3105,7 +3097,6 @@ async def test_sending_mqtt_effect_command_with_template( """Test the sending of Effect command with template.""" config = { light.DOMAIN: { - "platform": "mqtt", "name": "test", "command_topic": "test_light_brightness/set", "brightness_command_topic": "test_light_brightness/brightness/set", @@ -3118,7 +3109,7 @@ async def test_sending_mqtt_effect_command_with_template( } } - assert await async_setup_component(hass, light.DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -3147,7 +3138,7 @@ async def test_sending_mqtt_effect_command_with_template( async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = light.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG[platform]) + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) config["name"] = "test" del config["platform"] await help_test_setup_manual_entity_from_yaml(hass, platform, config) @@ -3157,7 +3148,20 @@ async def test_setup_manual_entity_from_yaml(hass): async def test_unload_entry(hass, mqtt_mock_entry_with_yaml_config, tmp_path): """Test unloading the config entry.""" domain = light.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry_with_yaml_config, tmp_path, domain, config ) + + +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +async def test_setup_with_legacy_schema(hass, mqtt_mock_entry_with_yaml_config): + """Test a setup with deprecated yaml platform schema.""" + domain = light.DOMAIN + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[domain]) + config["name"] = "test" + assert await async_setup_component(hass, domain, {domain: config}) + await hass.async_block_till_done() + await mqtt_mock_entry_with_yaml_config() + assert hass.states.get(f"{domain}.test") is not None diff --git a/tests/components/mqtt/test_light_json.py b/tests/components/mqtt/test_light_json.py index 8fac9092e3f5d..e61d4e772865e 100644 --- a/tests/components/mqtt/test_light_json.py +++ b/tests/components/mqtt/test_light_json.py @@ -2,58 +2,63 @@ Configuration with RGB, brightness, color temp, effect, and XY: -light: - platform: mqtt_json - name: mqtt_json_light_1 - state_topic: "home/rgb1" - command_topic: "home/rgb1/set" - brightness: true - color_temp: true - effect: true - rgb: true - xy: true +mqtt: + light: + schema: json + name: mqtt_json_light_1 + state_topic: "home/rgb1" + command_topic: "home/rgb1/set" + brightness: true + color_temp: true + effect: true + rgb: true + xy: true Configuration with RGB, brightness, color temp and effect: -light: - platform: mqtt_json - name: mqtt_json_light_1 - state_topic: "home/rgb1" - command_topic: "home/rgb1/set" - brightness: true - color_temp: true - effect: true - rgb: true +mqtt: + light: + schema: json + name: mqtt_json_light_1 + state_topic: "home/rgb1" + command_topic: "home/rgb1/set" + brightness: true + color_temp: true + effect: true + rgb: true Configuration with RGB, brightness and color temp: -light: - platform: mqtt_json - name: mqtt_json_light_1 - state_topic: "home/rgb1" - command_topic: "home/rgb1/set" - brightness: true - rgb: true - color_temp: true +mqtt: + light: + schema: json + name: mqtt_json_light_1 + state_topic: "home/rgb1" + command_topic: "home/rgb1/set" + brightness: true + rgb: true + color_temp: true Configuration with RGB, brightness: -light: - platform: mqtt_json - name: mqtt_json_light_1 - state_topic: "home/rgb1" - command_topic: "home/rgb1/set" - brightness: true - rgb: true +mqtt: + light: + schema: json + name: mqtt_json_light_1 + state_topic: "home/rgb1" + command_topic: "home/rgb1/set" + brightness: true + rgb: true Config without RGB: -light: - platform: mqtt_json - name: mqtt_json_light_1 - state_topic: "home/rgb1" - command_topic: "home/rgb1/set" - brightness: true +mqtt: + light: + schema: json + name: mqtt_json_light_1 + state_topic: "home/rgb1" + command_topic: "home/rgb1/set" + brightness: true Config without RGB and brightness: @@ -79,7 +84,7 @@ import pytest -from homeassistant.components import light +from homeassistant.components import light, mqtt from homeassistant.components.mqtt.light.schema_basic import ( MQTT_LIGHT_ATTRIBUTES_BLOCKED, ) @@ -128,14 +133,20 @@ from tests.components.light import common DEFAULT_CONFIG = { - light.DOMAIN: { - "platform": "mqtt", - "schema": "json", - "name": "test", - "command_topic": "test-topic", + mqtt.DOMAIN: { + light.DOMAIN: { + "schema": "json", + "name": "test", + "command_topic": "test-topic", + } } } +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +DEFAULT_CONFIG_LEGACY = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) +DEFAULT_CONFIG_LEGACY[light.DOMAIN]["platform"] = mqtt.DOMAIN + @pytest.fixture(autouse=True) def light_platform_only(): @@ -156,22 +167,21 @@ def __eq__(self, other): return json.loads(self.jsondata) == json.loads(other) -async def test_fail_setup_if_no_command_topic(hass, mqtt_mock_entry_no_yaml_config): +async def test_fail_setup_if_no_command_topic(hass, caplog): """Test if setup fails with no command topic.""" - assert await async_setup_component( + assert not await async_setup_component( hass, - light.DOMAIN, - {light.DOMAIN: {"platform": "mqtt", "schema": "json", "name": "test"}}, + mqtt.DOMAIN, + {mqtt.DOMAIN: {light.DOMAIN: {"schema": "json", "name": "test"}}}, + ) + assert ( + "Invalid config for [mqtt]: required key not provided @ data['mqtt']['light'][0]['command_topic']. Got None." + in caplog.text ) - await hass.async_block_till_done() - await mqtt_mock_entry_no_yaml_config() - assert hass.states.get("light.test") is None @pytest.mark.parametrize("deprecated", ("color_temp", "hs", "rgb", "xy")) -async def test_fail_setup_if_color_mode_deprecated( - hass, mqtt_mock_entry_no_yaml_config, deprecated -): +async def test_fail_setup_if_color_mode_deprecated(hass, caplog, deprecated): """Test if setup fails if color mode is combined with deprecated config keys.""" supported_color_modes = ["color_temp", "hs", "rgb", "rgbw", "rgbww", "xy"] @@ -181,27 +191,32 @@ async def test_fail_setup_if_color_mode_deprecated( "color_mode": True, "command_topic": "test_light_rgb/set", "name": "test", - "platform": "mqtt", "schema": "json", "supported_color_modes": supported_color_modes, } } config[light.DOMAIN][deprecated] = True - assert await async_setup_component( + assert not await async_setup_component( hass, - light.DOMAIN, - config, + mqtt.DOMAIN, + {mqtt.DOMAIN: config}, + ) + assert ( + "Invalid config for [mqtt]: color_mode must not be combined with any of" + in caplog.text ) - await hass.async_block_till_done() - await mqtt_mock_entry_no_yaml_config() - assert hass.states.get("light.test") is None @pytest.mark.parametrize( - "supported_color_modes", [["onoff", "rgb"], ["brightness", "rgb"], ["unknown"]] + "supported_color_modes,error", + [ + (["onoff", "rgb"], "Unknown error calling mqtt CONFIG_SCHEMA"), + (["brightness", "rgb"], "Unknown error calling mqtt CONFIG_SCHEMA"), + (["unknown"], "Invalid config for [mqtt]: value must be one of [ - on,{{ brightness|d }},{{ red|d }}-{{ green|d }}-{{ blue|d }} - command_off_template: 'off' - state_template: '{{ value.split(",")[0] }}' - brightness_template: '{{ value.split(",")[1] }}' - color_temp_template: '{{ value.split(",")[2] }}' - red_template: '{{ value.split(",")[4].split("-")[0] }}' - green_template: '{{ value.split(",")[4].split("-")[1] }}' - blue_template: '{{ value.split(",")[4].split("-")[2] }}' +mqtt: + light: + schema: template + name: mqtt_template_light_1 + state_topic: 'home/rgb1' + command_topic: 'home/rgb1/set' + command_on_template: > + on,{{ brightness|d }},{{ red|d }}-{{ green|d }}-{{ blue|d }} + command_off_template: 'off' + state_template: '{{ value.split(",")[0] }}' + brightness_template: '{{ value.split(",")[1] }}' + color_temp_template: '{{ value.split(",")[2] }}' + red_template: '{{ value.split(",")[4].split("-")[0] }}' + green_template: '{{ value.split(",")[4].split("-")[1] }}' + blue_template: '{{ value.split(",")[4].split("-")[2] }}' If your light doesn't support brightness feature, omit `brightness_template`. @@ -28,7 +29,7 @@ import pytest -from homeassistant.components import light +from homeassistant.components import light, mqtt from homeassistant.components.mqtt.light.schema_basic import ( MQTT_LIGHT_ATTRIBUTES_BLOCKED, ) @@ -74,24 +75,26 @@ help_test_update_with_json_attrs_not_dict, ) -from tests.common import ( - assert_setup_component, - async_fire_mqtt_message, - mock_restore_cache, -) +from tests.common import async_fire_mqtt_message, mock_restore_cache from tests.components.light import common DEFAULT_CONFIG = { - light.DOMAIN: { - "platform": "mqtt", - "schema": "template", - "name": "test", - "command_topic": "test-topic", - "command_on_template": "on,{{ transition }}", - "command_off_template": "off,{{ transition|d }}", + mqtt.DOMAIN: { + light.DOMAIN: { + "schema": "template", + "name": "test", + "command_topic": "test-topic", + "command_on_template": "on,{{ transition }}", + "command_off_template": "off,{{ transition|d }}", + } } } +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +DEFAULT_CONFIG_LEGACY = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) +DEFAULT_CONFIG_LEGACY[light.DOMAIN]["platform"] = mqtt.DOMAIN + @pytest.fixture(autouse=True) def light_platform_only(): @@ -103,10 +106,9 @@ def light_platform_only(): @pytest.mark.parametrize( "test_config", [ - ({"platform": "mqtt", "schema": "template", "name": "test"},), + ({"schema": "template", "name": "test"},), ( { - "platform": "mqtt", "schema": "template", "name": "test", "command_topic": "test_topic", @@ -114,7 +116,6 @@ def light_platform_only(): ), ( { - "platform": "mqtt", "schema": "template", "name": "test", "command_topic": "test_topic", @@ -123,7 +124,6 @@ def light_platform_only(): ), ( { - "platform": "mqtt", "schema": "template", "name": "test", "command_topic": "test_topic", @@ -132,36 +132,33 @@ def light_platform_only(): ), ], ) -async def test_setup_fails(hass, mqtt_mock_entry_no_yaml_config, test_config): +async def test_setup_fails(hass, caplog, test_config): """Test that setup fails with missing required configuration items.""" - with assert_setup_component(0, light.DOMAIN) as setup_config: - assert await async_setup_component( - hass, - light.DOMAIN, - {light.DOMAIN: test_config}, - ) - await hass.async_block_till_done() - await mqtt_mock_entry_no_yaml_config() - assert not setup_config[light.DOMAIN] - assert hass.states.get("light.test") is None + assert not await async_setup_component( + hass, + mqtt.DOMAIN, + {mqtt.DOMAIN: {light.DOMAIN: test_config}}, + ) + assert "Invalid config for [mqtt]" in caplog.text async def test_rgb_light(hass, mqtt_mock_entry_with_yaml_config): """Test RGB light flags brightness support.""" assert await async_setup_component( hass, - light.DOMAIN, + mqtt.DOMAIN, { - light.DOMAIN: { - "platform": "mqtt", - "schema": "template", - "name": "test", - "command_topic": "test_light_rgb/set", - "command_on_template": "on", - "command_off_template": "off", - "red_template": '{{ value.split(",")[4].' 'split("-")[0] }}', - "green_template": '{{ value.split(",")[4].' 'split("-")[1] }}', - "blue_template": '{{ value.split(",")[4].' 'split("-")[2] }}', + mqtt.DOMAIN: { + light.DOMAIN: { + "schema": "template", + "name": "test", + "command_topic": "test_light_rgb/set", + "command_on_template": "on", + "command_off_template": "off", + "red_template": '{{ value.split(",")[4].' 'split("-")[0] }}', + "green_template": '{{ value.split(",")[4].' 'split("-")[1] }}', + "blue_template": '{{ value.split(",")[4].' 'split("-")[2] }}', + } } }, ) @@ -181,13 +178,12 @@ async def test_rgb_light(hass, mqtt_mock_entry_with_yaml_config): async def test_state_change_via_topic(hass, mqtt_mock_entry_with_yaml_config): """Test state change via topic.""" - with assert_setup_component(1, light.DOMAIN): - assert await async_setup_component( - hass, - light.DOMAIN, - { + assert await async_setup_component( + hass, + mqtt.DOMAIN, + { + mqtt.DOMAIN: { light.DOMAIN: { - "platform": "mqtt", "schema": "template", "name": "test", "state_topic": "test_light_rgb", @@ -201,10 +197,11 @@ async def test_state_change_via_topic(hass, mqtt_mock_entry_with_yaml_config): "command_off_template": "off", "state_template": '{{ value.split(",")[0] }}', } - }, - ) - await hass.async_block_till_done() - await mqtt_mock_entry_with_yaml_config() + } + }, + ) + await hass.async_block_till_done() + await mqtt_mock_entry_with_yaml_config() state = hass.states.get("light.test") assert state.state == STATE_UNKNOWN @@ -236,13 +233,12 @@ async def test_state_brightness_color_effect_temp_change_via_topic( hass, mqtt_mock_entry_with_yaml_config ): """Test state, bri, color, effect, color temp change.""" - with assert_setup_component(1, light.DOMAIN): - assert await async_setup_component( - hass, - light.DOMAIN, - { + assert await async_setup_component( + hass, + mqtt.DOMAIN, + { + mqtt.DOMAIN: { light.DOMAIN: { - "platform": "mqtt", "schema": "template", "name": "test", "effect_list": ["rainbow", "colorloop"], @@ -264,10 +260,11 @@ async def test_state_brightness_color_effect_temp_change_via_topic( "blue_template": '{{ value.split(",")[3].' 'split("-")[2] }}', "effect_template": '{{ value.split(",")[4] }}', } - }, - ) - await hass.async_block_till_done() - await mqtt_mock_entry_with_yaml_config() + } + }, + ) + await hass.async_block_till_done() + await mqtt_mock_entry_with_yaml_config() state = hass.states.get("light.test") assert state.state == STATE_UNKNOWN @@ -340,13 +337,12 @@ async def test_sending_mqtt_commands_and_optimistic( ) mock_restore_cache(hass, (fake_state,)) - with assert_setup_component(1, light.DOMAIN): - assert await async_setup_component( - hass, - light.DOMAIN, - { + assert await async_setup_component( + hass, + mqtt.DOMAIN, + { + mqtt.DOMAIN: { light.DOMAIN: { - "platform": "mqtt", "schema": "template", "name": "test", "command_topic": "test_light_rgb/set", @@ -369,10 +365,11 @@ async def test_sending_mqtt_commands_and_optimistic( "effect_template": '{{ value.split(",")[4] }}', "qos": 2, } - }, - ) - await hass.async_block_till_done() - mqtt_mock = await mqtt_mock_entry_with_yaml_config() + } + }, + ) + await hass.async_block_till_done() + mqtt_mock = await mqtt_mock_entry_with_yaml_config() state = hass.states.get("light.test") assert state.state == STATE_ON @@ -470,13 +467,12 @@ async def test_sending_mqtt_commands_non_optimistic_brightness_template( hass, mqtt_mock_entry_with_yaml_config ): """Test the sending of command in optimistic mode.""" - with assert_setup_component(1, light.DOMAIN): - assert await async_setup_component( - hass, - light.DOMAIN, - { + assert await async_setup_component( + hass, + mqtt.DOMAIN, + { + mqtt.DOMAIN: { light.DOMAIN: { - "platform": "mqtt", "schema": "template", "name": "test", "effect_list": ["rainbow", "colorloop"], @@ -499,10 +495,11 @@ async def test_sending_mqtt_commands_non_optimistic_brightness_template( "blue_template": '{{ value.split(",")[3].' 'split("-")[2] }}', "effect_template": '{{ value.split(",")[4] }}', } - }, - ) - await hass.async_block_till_done() - mqtt_mock = await mqtt_mock_entry_with_yaml_config() + } + }, + ) + await hass.async_block_till_done() + mqtt_mock = await mqtt_mock_entry_with_yaml_config() state = hass.states.get("light.test") assert state.state == STATE_UNKNOWN @@ -591,13 +588,12 @@ async def test_sending_mqtt_commands_non_optimistic_brightness_template( async def test_effect(hass, mqtt_mock_entry_with_yaml_config): """Test effect sent over MQTT in optimistic mode.""" - with assert_setup_component(1, light.DOMAIN): - assert await async_setup_component( - hass, - light.DOMAIN, - { + assert await async_setup_component( + hass, + mqtt.DOMAIN, + { + mqtt.DOMAIN: { light.DOMAIN: { - "platform": "mqtt", "schema": "template", "effect_list": ["rainbow", "colorloop"], "name": "test", @@ -606,10 +602,11 @@ async def test_effect(hass, mqtt_mock_entry_with_yaml_config): "command_off_template": "off", "qos": 0, } - }, - ) - await hass.async_block_till_done() - mqtt_mock = await mqtt_mock_entry_with_yaml_config() + } + }, + ) + await hass.async_block_till_done() + mqtt_mock = await mqtt_mock_entry_with_yaml_config() state = hass.states.get("light.test") assert state.state == STATE_UNKNOWN @@ -644,13 +641,12 @@ async def test_effect(hass, mqtt_mock_entry_with_yaml_config): async def test_flash(hass, mqtt_mock_entry_with_yaml_config): """Test flash sent over MQTT in optimistic mode.""" - with assert_setup_component(1, light.DOMAIN): - assert await async_setup_component( - hass, - light.DOMAIN, - { + assert await async_setup_component( + hass, + mqtt.DOMAIN, + { + mqtt.DOMAIN: { light.DOMAIN: { - "platform": "mqtt", "schema": "template", "name": "test", "command_topic": "test_light_rgb/set", @@ -658,10 +654,11 @@ async def test_flash(hass, mqtt_mock_entry_with_yaml_config): "command_off_template": "off", "qos": 0, } - }, - ) - await hass.async_block_till_done() - mqtt_mock = await mqtt_mock_entry_with_yaml_config() + } + }, + ) + await hass.async_block_till_done() + mqtt_mock = await mqtt_mock_entry_with_yaml_config() state = hass.states.get("light.test") assert state.state == STATE_UNKNOWN @@ -693,13 +690,12 @@ async def test_flash(hass, mqtt_mock_entry_with_yaml_config): async def test_transition(hass, mqtt_mock_entry_with_yaml_config): """Test for transition time being sent when included.""" - with assert_setup_component(1, light.DOMAIN): - assert await async_setup_component( - hass, - light.DOMAIN, - { + assert await async_setup_component( + hass, + mqtt.DOMAIN, + { + mqtt.DOMAIN: { light.DOMAIN: { - "platform": "mqtt", "schema": "template", "name": "test", "command_topic": "test_light_rgb/set", @@ -707,10 +703,11 @@ async def test_transition(hass, mqtt_mock_entry_with_yaml_config): "command_off_template": "off,{{ transition|int|d }}", "qos": 1, } - }, - ) - await hass.async_block_till_done() - mqtt_mock = await mqtt_mock_entry_with_yaml_config() + } + }, + ) + await hass.async_block_till_done() + mqtt_mock = await mqtt_mock_entry_with_yaml_config() state = hass.states.get("light.test") assert state.state == STATE_UNKNOWN @@ -735,13 +732,12 @@ async def test_transition(hass, mqtt_mock_entry_with_yaml_config): async def test_invalid_values(hass, mqtt_mock_entry_with_yaml_config): """Test that invalid values are ignored.""" - with assert_setup_component(1, light.DOMAIN): - assert await async_setup_component( - hass, - light.DOMAIN, - { + assert await async_setup_component( + hass, + mqtt.DOMAIN, + { + mqtt.DOMAIN: { light.DOMAIN: { - "platform": "mqtt", "schema": "template", "name": "test", "effect_list": ["rainbow", "colorloop"], @@ -763,10 +759,11 @@ async def test_invalid_values(hass, mqtt_mock_entry_with_yaml_config): "blue_template": '{{ value.split(",")[3].' 'split("-")[2] }}', "effect_template": '{{ value.split(",")[4] }}', } - }, - ) - await hass.async_block_till_done() - await mqtt_mock_entry_with_yaml_config() + } + }, + ) + await hass.async_block_till_done() + await mqtt_mock_entry_with_yaml_config() state = hass.states.get("light.test") assert state.state == STATE_UNKNOWN @@ -827,28 +824,28 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by default payload with defined topic.""" await help_test_default_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by custom payload with defined topic.""" await help_test_custom_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -857,7 +854,7 @@ async def test_setting_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -869,7 +866,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, MQTT_LIGHT_ATTRIBUTES_BLOCKED, ) @@ -877,7 +874,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_with_template( - hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -886,7 +883,11 @@ async def test_update_with_json_attrs_not_dict( ): """Test attributes get extracted from a JSON result.""" await help_test_update_with_json_attrs_not_dict( - hass, mqtt_mock_entry_with_yaml_config, caplog, light.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_with_yaml_config, + caplog, + light.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) @@ -895,14 +896,22 @@ async def test_update_with_json_attrs_bad_JSON( ): """Test attributes get extracted from a JSON result.""" await help_test_update_with_json_attrs_bad_JSON( - hass, mqtt_mock_entry_with_yaml_config, caplog, light.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_with_yaml_config, + caplog, + light.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test update of discovered MQTTAttributes.""" await help_test_discovery_update_attr( - hass, mqtt_mock_entry_no_yaml_config, caplog, light.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_no_yaml_config, + caplog, + light.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) @@ -1017,42 +1026,42 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT light device registry integration.""" await help_test_entity_device_info_with_connection( - hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT light device registry integration.""" await help_test_entity_device_info_with_identifier( - hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): """Test device registry update.""" await help_test_entity_device_info_update( - hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test device registry remove.""" await help_test_entity_device_info_remove( - hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_config): """Test MQTT subscriptions are managed when entity_id is updated.""" await help_test_entity_id_update_subscriptions( - hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -1082,7 +1091,6 @@ async def test_max_mireds(hass, mqtt_mock_entry_with_yaml_config): """Test setting min_mireds and max_mireds.""" config = { light.DOMAIN: { - "platform": "mqtt", "schema": "template", "name": "test", "command_topic": "test_max_mireds/set", @@ -1093,7 +1101,7 @@ async def test_max_mireds(hass, mqtt_mock_entry_with_yaml_config): } } - assert await async_setup_component(hass, light.DOMAIN, config) + assert await async_setup_component(hass, mqtt.DOMAIN, {mqtt.DOMAIN: config}) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -1139,7 +1147,7 @@ async def test_publishing_with_custom_encoding( ): """Test publishing MQTT payload with different encoding.""" domain = light.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG[domain]) + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[domain]) if topic == "effect_command_topic": config["effect_list"] = ["random", "color_loop"] @@ -1162,7 +1170,7 @@ async def test_publishing_with_custom_encoding( async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = light.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) @@ -1171,7 +1179,7 @@ async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_pa async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = light.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable_late(hass, caplog, tmp_path, domain, config) @@ -1192,7 +1200,7 @@ async def test_encoding_subscribable_topics( init_payload, ): """Test handling of incoming encoded payload.""" - config = copy.deepcopy(DEFAULT_CONFIG[light.DOMAIN]) + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[light.DOMAIN]) config["state_template"] = "{{ value }}" await help_test_encoding_subscribable_topics( hass, @@ -1211,7 +1219,7 @@ async def test_encoding_subscribable_topics( async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = light.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG[platform]) + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) config["name"] = "test" del config["platform"] await help_test_setup_manual_entity_from_yaml(hass, platform, config) @@ -1221,7 +1229,20 @@ async def test_setup_manual_entity_from_yaml(hass): async def test_unload_entry(hass, mqtt_mock_entry_with_yaml_config, tmp_path): """Test unloading the config entry.""" domain = light.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry_with_yaml_config, tmp_path, domain, config ) + + +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +async def test_setup_with_legacy_schema(hass, mqtt_mock_entry_with_yaml_config): + """Test a setup with deprecated yaml platform schema.""" + domain = light.DOMAIN + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[domain]) + config["name"] = "test" + assert await async_setup_component(hass, domain, {domain: config}) + await hass.async_block_till_done() + await mqtt_mock_entry_with_yaml_config() + assert hass.states.get(f"{domain}.test") is not None diff --git a/tests/components/mqtt/test_lock.py b/tests/components/mqtt/test_lock.py index f6dc4a0ed6d80..de97de23a1e17 100644 --- a/tests/components/mqtt/test_lock.py +++ b/tests/components/mqtt/test_lock.py @@ -4,14 +4,14 @@ import pytest +from homeassistant.components import lock, mqtt from homeassistant.components.lock import ( - DOMAIN as LOCK_DOMAIN, SERVICE_LOCK, SERVICE_OPEN, SERVICE_UNLOCK, STATE_LOCKED, STATE_UNLOCKED, - SUPPORT_OPEN, + LockEntityFeature, ) from homeassistant.components.mqtt.lock import MQTT_LOCK_ATTRIBUTES_BLOCKED from homeassistant.const import ( @@ -56,9 +56,14 @@ from tests.common import async_fire_mqtt_message DEFAULT_CONFIG = { - LOCK_DOMAIN: {"platform": "mqtt", "name": "test", "command_topic": "test-topic"} + mqtt.DOMAIN: {lock.DOMAIN: {"name": "test", "command_topic": "test-topic"}} } +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +DEFAULT_CONFIG_LEGACY = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) +DEFAULT_CONFIG_LEGACY[lock.DOMAIN]["platform"] = mqtt.DOMAIN + @pytest.fixture(autouse=True) def lock_platform_only(): @@ -71,17 +76,18 @@ async def test_controlling_state_via_topic(hass, mqtt_mock_entry_with_yaml_confi """Test the controlling state via topic.""" assert await async_setup_component( hass, - LOCK_DOMAIN, + mqtt.DOMAIN, { - LOCK_DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "payload_lock": "LOCK", - "payload_unlock": "UNLOCK", - "state_locked": "LOCKED", - "state_unlocked": "UNLOCKED", + mqtt.DOMAIN: { + lock.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "payload_lock": "LOCK", + "payload_unlock": "UNLOCK", + "state_locked": "LOCKED", + "state_unlocked": "UNLOCKED", + } } }, ) @@ -110,17 +116,18 @@ async def test_controlling_non_default_state_via_topic( """Test the controlling state via topic.""" assert await async_setup_component( hass, - LOCK_DOMAIN, + mqtt.DOMAIN, { - LOCK_DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "payload_lock": "LOCK", - "payload_unlock": "UNLOCK", - "state_locked": "closed", - "state_unlocked": "open", + mqtt.DOMAIN: { + lock.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "payload_lock": "LOCK", + "payload_unlock": "UNLOCK", + "state_locked": "closed", + "state_unlocked": "open", + } } }, ) @@ -148,18 +155,19 @@ async def test_controlling_state_via_topic_and_json_message( """Test the controlling state via topic and JSON message.""" assert await async_setup_component( hass, - LOCK_DOMAIN, + mqtt.DOMAIN, { - LOCK_DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "payload_lock": "LOCK", - "payload_unlock": "UNLOCK", - "state_locked": "LOCKED", - "state_unlocked": "UNLOCKED", - "value_template": "{{ value_json.val }}", + mqtt.DOMAIN: { + lock.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "payload_lock": "LOCK", + "payload_unlock": "UNLOCK", + "state_locked": "LOCKED", + "state_unlocked": "UNLOCKED", + "value_template": "{{ value_json.val }}", + } } }, ) @@ -186,18 +194,19 @@ async def test_controlling_non_default_state_via_topic_and_json_message( """Test the controlling state via topic and JSON message.""" assert await async_setup_component( hass, - LOCK_DOMAIN, + mqtt.DOMAIN, { - LOCK_DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "payload_lock": "LOCK", - "payload_unlock": "UNLOCK", - "state_locked": "closed", - "state_unlocked": "open", - "value_template": "{{ value_json.val }}", + mqtt.DOMAIN: { + lock.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "payload_lock": "LOCK", + "payload_unlock": "UNLOCK", + "state_locked": "closed", + "state_unlocked": "open", + "value_template": "{{ value_json.val }}", + } } }, ) @@ -224,16 +233,17 @@ async def test_sending_mqtt_commands_and_optimistic( """Test optimistic mode without state topic.""" assert await async_setup_component( hass, - LOCK_DOMAIN, + mqtt.DOMAIN, { - LOCK_DOMAIN: { - "platform": "mqtt", - "name": "test", - "command_topic": "command-topic", - "payload_lock": "LOCK", - "payload_unlock": "UNLOCK", - "state_locked": "LOCKED", - "state_unlocked": "UNLOCKED", + mqtt.DOMAIN: { + lock.DOMAIN: { + "name": "test", + "command_topic": "command-topic", + "payload_lock": "LOCK", + "payload_unlock": "UNLOCK", + "state_locked": "LOCKED", + "state_unlocked": "UNLOCKED", + } } }, ) @@ -245,7 +255,7 @@ async def test_sending_mqtt_commands_and_optimistic( assert state.attributes.get(ATTR_ASSUMED_STATE) await hass.services.async_call( - LOCK_DOMAIN, SERVICE_LOCK, {ATTR_ENTITY_ID: "lock.test"}, blocking=True + lock.DOMAIN, SERVICE_LOCK, {ATTR_ENTITY_ID: "lock.test"}, blocking=True ) mqtt_mock.async_publish.assert_called_once_with("command-topic", "LOCK", 0, False) @@ -255,7 +265,7 @@ async def test_sending_mqtt_commands_and_optimistic( assert state.attributes.get(ATTR_ASSUMED_STATE) await hass.services.async_call( - LOCK_DOMAIN, SERVICE_UNLOCK, {ATTR_ENTITY_ID: "lock.test"}, blocking=True + lock.DOMAIN, SERVICE_UNLOCK, {ATTR_ENTITY_ID: "lock.test"}, blocking=True ) mqtt_mock.async_publish.assert_called_once_with("command-topic", "UNLOCK", 0, False) @@ -271,18 +281,19 @@ async def test_sending_mqtt_commands_and_explicit_optimistic( """Test optimistic mode without state topic.""" assert await async_setup_component( hass, - LOCK_DOMAIN, + mqtt.DOMAIN, { - LOCK_DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "payload_lock": "LOCK", - "payload_unlock": "UNLOCK", - "state_locked": "LOCKED", - "state_unlocked": "UNLOCKED", - "optimistic": True, + mqtt.DOMAIN: { + lock.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "payload_lock": "LOCK", + "payload_unlock": "UNLOCK", + "state_locked": "LOCKED", + "state_unlocked": "UNLOCKED", + "optimistic": True, + } } }, ) @@ -294,7 +305,7 @@ async def test_sending_mqtt_commands_and_explicit_optimistic( assert state.attributes.get(ATTR_ASSUMED_STATE) await hass.services.async_call( - LOCK_DOMAIN, SERVICE_LOCK, {ATTR_ENTITY_ID: "lock.test"}, blocking=True + lock.DOMAIN, SERVICE_LOCK, {ATTR_ENTITY_ID: "lock.test"}, blocking=True ) mqtt_mock.async_publish.assert_called_once_with("command-topic", "LOCK", 0, False) @@ -304,7 +315,7 @@ async def test_sending_mqtt_commands_and_explicit_optimistic( assert state.attributes.get(ATTR_ASSUMED_STATE) await hass.services.async_call( - LOCK_DOMAIN, SERVICE_UNLOCK, {ATTR_ENTITY_ID: "lock.test"}, blocking=True + lock.DOMAIN, SERVICE_UNLOCK, {ATTR_ENTITY_ID: "lock.test"}, blocking=True ) mqtt_mock.async_publish.assert_called_once_with("command-topic", "UNLOCK", 0, False) @@ -320,17 +331,18 @@ async def test_sending_mqtt_commands_support_open_and_optimistic( """Test open function of the lock without state topic.""" assert await async_setup_component( hass, - LOCK_DOMAIN, + mqtt.DOMAIN, { - LOCK_DOMAIN: { - "platform": "mqtt", - "name": "test", - "command_topic": "command-topic", - "payload_lock": "LOCK", - "payload_unlock": "UNLOCK", - "payload_open": "OPEN", - "state_locked": "LOCKED", - "state_unlocked": "UNLOCKED", + mqtt.DOMAIN: { + lock.DOMAIN: { + "name": "test", + "command_topic": "command-topic", + "payload_lock": "LOCK", + "payload_unlock": "UNLOCK", + "payload_open": "OPEN", + "state_locked": "LOCKED", + "state_unlocked": "UNLOCKED", + } } }, ) @@ -340,10 +352,10 @@ async def test_sending_mqtt_commands_support_open_and_optimistic( state = hass.states.get("lock.test") assert state.state is STATE_UNLOCKED assert state.attributes.get(ATTR_ASSUMED_STATE) - assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == SUPPORT_OPEN + assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == LockEntityFeature.OPEN await hass.services.async_call( - LOCK_DOMAIN, SERVICE_LOCK, {ATTR_ENTITY_ID: "lock.test"}, blocking=True + lock.DOMAIN, SERVICE_LOCK, {ATTR_ENTITY_ID: "lock.test"}, blocking=True ) mqtt_mock.async_publish.assert_called_once_with("command-topic", "LOCK", 0, False) @@ -353,7 +365,7 @@ async def test_sending_mqtt_commands_support_open_and_optimistic( assert state.attributes.get(ATTR_ASSUMED_STATE) await hass.services.async_call( - LOCK_DOMAIN, SERVICE_UNLOCK, {ATTR_ENTITY_ID: "lock.test"}, blocking=True + lock.DOMAIN, SERVICE_UNLOCK, {ATTR_ENTITY_ID: "lock.test"}, blocking=True ) mqtt_mock.async_publish.assert_called_once_with("command-topic", "UNLOCK", 0, False) @@ -363,7 +375,7 @@ async def test_sending_mqtt_commands_support_open_and_optimistic( assert state.attributes.get(ATTR_ASSUMED_STATE) await hass.services.async_call( - LOCK_DOMAIN, SERVICE_OPEN, {ATTR_ENTITY_ID: "lock.test"}, blocking=True + lock.DOMAIN, SERVICE_OPEN, {ATTR_ENTITY_ID: "lock.test"}, blocking=True ) mqtt_mock.async_publish.assert_called_once_with("command-topic", "OPEN", 0, False) @@ -379,19 +391,20 @@ async def test_sending_mqtt_commands_support_open_and_explicit_optimistic( """Test open function of the lock without state topic.""" assert await async_setup_component( hass, - LOCK_DOMAIN, + mqtt.DOMAIN, { - LOCK_DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "payload_lock": "LOCK", - "payload_unlock": "UNLOCK", - "payload_open": "OPEN", - "state_locked": "LOCKED", - "state_unlocked": "UNLOCKED", - "optimistic": True, + mqtt.DOMAIN: { + lock.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "payload_lock": "LOCK", + "payload_unlock": "UNLOCK", + "payload_open": "OPEN", + "state_locked": "LOCKED", + "state_unlocked": "UNLOCKED", + "optimistic": True, + } } }, ) @@ -401,10 +414,10 @@ async def test_sending_mqtt_commands_support_open_and_explicit_optimistic( state = hass.states.get("lock.test") assert state.state is STATE_UNLOCKED assert state.attributes.get(ATTR_ASSUMED_STATE) - assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == SUPPORT_OPEN + assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == LockEntityFeature.OPEN await hass.services.async_call( - LOCK_DOMAIN, SERVICE_LOCK, {ATTR_ENTITY_ID: "lock.test"}, blocking=True + lock.DOMAIN, SERVICE_LOCK, {ATTR_ENTITY_ID: "lock.test"}, blocking=True ) mqtt_mock.async_publish.assert_called_once_with("command-topic", "LOCK", 0, False) @@ -414,7 +427,7 @@ async def test_sending_mqtt_commands_support_open_and_explicit_optimistic( assert state.attributes.get(ATTR_ASSUMED_STATE) await hass.services.async_call( - LOCK_DOMAIN, SERVICE_UNLOCK, {ATTR_ENTITY_ID: "lock.test"}, blocking=True + lock.DOMAIN, SERVICE_UNLOCK, {ATTR_ENTITY_ID: "lock.test"}, blocking=True ) mqtt_mock.async_publish.assert_called_once_with("command-topic", "UNLOCK", 0, False) @@ -424,7 +437,7 @@ async def test_sending_mqtt_commands_support_open_and_explicit_optimistic( assert state.attributes.get(ATTR_ASSUMED_STATE) await hass.services.async_call( - LOCK_DOMAIN, SERVICE_OPEN, {ATTR_ENTITY_ID: "lock.test"}, blocking=True + lock.DOMAIN, SERVICE_OPEN, {ATTR_ENTITY_ID: "lock.test"}, blocking=True ) mqtt_mock.async_publish.assert_called_once_with("command-topic", "OPEN", 0, False) @@ -439,28 +452,28 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, LOCK_DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, lock.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, LOCK_DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, lock.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by default payload with defined topic.""" await help_test_default_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, LOCK_DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, lock.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by custom payload with defined topic.""" await help_test_custom_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, LOCK_DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, lock.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -469,7 +482,7 @@ async def test_setting_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_with_yaml_config, LOCK_DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, lock.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -480,8 +493,8 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( await help_test_setting_blocked_attribute_via_mqtt_json_message( hass, mqtt_mock_entry_no_yaml_config, - LOCK_DOMAIN, - DEFAULT_CONFIG, + lock.DOMAIN, + DEFAULT_CONFIG_LEGACY, MQTT_LOCK_ATTRIBUTES_BLOCKED, ) @@ -489,7 +502,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_with_template( - hass, mqtt_mock_entry_with_yaml_config, LOCK_DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, lock.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -498,7 +511,11 @@ async def test_update_with_json_attrs_not_dict( ): """Test attributes get extracted from a JSON result.""" await help_test_update_with_json_attrs_not_dict( - hass, mqtt_mock_entry_with_yaml_config, caplog, LOCK_DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_with_yaml_config, + caplog, + lock.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) @@ -507,21 +524,25 @@ async def test_update_with_json_attrs_bad_json( ): """Test attributes get extracted from a JSON result.""" await help_test_update_with_json_attrs_bad_JSON( - hass, mqtt_mock_entry_with_yaml_config, caplog, LOCK_DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_with_yaml_config, + caplog, + lock.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test update of discovered MQTTAttributes.""" await help_test_discovery_update_attr( - hass, mqtt_mock_entry_no_yaml_config, caplog, LOCK_DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, caplog, lock.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_unique_id(hass, mqtt_mock_entry_with_yaml_config): """Test unique id option only creates one lock per unique_id.""" config = { - LOCK_DOMAIN: [ + lock.DOMAIN: [ { "platform": "mqtt", "name": "Test 1", @@ -539,7 +560,7 @@ async def test_unique_id(hass, mqtt_mock_entry_with_yaml_config): ] } await help_test_unique_id( - hass, mqtt_mock_entry_with_yaml_config, LOCK_DOMAIN, config + hass, mqtt_mock_entry_with_yaml_config, lock.DOMAIN, config ) @@ -547,7 +568,7 @@ async def test_discovery_removal_lock(hass, mqtt_mock_entry_no_yaml_config, capl """Test removal of discovered lock.""" data = '{ "name": "test",' ' "command_topic": "test_topic" }' await help_test_discovery_removal( - hass, mqtt_mock_entry_no_yaml_config, caplog, LOCK_DOMAIN, data + hass, mqtt_mock_entry_no_yaml_config, caplog, lock.DOMAIN, data ) @@ -566,7 +587,7 @@ async def test_discovery_update_lock(hass, mqtt_mock_entry_no_yaml_config, caplo "availability_topic": "availability_topic2", } await help_test_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, caplog, LOCK_DOMAIN, config1, config2 + hass, mqtt_mock_entry_no_yaml_config, caplog, lock.DOMAIN, config1, config2 ) @@ -586,7 +607,7 @@ async def test_discovery_update_unchanged_lock( hass, mqtt_mock_entry_no_yaml_config, caplog, - LOCK_DOMAIN, + lock.DOMAIN, data1, discovery_update, ) @@ -598,49 +619,49 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): data1 = '{ "name": "Beer" }' data2 = '{ "name": "Milk",' ' "command_topic": "test_topic" }' await help_test_discovery_broken( - hass, mqtt_mock_entry_no_yaml_config, caplog, LOCK_DOMAIN, data1, data2 + hass, mqtt_mock_entry_no_yaml_config, caplog, lock.DOMAIN, data1, data2 ) async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT lock device registry integration.""" await help_test_entity_device_info_with_connection( - hass, mqtt_mock_entry_no_yaml_config, LOCK_DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, lock.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT lock device registry integration.""" await help_test_entity_device_info_with_identifier( - hass, mqtt_mock_entry_no_yaml_config, LOCK_DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, lock.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): """Test device registry update.""" await help_test_entity_device_info_update( - hass, mqtt_mock_entry_no_yaml_config, LOCK_DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, lock.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test device registry remove.""" await help_test_entity_device_info_remove( - hass, mqtt_mock_entry_no_yaml_config, LOCK_DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, lock.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_config): """Test MQTT subscriptions are managed when entity_id is updated.""" await help_test_entity_id_update_subscriptions( - hass, mqtt_mock_entry_with_yaml_config, LOCK_DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, lock.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, LOCK_DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, lock.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -649,8 +670,8 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): await help_test_entity_debug_info_message( hass, mqtt_mock_entry_no_yaml_config, - LOCK_DOMAIN, - DEFAULT_CONFIG, + lock.DOMAIN, + DEFAULT_CONFIG_LEGACY, SERVICE_LOCK, command_payload="LOCK", ) @@ -679,8 +700,8 @@ async def test_publishing_with_custom_encoding( template, ): """Test publishing MQTT payload with different encoding.""" - domain = LOCK_DOMAIN - config = DEFAULT_CONFIG[domain] + domain = lock.DOMAIN + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_publishing_with_custom_encoding( hass, @@ -698,8 +719,8 @@ async def test_publishing_with_custom_encoding( async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" - domain = LOCK_DOMAIN - config = DEFAULT_CONFIG[domain] + domain = lock.DOMAIN + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) @@ -707,8 +728,8 @@ async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_pa async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" - domain = LOCK_DOMAIN - config = DEFAULT_CONFIG[domain] + domain = lock.DOMAIN + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable_late(hass, caplog, tmp_path, domain, config) @@ -732,8 +753,8 @@ async def test_encoding_subscribable_topics( hass, mqtt_mock_entry_with_yaml_config, caplog, - LOCK_DOMAIN, - DEFAULT_CONFIG[LOCK_DOMAIN], + lock.DOMAIN, + DEFAULT_CONFIG_LEGACY[lock.DOMAIN], topic, value, attribute, @@ -743,8 +764,8 @@ async def test_encoding_subscribable_topics( async def test_setup_manual_entity_from_yaml(hass, caplog, tmp_path): """Test setup manual configured MQTT entity.""" - platform = LOCK_DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG[platform]) + platform = lock.DOMAIN + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) config["name"] = "test" del config["platform"] await help_test_setup_manual_entity_from_yaml(hass, platform, config) @@ -753,8 +774,21 @@ async def test_setup_manual_entity_from_yaml(hass, caplog, tmp_path): async def test_unload_entry(hass, mqtt_mock_entry_with_yaml_config, tmp_path): """Test unloading the config entry.""" - domain = LOCK_DOMAIN - config = DEFAULT_CONFIG[domain] + domain = lock.DOMAIN + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry_with_yaml_config, tmp_path, domain, config ) + + +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +async def test_setup_with_legacy_schema(hass, mqtt_mock_entry_with_yaml_config): + """Test a setup with deprecated yaml platform schema.""" + domain = lock.DOMAIN + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[domain]) + config["name"] = "test" + assert await async_setup_component(hass, domain, {domain: config}) + await hass.async_block_till_done() + await mqtt_mock_entry_with_yaml_config() + assert hass.states.get(f"{domain}.test") is not None diff --git a/tests/components/mqtt/test_number.py b/tests/components/mqtt/test_number.py index 603984cffadb6..69b0473fb9d0e 100644 --- a/tests/components/mqtt/test_number.py +++ b/tests/components/mqtt/test_number.py @@ -66,9 +66,14 @@ from tests.common import async_fire_mqtt_message, mock_restore_cache_with_extra_data DEFAULT_CONFIG = { - number.DOMAIN: {"platform": "mqtt", "name": "test", "command_topic": "test-topic"} + mqtt.DOMAIN: {number.DOMAIN: {"name": "test", "command_topic": "test-topic"}} } +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +DEFAULT_CONFIG_LEGACY = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) +DEFAULT_CONFIG_LEGACY[number.DOMAIN]["platform"] = mqtt.DOMAIN + @pytest.fixture(autouse=True) def number_platform_only(): @@ -82,16 +87,17 @@ async def test_run_number_setup(hass, mqtt_mock_entry_with_yaml_config): topic = "test/number" await async_setup_component( hass, - "number", + mqtt.DOMAIN, { - "number": { - "platform": "mqtt", - "state_topic": topic, - "command_topic": topic, - "name": "Test Number", - "device_class": "temperature", - "unit_of_measurement": TEMP_FAHRENHEIT, - "payload_reset": "reset!", + mqtt.DOMAIN: { + number.DOMAIN: { + "state_topic": topic, + "command_topic": topic, + "name": "Test Number", + "device_class": "temperature", + "unit_of_measurement": TEMP_FAHRENHEIT, + "payload_reset": "reset!", + } } }, ) @@ -131,14 +137,15 @@ async def test_value_template(hass, mqtt_mock_entry_with_yaml_config): topic = "test/number" await async_setup_component( hass, - "number", + mqtt.DOMAIN, { - "number": { - "platform": "mqtt", - "state_topic": topic, - "command_topic": topic, - "name": "Test Number", - "value_template": "{{ value_json.val }}", + mqtt.DOMAIN: { + number.DOMAIN: { + "state_topic": topic, + "command_topic": topic, + "name": "Test Number", + "value_template": "{{ value_json.val }}", + } } }, ) @@ -184,14 +191,15 @@ async def test_restore_native_value(hass, mqtt_mock_entry_with_yaml_config): ) assert await async_setup_component( hass, - number.DOMAIN, + mqtt.DOMAIN, { - "number": { - "platform": "mqtt", - "command_topic": topic, - "device_class": "temperature", - "unit_of_measurement": TEMP_FAHRENHEIT, - "name": "Test Number", + mqtt.DOMAIN: { + number.DOMAIN: { + "command_topic": topic, + "device_class": "temperature", + "unit_of_measurement": TEMP_FAHRENHEIT, + "name": "Test Number", + } } }, ) @@ -220,12 +228,13 @@ async def test_run_number_service_optimistic(hass, mqtt_mock_entry_with_yaml_con ) assert await async_setup_component( hass, - number.DOMAIN, + mqtt.DOMAIN, { - "number": { - "platform": "mqtt", - "command_topic": topic, - "name": "Test Number", + mqtt.DOMAIN: { + number.DOMAIN: { + "command_topic": topic, + "name": "Test Number", + } } }, ) @@ -295,13 +304,14 @@ async def test_run_number_service_optimistic_with_command_template( ) assert await async_setup_component( hass, - number.DOMAIN, + mqtt.DOMAIN, { - "number": { - "platform": "mqtt", - "command_topic": topic, - "name": "Test Number", - "command_template": '{"number": {{ value }} }', + mqtt.DOMAIN: { + number.DOMAIN: { + "command_topic": topic, + "name": "Test Number", + "command_template": '{"number": {{ value }} }', + } } }, ) @@ -361,13 +371,14 @@ async def test_run_number_service(hass, mqtt_mock_entry_with_yaml_config): assert await async_setup_component( hass, - number.DOMAIN, + mqtt.DOMAIN, { - "number": { - "platform": "mqtt", - "command_topic": cmd_topic, - "state_topic": state_topic, - "name": "Test Number", + mqtt.DOMAIN: { + number.DOMAIN: { + "command_topic": cmd_topic, + "state_topic": state_topic, + "name": "Test Number", + } } }, ) @@ -398,14 +409,15 @@ async def test_run_number_service_with_command_template( assert await async_setup_component( hass, - number.DOMAIN, + mqtt.DOMAIN, { - "number": { - "platform": "mqtt", - "command_topic": cmd_topic, - "state_topic": state_topic, - "name": "Test Number", - "command_template": '{"number": {{ value }} }', + mqtt.DOMAIN: { + number.DOMAIN: { + "command_topic": cmd_topic, + "state_topic": state_topic, + "name": "Test Number", + "command_template": '{"number": {{ value }} }', + } } }, ) @@ -434,28 +446,28 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, number.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, number.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, number.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, number.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by default payload with defined topic.""" await help_test_default_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, number.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, number.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by custom payload with defined topic.""" await help_test_custom_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, number.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, number.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -464,7 +476,7 @@ async def test_setting_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_with_yaml_config, number.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, number.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -476,7 +488,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( hass, mqtt_mock_entry_no_yaml_config, number.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, MQTT_NUMBER_ATTRIBUTES_BLOCKED, ) @@ -484,7 +496,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_with_template( - hass, mqtt_mock_entry_with_yaml_config, number.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, number.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -493,7 +505,11 @@ async def test_update_with_json_attrs_not_dict( ): """Test attributes get extracted from a JSON result.""" await help_test_update_with_json_attrs_not_dict( - hass, mqtt_mock_entry_with_yaml_config, caplog, number.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_with_yaml_config, + caplog, + number.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) @@ -502,14 +518,22 @@ async def test_update_with_json_attrs_bad_JSON( ): """Test attributes get extracted from a JSON result.""" await help_test_update_with_json_attrs_bad_JSON( - hass, mqtt_mock_entry_with_yaml_config, caplog, number.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_with_yaml_config, + caplog, + number.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test update of discovered MQTTAttributes.""" await help_test_discovery_update_attr( - hass, mqtt_mock_entry_no_yaml_config, caplog, number.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_no_yaml_config, + caplog, + number.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) @@ -540,7 +564,7 @@ async def test_unique_id(hass, mqtt_mock_entry_with_yaml_config): async def test_discovery_removal_number(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test removal of discovered number.""" - data = json.dumps(DEFAULT_CONFIG[number.DOMAIN]) + data = json.dumps(DEFAULT_CONFIG_LEGACY[number.DOMAIN]) await help_test_discovery_removal( hass, mqtt_mock_entry_no_yaml_config, caplog, number.DOMAIN, data ) @@ -600,42 +624,42 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT number device registry integration.""" await help_test_entity_device_info_with_connection( - hass, mqtt_mock_entry_no_yaml_config, number.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, number.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT number device registry integration.""" await help_test_entity_device_info_with_identifier( - hass, mqtt_mock_entry_no_yaml_config, number.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, number.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): """Test device registry update.""" await help_test_entity_device_info_update( - hass, mqtt_mock_entry_no_yaml_config, number.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, number.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test device registry remove.""" await help_test_entity_device_info_remove( - hass, mqtt_mock_entry_no_yaml_config, number.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, number.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_config): """Test MQTT subscriptions are managed when entity_id is updated.""" await help_test_entity_id_update_subscriptions( - hass, mqtt_mock_entry_with_yaml_config, number.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, number.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, number.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, number.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -645,7 +669,7 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): hass, mqtt_mock_entry_no_yaml_config, number.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, SERVICE_SET_VALUE, service_parameters={ATTR_VALUE: 45}, command_payload="45", @@ -658,16 +682,17 @@ async def test_min_max_step_attributes(hass, mqtt_mock_entry_with_yaml_config): topic = "test/number" await async_setup_component( hass, - "number", + mqtt.DOMAIN, { - "number": { - "platform": "mqtt", - "state_topic": topic, - "command_topic": topic, - "name": "Test Number", - "min": 5, - "max": 110, - "step": 20, + mqtt.DOMAIN: { + number.DOMAIN: { + "state_topic": topic, + "command_topic": topic, + "name": "Test Number", + "min": 5, + "max": 110, + "step": 20, + } } }, ) @@ -680,25 +705,24 @@ async def test_min_max_step_attributes(hass, mqtt_mock_entry_with_yaml_config): assert state.attributes.get(ATTR_STEP) == 20 -async def test_invalid_min_max_attributes(hass, caplog, mqtt_mock_entry_no_yaml_config): +async def test_invalid_min_max_attributes(hass, caplog): """Test invalid min/max attributes.""" topic = "test/number" - await async_setup_component( + assert not await async_setup_component( hass, - "number", + mqtt.DOMAIN, { - "number": { - "platform": "mqtt", - "state_topic": topic, - "command_topic": topic, - "name": "Test Number", - "min": 35, - "max": 10, + mqtt.DOMAIN: { + number.DOMAIN: { + "state_topic": topic, + "command_topic": topic, + "name": "Test Number", + "min": 35, + "max": 10, + } } }, ) - await hass.async_block_till_done() - await mqtt_mock_entry_no_yaml_config() assert f"'{CONF_MAX}' must be > '{CONF_MIN}'" in caplog.text @@ -779,15 +803,16 @@ async def test_mqtt_payload_not_a_number_warning( ): """Test warning for MQTT payload which is not a number.""" topic = "test/number" - await async_setup_component( + assert await async_setup_component( hass, - "number", + mqtt.DOMAIN, { - "number": { - "platform": "mqtt", - "state_topic": topic, - "command_topic": topic, - "name": "Test Number", + mqtt.DOMAIN: { + number.DOMAIN: { + "state_topic": topic, + "command_topic": topic, + "name": "Test Number", + } } }, ) @@ -808,15 +833,16 @@ async def test_mqtt_payload_out_of_range_error( topic = "test/number" await async_setup_component( hass, - "number", + mqtt.DOMAIN, { - "number": { - "platform": "mqtt", - "state_topic": topic, - "command_topic": topic, - "name": "Test Number", - "min": 5, - "max": 110, + mqtt.DOMAIN: { + number.DOMAIN: { + "state_topic": topic, + "command_topic": topic, + "name": "Test Number", + "min": 5, + "max": 110, + } } }, ) @@ -856,7 +882,7 @@ async def test_publishing_with_custom_encoding( ): """Test publishing MQTT payload with different encoding.""" domain = NUMBER_DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_publishing_with_custom_encoding( hass, @@ -875,7 +901,7 @@ async def test_publishing_with_custom_encoding( async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = number.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) @@ -884,7 +910,7 @@ async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_pa async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = number.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable_late(hass, caplog, tmp_path, domain, config) @@ -910,7 +936,7 @@ async def test_encoding_subscribable_topics( mqtt_mock_entry_with_yaml_config, caplog, "number", - DEFAULT_CONFIG["number"], + DEFAULT_CONFIG_LEGACY["number"], topic, value, attribute, @@ -921,7 +947,7 @@ async def test_encoding_subscribable_topics( async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = number.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG[platform]) + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) config["name"] = "test" del config["platform"] await help_test_setup_manual_entity_from_yaml(hass, platform, config) @@ -931,7 +957,20 @@ async def test_setup_manual_entity_from_yaml(hass): async def test_unload_entry(hass, mqtt_mock_entry_with_yaml_config, tmp_path): """Test unloading the config entry.""" domain = number.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry_with_yaml_config, tmp_path, domain, config ) + + +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +async def test_setup_with_legacy_schema(hass, mqtt_mock_entry_with_yaml_config): + """Test a setup with deprecated yaml platform schema.""" + domain = number.DOMAIN + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[domain]) + config["name"] = "test" + assert await async_setup_component(hass, domain, {domain: config}) + await hass.async_block_till_done() + await mqtt_mock_entry_with_yaml_config() + assert hass.states.get(f"{domain}.test") is not None diff --git a/tests/components/mqtt/test_scene.py b/tests/components/mqtt/test_scene.py index d676429bf3e68..a1c1644cc37ac 100644 --- a/tests/components/mqtt/test_scene.py +++ b/tests/components/mqtt/test_scene.py @@ -4,7 +4,7 @@ import pytest -from homeassistant.components import scene +from homeassistant.components import mqtt, scene from homeassistant.const import ATTR_ENTITY_ID, SERVICE_TURN_ON, STATE_UNKNOWN, Platform import homeassistant.core as ha from homeassistant.setup import async_setup_component @@ -28,14 +28,20 @@ from tests.common import mock_restore_cache DEFAULT_CONFIG = { - scene.DOMAIN: { - "platform": "mqtt", - "name": "test", - "command_topic": "test-topic", - "payload_on": "test-payload-on", + mqtt.DOMAIN: { + scene.DOMAIN: { + "name": "test", + "command_topic": "test-topic", + "payload_on": "test-payload-on", + } } } +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +DEFAULT_CONFIG_LEGACY = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) +DEFAULT_CONFIG_LEGACY[scene.DOMAIN]["platform"] = mqtt.DOMAIN + @pytest.fixture(autouse=True) def scene_platform_only(): @@ -51,14 +57,15 @@ async def test_sending_mqtt_commands(hass, mqtt_mock_entry_with_yaml_config): assert await async_setup_component( hass, - scene.DOMAIN, + mqtt.DOMAIN, { - scene.DOMAIN: { - "platform": "mqtt", - "name": "test", - "command_topic": "command-topic", - "payload_on": "beer on", - }, + mqtt.DOMAIN: { + scene.DOMAIN: { + "name": "test", + "command_topic": "command-topic", + "payload_on": "beer on", + }, + } }, ) await hass.async_block_till_done() @@ -80,14 +87,14 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, scene.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, scene.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, scene.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, scene.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -168,8 +175,8 @@ async def test_discovery_removal_scene(hass, mqtt_mock_entry_no_yaml_config, cap async def test_discovery_update_payload(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test update of discovered scene.""" - config1 = copy.deepcopy(DEFAULT_CONFIG[scene.DOMAIN]) - config2 = copy.deepcopy(DEFAULT_CONFIG[scene.DOMAIN]) + config1 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[scene.DOMAIN]) + config2 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[scene.DOMAIN]) config1["name"] = "Beer" config2["name"] = "Milk" config1["payload_on"] = "ON" @@ -216,7 +223,7 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = scene.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) @@ -225,14 +232,14 @@ async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_pa async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = scene.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable_late(hass, caplog, tmp_path, domain, config) async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = scene.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG[platform]) + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) config["name"] = "test" del config["platform"] await help_test_setup_manual_entity_from_yaml(hass, platform, config) @@ -242,7 +249,20 @@ async def test_setup_manual_entity_from_yaml(hass): async def test_unload_entry(hass, mqtt_mock_entry_with_yaml_config, tmp_path): """Test unloading the config entry.""" domain = scene.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry_with_yaml_config, tmp_path, domain, config ) + + +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +async def test_setup_with_legacy_schema(hass, mqtt_mock_entry_with_yaml_config): + """Test a setup with deprecated yaml platform schema.""" + domain = scene.DOMAIN + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[domain]) + config["name"] = "test" + assert await async_setup_component(hass, domain, {domain: config}) + await hass.async_block_till_done() + await mqtt_mock_entry_with_yaml_config() + assert hass.states.get(f"{domain}.test") is not None diff --git a/tests/components/mqtt/test_select.py b/tests/components/mqtt/test_select.py index 085c4d5df0041..c66638a18af96 100644 --- a/tests/components/mqtt/test_select.py +++ b/tests/components/mqtt/test_select.py @@ -5,7 +5,7 @@ import pytest -from homeassistant.components import select +from homeassistant.components import mqtt, select from homeassistant.components.mqtt.select import MQTT_SELECT_ATTRIBUTES_BLOCKED from homeassistant.components.select import ( ATTR_OPTION, @@ -56,14 +56,20 @@ from tests.common import async_fire_mqtt_message, mock_restore_cache DEFAULT_CONFIG = { - select.DOMAIN: { - "platform": "mqtt", - "name": "test", - "command_topic": "test-topic", - "options": ["milk", "beer"], + mqtt.DOMAIN: { + select.DOMAIN: { + "name": "test", + "command_topic": "test-topic", + "options": ["milk", "beer"], + } } } +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +DEFAULT_CONFIG_LEGACY = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) +DEFAULT_CONFIG_LEGACY[select.DOMAIN]["platform"] = mqtt.DOMAIN + @pytest.fixture(autouse=True) def select_platform_only(): @@ -77,14 +83,15 @@ async def test_run_select_setup(hass, mqtt_mock_entry_with_yaml_config): topic = "test/select" await async_setup_component( hass, - "select", + mqtt.DOMAIN, { - "select": { - "platform": "mqtt", - "state_topic": topic, - "command_topic": topic, - "name": "Test Select", - "options": ["milk", "beer"], + mqtt.DOMAIN: { + select.DOMAIN: { + "state_topic": topic, + "command_topic": topic, + "name": "Test Select", + "options": ["milk", "beer"], + } } }, ) @@ -111,15 +118,16 @@ async def test_value_template(hass, mqtt_mock_entry_with_yaml_config): topic = "test/select" await async_setup_component( hass, - "select", + mqtt.DOMAIN, { - "select": { - "platform": "mqtt", - "state_topic": topic, - "command_topic": topic, - "name": "Test Select", - "options": ["milk", "beer"], - "value_template": "{{ value_json.val }}", + mqtt.DOMAIN: { + select.DOMAIN: { + "state_topic": topic, + "command_topic": topic, + "name": "Test Select", + "options": ["milk", "beer"], + "value_template": "{{ value_json.val }}", + } } }, ) @@ -157,13 +165,14 @@ async def test_run_select_service_optimistic(hass, mqtt_mock_entry_with_yaml_con assert await async_setup_component( hass, - select.DOMAIN, + mqtt.DOMAIN, { - "select": { - "platform": "mqtt", - "command_topic": topic, - "name": "Test Select", - "options": ["milk", "beer"], + mqtt.DOMAIN: { + select.DOMAIN: { + "command_topic": topic, + "name": "Test Select", + "options": ["milk", "beer"], + } } }, ) @@ -198,14 +207,15 @@ async def test_run_select_service_optimistic_with_command_template( assert await async_setup_component( hass, - select.DOMAIN, + mqtt.DOMAIN, { - "select": { - "platform": "mqtt", - "command_topic": topic, - "name": "Test Select", - "options": ["milk", "beer"], - "command_template": '{"option": "{{ value }}"}', + mqtt.DOMAIN: { + select.DOMAIN: { + "command_topic": topic, + "name": "Test Select", + "options": ["milk", "beer"], + "command_template": '{"option": "{{ value }}"}', + } } }, ) @@ -238,14 +248,15 @@ async def test_run_select_service(hass, mqtt_mock_entry_with_yaml_config): assert await async_setup_component( hass, - select.DOMAIN, + mqtt.DOMAIN, { - "select": { - "platform": "mqtt", - "command_topic": cmd_topic, - "state_topic": state_topic, - "name": "Test Select", - "options": ["milk", "beer"], + mqtt.DOMAIN: { + select.DOMAIN: { + "command_topic": cmd_topic, + "state_topic": state_topic, + "name": "Test Select", + "options": ["milk", "beer"], + } } }, ) @@ -276,15 +287,16 @@ async def test_run_select_service_with_command_template( assert await async_setup_component( hass, - select.DOMAIN, + mqtt.DOMAIN, { - "select": { - "platform": "mqtt", - "command_topic": cmd_topic, - "state_topic": state_topic, - "name": "Test Select", - "options": ["milk", "beer"], - "command_template": '{"option": "{{ value }}"}', + mqtt.DOMAIN: { + select.DOMAIN: { + "command_topic": cmd_topic, + "state_topic": state_topic, + "name": "Test Select", + "options": ["milk", "beer"], + "command_template": '{"option": "{{ value }}"}', + } } }, ) @@ -311,28 +323,28 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, select.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, select.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, select.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, select.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by default payload with defined topic.""" await help_test_default_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, select.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, select.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by custom payload with defined topic.""" await help_test_custom_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, select.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, select.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -341,7 +353,7 @@ async def test_setting_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_with_yaml_config, select.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, select.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -353,7 +365,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( hass, mqtt_mock_entry_no_yaml_config, select.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, MQTT_SELECT_ATTRIBUTES_BLOCKED, ) @@ -361,7 +373,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_with_template( - hass, mqtt_mock_entry_with_yaml_config, select.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, select.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -370,7 +382,11 @@ async def test_update_with_json_attrs_not_dict( ): """Test attributes get extracted from a JSON result.""" await help_test_update_with_json_attrs_not_dict( - hass, mqtt_mock_entry_with_yaml_config, caplog, select.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_with_yaml_config, + caplog, + select.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) @@ -379,14 +395,22 @@ async def test_update_with_json_attrs_bad_JSON( ): """Test attributes get extracted from a JSON result.""" await help_test_update_with_json_attrs_bad_JSON( - hass, mqtt_mock_entry_with_yaml_config, caplog, select.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_with_yaml_config, + caplog, + select.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test update of discovered MQTTAttributes.""" await help_test_discovery_update_attr( - hass, mqtt_mock_entry_no_yaml_config, caplog, select.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_no_yaml_config, + caplog, + select.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) @@ -419,7 +443,7 @@ async def test_unique_id(hass, mqtt_mock_entry_with_yaml_config): async def test_discovery_removal_select(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test removal of discovered select.""" - data = json.dumps(DEFAULT_CONFIG[select.DOMAIN]) + data = json.dumps(DEFAULT_CONFIG_LEGACY[select.DOMAIN]) await help_test_discovery_removal( hass, mqtt_mock_entry_no_yaml_config, caplog, select.DOMAIN, data ) @@ -477,42 +501,42 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT select device registry integration.""" await help_test_entity_device_info_with_connection( - hass, mqtt_mock_entry_no_yaml_config, select.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, select.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT select device registry integration.""" await help_test_entity_device_info_with_identifier( - hass, mqtt_mock_entry_no_yaml_config, select.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, select.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): """Test device registry update.""" await help_test_entity_device_info_update( - hass, mqtt_mock_entry_no_yaml_config, select.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, select.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test device registry remove.""" await help_test_entity_device_info_remove( - hass, mqtt_mock_entry_no_yaml_config, select.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, select.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_config): """Test MQTT subscriptions are managed when entity_id is updated.""" await help_test_entity_id_update_subscriptions( - hass, mqtt_mock_entry_with_yaml_config, select.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, select.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, select.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, select.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -522,7 +546,7 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): hass, mqtt_mock_entry_no_yaml_config, select.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, select.SERVICE_SELECT_OPTION, service_parameters={ATTR_OPTION: "beer"}, command_payload="beer", @@ -536,14 +560,15 @@ async def test_options_attributes(hass, mqtt_mock_entry_with_yaml_config, option topic = "test/select" await async_setup_component( hass, - "select", + mqtt.DOMAIN, { - "select": { - "platform": "mqtt", - "state_topic": topic, - "command_topic": topic, - "name": "Test select", - "options": options, + mqtt.DOMAIN: { + select.DOMAIN: { + "state_topic": topic, + "command_topic": topic, + "name": "Test select", + "options": options, + } } }, ) @@ -561,14 +586,15 @@ async def test_mqtt_payload_not_an_option_warning( topic = "test/select" await async_setup_component( hass, - "select", + mqtt.DOMAIN, { - "select": { - "platform": "mqtt", - "state_topic": topic, - "command_topic": topic, - "name": "Test Select", - "options": ["milk", "beer"], + mqtt.DOMAIN: { + select.DOMAIN: { + "state_topic": topic, + "command_topic": topic, + "name": "Test Select", + "options": ["milk", "beer"], + } } }, ) @@ -609,7 +635,7 @@ async def test_publishing_with_custom_encoding( ): """Test publishing MQTT payload with different encoding.""" domain = select.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] config["options"] = ["milk", "beer"] await help_test_publishing_with_custom_encoding( @@ -629,7 +655,7 @@ async def test_publishing_with_custom_encoding( async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = select.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) @@ -638,7 +664,7 @@ async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_pa async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = select.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable_late(hass, caplog, tmp_path, domain, config) @@ -659,7 +685,7 @@ async def test_encoding_subscribable_topics( attribute_value, ): """Test handling of incoming encoded payload.""" - config = copy.deepcopy(DEFAULT_CONFIG["select"]) + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY["select"]) config["options"] = ["milk", "beer"] await help_test_encoding_subscribable_topics( hass, @@ -677,7 +703,7 @@ async def test_encoding_subscribable_topics( async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = select.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG[platform]) + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) config["name"] = "test" del config["platform"] await help_test_setup_manual_entity_from_yaml(hass, platform, config) @@ -687,7 +713,20 @@ async def test_setup_manual_entity_from_yaml(hass): async def test_unload_entry(hass, mqtt_mock_entry_with_yaml_config, tmp_path): """Test unloading the config entry.""" domain = select.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry_with_yaml_config, tmp_path, domain, config ) + + +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +async def test_setup_with_legacy_schema(hass, mqtt_mock_entry_with_yaml_config): + """Test a setup with deprecated yaml platform schema.""" + domain = select.DOMAIN + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[domain]) + config["name"] = "test" + assert await async_setup_component(hass, domain, {domain: config}) + await hass.async_block_till_done() + await mqtt_mock_entry_with_yaml_config() + assert hass.states.get(f"{domain}.test") is not None diff --git a/tests/components/mqtt/test_sensor.py b/tests/components/mqtt/test_sensor.py index b446b1a8b76d9..c5cf377cf1adc 100644 --- a/tests/components/mqtt/test_sensor.py +++ b/tests/components/mqtt/test_sensor.py @@ -6,8 +6,8 @@ import pytest +from homeassistant.components import mqtt, sensor from homeassistant.components.mqtt.sensor import MQTT_SENSOR_ATTRIBUTES_BLOCKED -import homeassistant.components.sensor as sensor from homeassistant.const import ( EVENT_STATE_CHANGED, STATE_UNAVAILABLE, @@ -64,16 +64,20 @@ ) from tests.common import ( - assert_setup_component, async_fire_mqtt_message, async_fire_time_changed, mock_restore_cache_with_extra_data, ) DEFAULT_CONFIG = { - sensor.DOMAIN: {"platform": "mqtt", "name": "test", "state_topic": "test-topic"} + mqtt.DOMAIN: {sensor.DOMAIN: {"name": "test", "state_topic": "test-topic"}} } +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +DEFAULT_CONFIG_LEGACY = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) +DEFAULT_CONFIG_LEGACY[sensor.DOMAIN]["platform"] = mqtt.DOMAIN + @pytest.fixture(autouse=True) def sensor_platform_only(): @@ -88,13 +92,14 @@ async def test_setting_sensor_value_via_mqtt_message( """Test the setting of the value via MQTT.""" assert await async_setup_component( hass, - sensor.DOMAIN, + mqtt.DOMAIN, { - sensor.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "test-topic", - "unit_of_measurement": "fav unit", + mqtt.DOMAIN: { + sensor.DOMAIN: { + "name": "test", + "state_topic": "test-topic", + "unit_of_measurement": "fav unit", + } } }, ) @@ -146,13 +151,14 @@ async def test_setting_sensor_native_value_handling_via_mqtt_message( """Test the setting of the value via MQTT.""" assert await async_setup_component( hass, - sensor.DOMAIN, + mqtt.DOMAIN, { - sensor.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "test-topic", - "device_class": device_class, + mqtt.DOMAIN: { + sensor.DOMAIN: { + "name": "test", + "state_topic": "test-topic", + "device_class": device_class, + } } }, ) @@ -173,15 +179,16 @@ async def test_setting_sensor_value_expires_availability_topic( """Test the expiration of the value.""" assert await async_setup_component( hass, - sensor.DOMAIN, + mqtt.DOMAIN, { - sensor.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "test-topic", - "expire_after": 4, - "force_update": True, - "availability_topic": "availability-topic", + mqtt.DOMAIN: { + sensor.DOMAIN: { + "name": "test", + "state_topic": "test-topic", + "expire_after": 4, + "force_update": True, + "availability_topic": "availability-topic", + } } }, ) @@ -206,15 +213,16 @@ async def test_setting_sensor_value_expires( """Test the expiration of the value.""" assert await async_setup_component( hass, - sensor.DOMAIN, + mqtt.DOMAIN, { - sensor.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "test-topic", - "unit_of_measurement": "fav unit", - "expire_after": "4", - "force_update": True, + mqtt.DOMAIN: { + sensor.DOMAIN: { + "name": "test", + "state_topic": "test-topic", + "unit_of_measurement": "fav unit", + "expire_after": "4", + "force_update": True, + } } }, ) @@ -285,14 +293,15 @@ async def test_setting_sensor_value_via_mqtt_json_message( """Test the setting of the value via MQTT with JSON payload.""" assert await async_setup_component( hass, - sensor.DOMAIN, + mqtt.DOMAIN, { - sensor.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "test-topic", - "unit_of_measurement": "fav unit", - "value_template": "{{ value_json.val }}", + mqtt.DOMAIN: { + sensor.DOMAIN: { + "name": "test", + "state_topic": "test-topic", + "unit_of_measurement": "fav unit", + "value_template": "{{ value_json.val }}", + } } }, ) @@ -311,14 +320,15 @@ async def test_setting_sensor_value_via_mqtt_json_message_and_default_current_st """Test the setting of the value via MQTT with fall back to current state.""" assert await async_setup_component( hass, - sensor.DOMAIN, + mqtt.DOMAIN, { - sensor.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "test-topic", - "unit_of_measurement": "fav unit", - "value_template": "{{ value_json.val | is_defined }}-{{ value_json.par }}", + mqtt.DOMAIN: { + sensor.DOMAIN: { + "name": "test", + "state_topic": "test-topic", + "unit_of_measurement": "fav unit", + "value_template": "{{ value_json.val | is_defined }}-{{ value_json.par }}", + } } }, ) @@ -344,15 +354,16 @@ async def test_setting_sensor_last_reset_via_mqtt_message( """Test the setting of the last_reset property via MQTT.""" assert await async_setup_component( hass, - sensor.DOMAIN, + mqtt.DOMAIN, { - sensor.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_class": "total", - "state_topic": "test-topic", - "unit_of_measurement": "fav unit", - "last_reset_topic": "last-reset-topic", + mqtt.DOMAIN: { + sensor.DOMAIN: { + "name": "test", + "state_class": "total", + "state_topic": "test-topic", + "unit_of_measurement": "fav unit", + "last_reset_topic": "last-reset-topic", + } } }, ) @@ -376,15 +387,16 @@ async def test_setting_sensor_bad_last_reset_via_mqtt_message( """Test the setting of the last_reset property via MQTT.""" assert await async_setup_component( hass, - sensor.DOMAIN, + mqtt.DOMAIN, { - sensor.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_class": "total", - "state_topic": "test-topic", - "unit_of_measurement": "fav unit", - "last_reset_topic": "last-reset-topic", + mqtt.DOMAIN: { + sensor.DOMAIN: { + "name": "test", + "state_class": "total", + "state_topic": "test-topic", + "unit_of_measurement": "fav unit", + "last_reset_topic": "last-reset-topic", + } } }, ) @@ -403,15 +415,16 @@ async def test_setting_sensor_empty_last_reset_via_mqtt_message( """Test the setting of the last_reset property via MQTT.""" assert await async_setup_component( hass, - sensor.DOMAIN, + mqtt.DOMAIN, { - sensor.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_class": "total", - "state_topic": "test-topic", - "unit_of_measurement": "fav unit", - "last_reset_topic": "last-reset-topic", + mqtt.DOMAIN: { + sensor.DOMAIN: { + "name": "test", + "state_class": "total", + "state_topic": "test-topic", + "unit_of_measurement": "fav unit", + "last_reset_topic": "last-reset-topic", + } } }, ) @@ -430,16 +443,17 @@ async def test_setting_sensor_last_reset_via_mqtt_json_message( """Test the setting of the value via MQTT with JSON payload.""" assert await async_setup_component( hass, - sensor.DOMAIN, + mqtt.DOMAIN, { - sensor.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_class": "total", - "state_topic": "test-topic", - "unit_of_measurement": "fav unit", - "last_reset_topic": "last-reset-topic", - "last_reset_value_template": "{{ value_json.last_reset }}", + mqtt.DOMAIN: { + sensor.DOMAIN: { + "name": "test", + "state_class": "total", + "state_topic": "test-topic", + "unit_of_measurement": "fav unit", + "last_reset_topic": "last-reset-topic", + "last_reset_value_template": "{{ value_json.last_reset }}", + } } }, ) @@ -460,19 +474,20 @@ async def test_setting_sensor_last_reset_via_mqtt_json_message_2( """Test the setting of the value via MQTT with JSON payload.""" assert await async_setup_component( hass, - sensor.DOMAIN, + mqtt.DOMAIN, { - sensor.DOMAIN: { - **{ - "platform": "mqtt", - "name": "test", - "state_class": "total", - "state_topic": "test-topic", - "unit_of_measurement": "kWh", - "value_template": "{{ value_json.value | float / 60000 }}", - "last_reset_value_template": "{{ utcnow().fromtimestamp(value_json.time / 1000, tz=utcnow().tzinfo) }}", - }, - **extra, + mqtt.DOMAIN: { + sensor.DOMAIN: { + **{ + "name": "test", + "state_class": "total", + "state_topic": "test-topic", + "unit_of_measurement": "kWh", + "value_template": "{{ value_json.value | float / 60000 }}", + "last_reset_value_template": "{{ utcnow().fromtimestamp(value_json.time / 1000, tz=utcnow().tzinfo) }}", + }, + **extra, + } } }, ) @@ -498,13 +513,14 @@ async def test_force_update_disabled(hass, mqtt_mock_entry_with_yaml_config): """Test force update option.""" assert await async_setup_component( hass, - sensor.DOMAIN, + mqtt.DOMAIN, { - sensor.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "test-topic", - "unit_of_measurement": "fav unit", + mqtt.DOMAIN: { + sensor.DOMAIN: { + "name": "test", + "state_topic": "test-topic", + "unit_of_measurement": "fav unit", + } } }, ) @@ -532,14 +548,15 @@ async def test_force_update_enabled(hass, mqtt_mock_entry_with_yaml_config): """Test force update option.""" assert await async_setup_component( hass, - sensor.DOMAIN, + mqtt.DOMAIN, { - sensor.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "test-topic", - "unit_of_measurement": "fav unit", - "force_update": True, + mqtt.DOMAIN: { + sensor.DOMAIN: { + "name": "test", + "state_topic": "test-topic", + "unit_of_measurement": "fav unit", + "force_update": True, + } } }, ) @@ -568,21 +585,21 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by default payload with defined topic.""" await help_test_default_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -591,7 +608,7 @@ async def test_default_availability_list_payload( ): """Test availability by default payload with defined topic.""" await help_test_default_availability_list_payload( - hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -600,7 +617,7 @@ async def test_default_availability_list_payload_all( ): """Test availability by default payload with defined topic.""" await help_test_default_availability_list_payload_all( - hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -609,7 +626,7 @@ async def test_default_availability_list_payload_any( ): """Test availability by default payload with defined topic.""" await help_test_default_availability_list_payload_any( - hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -618,21 +635,25 @@ async def test_default_availability_list_single( ): """Test availability list and availability_topic are mutually exclusive.""" await help_test_default_availability_list_single( - hass, mqtt_mock_entry_no_yaml_config, caplog, sensor.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_no_yaml_config, + caplog, + sensor.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by custom payload with defined topic.""" await help_test_custom_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_discovery_update_availability(hass, mqtt_mock_entry_no_yaml_config): """Test availability discovery update.""" await help_test_discovery_update_availability( - hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -642,11 +663,12 @@ async def test_invalid_device_class(hass, mqtt_mock_entry_no_yaml_config): hass, sensor.DOMAIN, { - sensor.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "test-topic", - "device_class": "foobarnotreal", + mqtt.DOMAIN: { + sensor.DOMAIN: { + "name": "test", + "state_topic": "test-topic", + "device_class": "foobarnotreal", + } } }, ) @@ -661,17 +683,18 @@ async def test_valid_device_class(hass, mqtt_mock_entry_with_yaml_config): """Test device_class option with valid values.""" assert await async_setup_component( hass, - "sensor", + mqtt.DOMAIN, { - "sensor": [ - { - "platform": "mqtt", - "name": "Test 1", - "state_topic": "test-topic", - "device_class": "temperature", - }, - {"platform": "mqtt", "name": "Test 2", "state_topic": "test-topic"}, - ] + mqtt.DOMAIN: { + sensor.DOMAIN: [ + { + "name": "Test 1", + "state_topic": "test-topic", + "device_class": "temperature", + }, + {"name": "Test 2", "state_topic": "test-topic"}, + ] + } }, ) await hass.async_block_till_done() @@ -689,11 +712,12 @@ async def test_invalid_state_class(hass, mqtt_mock_entry_no_yaml_config): hass, sensor.DOMAIN, { - sensor.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "test-topic", - "state_class": "foobarnotreal", + mqtt.DOMAIN: { + sensor.DOMAIN: { + "name": "test", + "state_topic": "test-topic", + "state_class": "foobarnotreal", + } } }, ) @@ -708,17 +732,18 @@ async def test_valid_state_class(hass, mqtt_mock_entry_with_yaml_config): """Test state_class option with valid values.""" assert await async_setup_component( hass, - "sensor", + mqtt.DOMAIN, { - "sensor": [ - { - "platform": "mqtt", - "name": "Test 1", - "state_topic": "test-topic", - "state_class": "measurement", - }, - {"platform": "mqtt", "name": "Test 2", "state_topic": "test-topic"}, - ] + mqtt.DOMAIN: { + sensor.DOMAIN: [ + { + "name": "Test 1", + "state_topic": "test-topic", + "state_class": "measurement", + }, + {"name": "Test 2", "state_topic": "test-topic"}, + ] + } }, ) await hass.async_block_till_done() @@ -735,7 +760,7 @@ async def test_setting_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -747,7 +772,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, MQTT_SENSOR_ATTRIBUTES_BLOCKED, ) @@ -755,7 +780,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_with_template( - hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -764,7 +789,11 @@ async def test_update_with_json_attrs_not_dict( ): """Test attributes get extracted from a JSON result.""" await help_test_update_with_json_attrs_not_dict( - hass, mqtt_mock_entry_with_yaml_config, caplog, sensor.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_with_yaml_config, + caplog, + sensor.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) @@ -773,14 +802,22 @@ async def test_update_with_json_attrs_bad_JSON( ): """Test attributes get extracted from a JSON result.""" await help_test_update_with_json_attrs_bad_JSON( - hass, mqtt_mock_entry_with_yaml_config, caplog, sensor.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_with_yaml_config, + caplog, + sensor.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test update of discovered MQTTAttributes.""" await help_test_discovery_update_attr( - hass, mqtt_mock_entry_no_yaml_config, caplog, sensor.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_no_yaml_config, + caplog, + sensor.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) @@ -914,42 +951,42 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT sensor device registry integration.""" await help_test_entity_device_info_with_connection( - hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT sensor device registry integration.""" await help_test_entity_device_info_with_identifier( - hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): """Test device registry update.""" await help_test_entity_device_info_update( - hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test device registry remove.""" await help_test_entity_device_info_remove( - hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_config): """Test MQTT subscriptions are managed when entity_id is updated.""" await help_test_entity_id_update_subscriptions( - hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -967,7 +1004,6 @@ async def test_entity_device_info_with_hub(hass, mqtt_mock_entry_no_yaml_config) data = json.dumps( { - "platform": "mqtt", "name": "Test 1", "state_topic": "test-topic", "device": {"identifiers": ["helloworld"], "via_device": "hub-id"}, @@ -985,42 +1021,42 @@ async def test_entity_device_info_with_hub(hass, mqtt_mock_entry_no_yaml_config) async def test_entity_debug_info(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT sensor debug info.""" await help_test_entity_debug_info( - hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_debug_info_max_messages(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT sensor debug info.""" await help_test_entity_debug_info_max_messages( - hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT debug info.""" await help_test_entity_debug_info_message( - hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG, None + hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY, None ) async def test_entity_debug_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT sensor debug info.""" await help_test_entity_debug_info_remove( - hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_debug_info_update_entity_id(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT sensor debug info.""" await help_test_entity_debug_info_update_entity_id( - hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_disabled_by_default(hass, mqtt_mock_entry_no_yaml_config): """Test entity disabled by default.""" await help_test_entity_disabled_by_default( - hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -1028,7 +1064,7 @@ async def test_entity_disabled_by_default(hass, mqtt_mock_entry_no_yaml_config): async def test_entity_category(hass, mqtt_mock_entry_no_yaml_config): """Test entity category.""" await help_test_entity_category( - hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -1036,19 +1072,20 @@ async def test_value_template_with_entity_id(hass, mqtt_mock_entry_with_yaml_con """Test the access to attributes in value_template via the entity_id.""" assert await async_setup_component( hass, - sensor.DOMAIN, + mqtt.DOMAIN, { - sensor.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "test-topic", - "unit_of_measurement": "fav unit", - "value_template": '\ + mqtt.DOMAIN: { + sensor.DOMAIN: { + "name": "test", + "state_topic": "test-topic", + "unit_of_measurement": "fav unit", + "value_template": '\ {% if state_attr(entity_id, "friendly_name") == "test" %} \ {{ value | int + 1 }} \ {% else %} \ {{ value }} \ {% endif %}', + } } }, ) @@ -1064,7 +1101,7 @@ async def test_value_template_with_entity_id(hass, mqtt_mock_entry_with_yaml_con async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = sensor.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) @@ -1073,7 +1110,7 @@ async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_pa async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = sensor.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable_late(hass, caplog, tmp_path, domain, config) @@ -1082,14 +1119,14 @@ async def test_cleanup_triggers_and_restoring_state( ): """Test cleanup old triggers at reloading and restoring the state.""" domain = sensor.DOMAIN - config1 = copy.deepcopy(DEFAULT_CONFIG[domain]) + config1 = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][domain]) config1["name"] = "test1" config1["expire_after"] = 30 config1["state_topic"] = "test-topic1" config1["device_class"] = "temperature" config1["unit_of_measurement"] = TEMP_FAHRENHEIT - config2 = copy.deepcopy(DEFAULT_CONFIG[domain]) + config2 = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][domain]) config2["name"] = "test2" config2["expire_after"] = 5 config2["state_topic"] = "test-topic2" @@ -1100,8 +1137,8 @@ async def test_cleanup_triggers_and_restoring_state( assert await async_setup_component( hass, - domain, - {domain: [config1, config2]}, + mqtt.DOMAIN, + {mqtt.DOMAIN: {domain: [config1, config2]}}, ) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -1116,7 +1153,7 @@ async def test_cleanup_triggers_and_restoring_state( freezer.move_to("2022-02-02 12:01:10+01:00") await help_test_reload_with_config( - hass, caplog, tmp_path, {domain: [config1, config2]} + hass, caplog, tmp_path, {mqtt.DOMAIN: {domain: [config1, config2]}} ) await hass.async_block_till_done() @@ -1150,7 +1187,7 @@ async def test_skip_restoring_state_with_over_due_expire_trigger( freezer.move_to("2022-02-02 12:02:00+01:00") domain = sensor.DOMAIN - config3 = copy.deepcopy(DEFAULT_CONFIG[domain]) + config3 = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][domain]) config3["name"] = "test3" config3["expire_after"] = 10 config3["state_topic"] = "test-topic3" @@ -1163,10 +1200,11 @@ async def test_skip_restoring_state_with_over_due_expire_trigger( fake_extra_data = MagicMock() mock_restore_cache_with_extra_data(hass, ((fake_state, fake_extra_data),)) - with assert_setup_component(1, domain): - assert await async_setup_component(hass, domain, {domain: config3}) - await hass.async_block_till_done() - await mqtt_mock_entry_with_yaml_config() + assert await async_setup_component( + hass, mqtt.DOMAIN, {mqtt.DOMAIN: {domain: config3}} + ) + await hass.async_block_till_done() + await mqtt_mock_entry_with_yaml_config() assert "Skip state recovery after reload for sensor.test3" in caplog.text @@ -1192,7 +1230,7 @@ async def test_encoding_subscribable_topics( mqtt_mock_entry_with_yaml_config, caplog, sensor.DOMAIN, - DEFAULT_CONFIG[sensor.DOMAIN], + DEFAULT_CONFIG_LEGACY[sensor.DOMAIN], topic, value, attribute, @@ -1204,7 +1242,7 @@ async def test_encoding_subscribable_topics( async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = sensor.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG[platform]) + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) config["name"] = "test" del config["platform"] await help_test_setup_manual_entity_from_yaml(hass, platform, config) @@ -1214,7 +1252,20 @@ async def test_setup_manual_entity_from_yaml(hass): async def test_unload_entry(hass, mqtt_mock_entry_with_yaml_config, tmp_path): """Test unloading the config entry.""" domain = sensor.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry_with_yaml_config, tmp_path, domain, config ) + + +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +async def test_setup_with_legacy_schema(hass, mqtt_mock_entry_with_yaml_config): + """Test a setup with deprecated yaml platform schema.""" + domain = sensor.DOMAIN + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[domain]) + config["name"] = "test" + assert await async_setup_component(hass, domain, {domain: config}) + await hass.async_block_till_done() + await mqtt_mock_entry_with_yaml_config() + assert hass.states.get(f"{domain}.test") is not None diff --git a/tests/components/mqtt/test_siren.py b/tests/components/mqtt/test_siren.py index 13648f1c48645..fd91847f7672c 100644 --- a/tests/components/mqtt/test_siren.py +++ b/tests/components/mqtt/test_siren.py @@ -4,7 +4,7 @@ import pytest -from homeassistant.components import siren +from homeassistant.components import mqtt, siren from homeassistant.components.siren.const import ATTR_VOLUME_LEVEL from homeassistant.const import ( ATTR_ASSUMED_STATE, @@ -53,9 +53,14 @@ from tests.common import async_fire_mqtt_message DEFAULT_CONFIG = { - siren.DOMAIN: {"platform": "mqtt", "name": "test", "command_topic": "test-topic"} + mqtt.DOMAIN: {siren.DOMAIN: {"name": "test", "command_topic": "test-topic"}} } +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +DEFAULT_CONFIG_LEGACY = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) +DEFAULT_CONFIG_LEGACY[siren.DOMAIN]["platform"] = mqtt.DOMAIN + @pytest.fixture(autouse=True) def siren_platform_only(): @@ -83,15 +88,16 @@ async def test_controlling_state_via_topic(hass, mqtt_mock_entry_with_yaml_confi """Test the controlling state via topic.""" assert await async_setup_component( hass, - siren.DOMAIN, + mqtt.DOMAIN, { - siren.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "payload_on": 1, - "payload_off": 0, + mqtt.DOMAIN: { + siren.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "payload_on": 1, + "payload_off": 0, + } } }, ) @@ -119,15 +125,16 @@ async def test_sending_mqtt_commands_and_optimistic( """Test the sending MQTT commands in optimistic mode.""" assert await async_setup_component( hass, - siren.DOMAIN, + mqtt.DOMAIN, { - siren.DOMAIN: { - "platform": "mqtt", - "name": "test", - "command_topic": "command-topic", - "payload_on": "beer on", - "payload_off": "beer off", - "qos": "2", + mqtt.DOMAIN: { + siren.DOMAIN: { + "name": "test", + "command_topic": "command-topic", + "payload_on": "beer on", + "payload_off": "beer off", + "qos": "2", + } } }, ) @@ -162,16 +169,17 @@ async def test_controlling_state_via_topic_and_json_message( """Test the controlling state via topic and JSON message.""" assert await async_setup_component( hass, - siren.DOMAIN, + mqtt.DOMAIN, { - siren.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "payload_on": "beer on", - "payload_off": "beer off", - "state_value_template": "{{ value_json.val }}", + mqtt.DOMAIN: { + siren.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "payload_on": "beer on", + "payload_off": "beer off", + "state_value_template": "{{ value_json.val }}", + } } }, ) @@ -202,16 +210,17 @@ async def test_controlling_state_and_attributes_with_json_message_without_templa """Test the controlling state via topic and JSON message without a value template.""" assert await async_setup_component( hass, - siren.DOMAIN, + mqtt.DOMAIN, { - siren.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "payload_on": "beer on", - "payload_off": "beer off", - "available_tones": ["ping", "siren", "bell"], + mqtt.DOMAIN: { + siren.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "payload_on": "beer on", + "payload_off": "beer off", + "available_tones": ["ping", "siren", "bell"], + } } }, ) @@ -284,7 +293,6 @@ async def test_filtering_not_supported_attributes_optimistic( ): """Test setting attributes with support flags optimistic.""" config = { - "platform": "mqtt", "command_topic": "command-topic", "available_tones": ["ping", "siren", "bell"], } @@ -300,8 +308,8 @@ async def test_filtering_not_supported_attributes_optimistic( assert await async_setup_component( hass, - siren.DOMAIN, - {siren.DOMAIN: [config1, config2, config3]}, + mqtt.DOMAIN, + {mqtt.DOMAIN: {siren.DOMAIN: [config1, config2, config3]}}, ) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -370,7 +378,6 @@ async def test_filtering_not_supported_attributes_via_state( ): """Test setting attributes with support flags via state.""" config = { - "platform": "mqtt", "command_topic": "command-topic", "available_tones": ["ping", "siren", "bell"], } @@ -389,8 +396,8 @@ async def test_filtering_not_supported_attributes_via_state( assert await async_setup_component( hass, - siren.DOMAIN, - {siren.DOMAIN: [config1, config2, config3]}, + mqtt.DOMAIN, + {mqtt.DOMAIN: {siren.DOMAIN: [config1, config2, config3]}}, ) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -450,14 +457,14 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, siren.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, siren.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, siren.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, siren.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -513,17 +520,18 @@ async def test_custom_state_payload(hass, mqtt_mock_entry_with_yaml_config): """Test the state payload.""" assert await async_setup_component( hass, - siren.DOMAIN, + mqtt.DOMAIN, { - siren.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "payload_on": 1, - "payload_off": 0, - "state_on": "HIGH", - "state_off": "LOW", + mqtt.DOMAIN: { + siren.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "payload_on": 1, + "payload_off": 0, + "state_on": "HIGH", + "state_off": "LOW", + } } }, ) @@ -550,7 +558,7 @@ async def test_setting_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_with_yaml_config, siren.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, siren.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -559,14 +567,14 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_blocked_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_no_yaml_config, siren.DOMAIN, DEFAULT_CONFIG, {} + hass, mqtt_mock_entry_no_yaml_config, siren.DOMAIN, DEFAULT_CONFIG_LEGACY, {} ) async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_with_template( - hass, mqtt_mock_entry_with_yaml_config, siren.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, siren.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -575,7 +583,11 @@ async def test_update_with_json_attrs_not_dict( ): """Test attributes get extracted from a JSON result.""" await help_test_update_with_json_attrs_not_dict( - hass, mqtt_mock_entry_with_yaml_config, caplog, siren.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_with_yaml_config, + caplog, + siren.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) @@ -584,14 +596,22 @@ async def test_update_with_json_attrs_bad_JSON( ): """Test attributes get extracted from a JSON result.""" await help_test_update_with_json_attrs_bad_JSON( - hass, mqtt_mock_entry_with_yaml_config, caplog, siren.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_with_yaml_config, + caplog, + siren.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test update of discovered MQTTAttributes.""" await help_test_discovery_update_attr( - hass, mqtt_mock_entry_no_yaml_config, caplog, siren.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_no_yaml_config, + caplog, + siren.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) @@ -636,8 +656,8 @@ async def test_discovery_update_siren_topic_template( hass, mqtt_mock_entry_no_yaml_config, caplog ): """Test update of discovered siren.""" - config1 = copy.deepcopy(DEFAULT_CONFIG[siren.DOMAIN]) - config2 = copy.deepcopy(DEFAULT_CONFIG[siren.DOMAIN]) + config1 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[siren.DOMAIN]) + config2 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[siren.DOMAIN]) config1["name"] = "Beer" config2["name"] = "Milk" config1["state_topic"] = "siren/state1" @@ -673,8 +693,8 @@ async def test_discovery_update_siren_template( hass, mqtt_mock_entry_no_yaml_config, caplog ): """Test update of discovered siren.""" - config1 = copy.deepcopy(DEFAULT_CONFIG[siren.DOMAIN]) - config2 = copy.deepcopy(DEFAULT_CONFIG[siren.DOMAIN]) + config1 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[siren.DOMAIN]) + config2 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[siren.DOMAIN]) config1["name"] = "Beer" config2["name"] = "Milk" config1["state_topic"] = "siren/state1" @@ -706,7 +726,7 @@ async def test_discovery_update_siren_template( async def test_command_templates(hass, mqtt_mock_entry_with_yaml_config, caplog): """Test siren with command templates optimistic.""" - config1 = copy.deepcopy(DEFAULT_CONFIG[siren.DOMAIN]) + config1 = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][siren.DOMAIN]) config1["name"] = "Beer" config1["available_tones"] = ["ping", "chimes"] config1[ @@ -719,8 +739,8 @@ async def test_command_templates(hass, mqtt_mock_entry_with_yaml_config, caplog) assert await async_setup_component( hass, - siren.DOMAIN, - {siren.DOMAIN: [config1, config2]}, + mqtt.DOMAIN, + {mqtt.DOMAIN: {siren.DOMAIN: [config1, config2]}}, ) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -824,42 +844,42 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT siren device registry integration.""" await help_test_entity_device_info_with_connection( - hass, mqtt_mock_entry_no_yaml_config, siren.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, siren.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT siren device registry integration.""" await help_test_entity_device_info_with_identifier( - hass, mqtt_mock_entry_no_yaml_config, siren.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, siren.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): """Test device registry update.""" await help_test_entity_device_info_update( - hass, mqtt_mock_entry_no_yaml_config, siren.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, siren.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test device registry remove.""" await help_test_entity_device_info_remove( - hass, mqtt_mock_entry_no_yaml_config, siren.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, siren.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_config): """Test MQTT subscriptions are managed when entity_id is updated.""" await help_test_entity_id_update_subscriptions( - hass, mqtt_mock_entry_with_yaml_config, siren.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, siren.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, siren.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, siren.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -869,7 +889,7 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): hass, mqtt_mock_entry_no_yaml_config, siren.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, siren.SERVICE_TURN_ON, command_payload='{"state":"ON"}', ) @@ -906,7 +926,7 @@ async def test_publishing_with_custom_encoding( ): """Test publishing MQTT payload with command templates and different encoding.""" domain = siren.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG[domain]) + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[domain]) config[siren.ATTR_AVAILABLE_TONES] = ["siren", "xylophone"] await help_test_publishing_with_custom_encoding( @@ -926,7 +946,7 @@ async def test_publishing_with_custom_encoding( async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = siren.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) @@ -935,7 +955,7 @@ async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_pa async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = siren.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable_late(hass, caplog, tmp_path, domain, config) @@ -960,7 +980,7 @@ async def test_encoding_subscribable_topics( mqtt_mock_entry_with_yaml_config, caplog, siren.DOMAIN, - DEFAULT_CONFIG[siren.DOMAIN], + DEFAULT_CONFIG_LEGACY[siren.DOMAIN], topic, value, attribute, @@ -971,7 +991,7 @@ async def test_encoding_subscribable_topics( async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = siren.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG[platform]) + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) config["name"] = "test" del config["platform"] await help_test_setup_manual_entity_from_yaml(hass, platform, config) @@ -981,7 +1001,20 @@ async def test_setup_manual_entity_from_yaml(hass): async def test_unload_entry(hass, mqtt_mock_entry_with_yaml_config, tmp_path): """Test unloading the config entry.""" domain = siren.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry_with_yaml_config, tmp_path, domain, config ) + + +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +async def test_setup_with_legacy_schema(hass, mqtt_mock_entry_with_yaml_config): + """Test a setup with deprecated yaml platform schema.""" + domain = siren.DOMAIN + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[domain]) + config["name"] = "test" + assert await async_setup_component(hass, domain, {domain: config}) + await hass.async_block_till_done() + await mqtt_mock_entry_with_yaml_config() + assert hass.states.get(f"{domain}.test") is not None diff --git a/tests/components/mqtt/test_state_vacuum.py b/tests/components/mqtt/test_state_vacuum.py index b0b89c286466c..4c2fbf3a596d5 100644 --- a/tests/components/mqtt/test_state_vacuum.py +++ b/tests/components/mqtt/test_state_vacuum.py @@ -5,7 +5,7 @@ import pytest -from homeassistant.components import vacuum +from homeassistant.components import mqtt, vacuum from homeassistant.components.mqtt.const import CONF_COMMAND_TOPIC, CONF_STATE_TOPIC from homeassistant.components.mqtt.vacuum import CONF_SCHEMA, schema_state as mqttvacuum from homeassistant.components.mqtt.vacuum.const import MQTT_VACUUM_ATTRIBUTES_BLOCKED @@ -73,19 +73,27 @@ STATE_TOPIC = "vacuum/state" DEFAULT_CONFIG = { - CONF_PLATFORM: "mqtt", - CONF_SCHEMA: "state", - CONF_NAME: "mqtttest", - CONF_COMMAND_TOPIC: COMMAND_TOPIC, - mqttvacuum.CONF_SEND_COMMAND_TOPIC: SEND_COMMAND_TOPIC, - CONF_STATE_TOPIC: STATE_TOPIC, - mqttvacuum.CONF_SET_FAN_SPEED_TOPIC: "vacuum/set_fan_speed", - mqttvacuum.CONF_FAN_SPEED_LIST: ["min", "medium", "high", "max"], + mqtt.DOMAIN: { + vacuum.DOMAIN: { + CONF_SCHEMA: "state", + CONF_NAME: "mqtttest", + CONF_COMMAND_TOPIC: COMMAND_TOPIC, + mqttvacuum.CONF_SEND_COMMAND_TOPIC: SEND_COMMAND_TOPIC, + CONF_STATE_TOPIC: STATE_TOPIC, + mqttvacuum.CONF_SET_FAN_SPEED_TOPIC: "vacuum/set_fan_speed", + mqttvacuum.CONF_FAN_SPEED_LIST: ["min", "medium", "high", "max"], + } + } } -DEFAULT_CONFIG_2 = { - vacuum.DOMAIN: {"platform": "mqtt", "schema": "state", "name": "test"} -} +DEFAULT_CONFIG_2 = {mqtt.DOMAIN: {vacuum.DOMAIN: {"schema": "state", "name": "test"}}} + +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +DEFAULT_CONFIG_LEGACY = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) +DEFAULT_CONFIG_LEGACY[vacuum.DOMAIN][CONF_PLATFORM] = mqtt.DOMAIN +DEFAULT_CONFIG_2_LEGACY = deepcopy(DEFAULT_CONFIG_2[mqtt.DOMAIN]) +DEFAULT_CONFIG_2_LEGACY[vacuum.DOMAIN][CONF_PLATFORM] = mqtt.DOMAIN @pytest.fixture(autouse=True) @@ -97,9 +105,7 @@ def vacuum_platform_only(): async def test_default_supported_features(hass, mqtt_mock_entry_with_yaml_config): """Test that the correct supported features.""" - assert await async_setup_component( - hass, vacuum.DOMAIN, {vacuum.DOMAIN: DEFAULT_CONFIG} - ) + assert await async_setup_component(hass, mqtt.DOMAIN, DEFAULT_CONFIG) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() entity = hass.states.get("vacuum.mqtttest") @@ -111,12 +117,14 @@ async def test_default_supported_features(hass, mqtt_mock_entry_with_yaml_config async def test_all_commands(hass, mqtt_mock_entry_with_yaml_config): """Test simple commands send to the vacuum.""" - config = deepcopy(DEFAULT_CONFIG) + config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) config[mqttvacuum.CONF_SUPPORTED_FEATURES] = services_to_strings( mqttvacuum.ALL_SERVICES, SERVICE_TO_STRING ) - assert await async_setup_component(hass, vacuum.DOMAIN, {vacuum.DOMAIN: config}) + assert await async_setup_component( + hass, mqtt.DOMAIN, {mqtt.DOMAIN: {vacuum.DOMAIN: config}} + ) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -185,13 +193,15 @@ async def test_commands_without_supported_features( hass, mqtt_mock_entry_with_yaml_config ): """Test commands which are not supported by the vacuum.""" - config = deepcopy(DEFAULT_CONFIG) + config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) services = mqttvacuum.STRING_TO_SERVICE["status"] config[mqttvacuum.CONF_SUPPORTED_FEATURES] = services_to_strings( services, SERVICE_TO_STRING ) - assert await async_setup_component(hass, vacuum.DOMAIN, {vacuum.DOMAIN: config}) + assert await async_setup_component( + hass, mqtt.DOMAIN, {mqtt.DOMAIN: {vacuum.DOMAIN: config}} + ) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -243,12 +253,14 @@ async def test_commands_without_supported_features( async def test_status(hass, mqtt_mock_entry_with_yaml_config): """Test status updates from the vacuum.""" - config = deepcopy(DEFAULT_CONFIG) + config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) config[mqttvacuum.CONF_SUPPORTED_FEATURES] = services_to_strings( mqttvacuum.ALL_SERVICES, SERVICE_TO_STRING ) - assert await async_setup_component(hass, vacuum.DOMAIN, {vacuum.DOMAIN: config}) + assert await async_setup_component( + hass, mqtt.DOMAIN, {mqtt.DOMAIN: {vacuum.DOMAIN: config}} + ) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() state = hass.states.get("vacuum.mqtttest") @@ -288,13 +300,15 @@ async def test_status(hass, mqtt_mock_entry_with_yaml_config): async def test_no_fan_vacuum(hass, mqtt_mock_entry_with_yaml_config): """Test status updates from the vacuum when fan is not supported.""" - config = deepcopy(DEFAULT_CONFIG) + config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) del config[mqttvacuum.CONF_FAN_SPEED_LIST] config[mqttvacuum.CONF_SUPPORTED_FEATURES] = services_to_strings( mqttvacuum.DEFAULT_SERVICES, SERVICE_TO_STRING ) - assert await async_setup_component(hass, vacuum.DOMAIN, {vacuum.DOMAIN: config}) + assert await async_setup_component( + hass, mqtt.DOMAIN, {mqtt.DOMAIN: {vacuum.DOMAIN: config}} + ) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -340,12 +354,14 @@ async def test_no_fan_vacuum(hass, mqtt_mock_entry_with_yaml_config): @pytest.mark.no_fail_on_log_exception async def test_status_invalid_json(hass, mqtt_mock_entry_with_yaml_config): """Test to make sure nothing breaks if the vacuum sends bad JSON.""" - config = deepcopy(DEFAULT_CONFIG) + config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) config[mqttvacuum.CONF_SUPPORTED_FEATURES] = services_to_strings( mqttvacuum.ALL_SERVICES, SERVICE_TO_STRING ) - assert await async_setup_component(hass, vacuum.DOMAIN, {vacuum.DOMAIN: config}) + assert await async_setup_component( + hass, mqtt.DOMAIN, {mqtt.DOMAIN: {vacuum.DOMAIN: config}} + ) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -359,28 +375,28 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 + hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 + hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY ) async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by default payload with defined topic.""" await help_test_default_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 + hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY ) async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by custom payload with defined topic.""" await help_test_custom_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 + hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY ) @@ -389,7 +405,7 @@ async def test_setting_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 + hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY ) @@ -401,7 +417,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, - DEFAULT_CONFIG_2, + DEFAULT_CONFIG_2_LEGACY, MQTT_VACUUM_ATTRIBUTES_BLOCKED, ) @@ -409,7 +425,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_with_template( - hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 + hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY ) @@ -418,7 +434,11 @@ async def test_update_with_json_attrs_not_dict( ): """Test attributes get extracted from a JSON result.""" await help_test_update_with_json_attrs_not_dict( - hass, mqtt_mock_entry_with_yaml_config, caplog, vacuum.DOMAIN, DEFAULT_CONFIG_2 + hass, + mqtt_mock_entry_with_yaml_config, + caplog, + vacuum.DOMAIN, + DEFAULT_CONFIG_2_LEGACY, ) @@ -427,14 +447,22 @@ async def test_update_with_json_attrs_bad_json( ): """Test attributes get extracted from a JSON result.""" await help_test_update_with_json_attrs_bad_JSON( - hass, mqtt_mock_entry_with_yaml_config, caplog, vacuum.DOMAIN, DEFAULT_CONFIG_2 + hass, + mqtt_mock_entry_with_yaml_config, + caplog, + vacuum.DOMAIN, + DEFAULT_CONFIG_2_LEGACY, ) async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test update of discovered MQTTAttributes.""" await help_test_discovery_update_attr( - hass, mqtt_mock_entry_no_yaml_config, caplog, vacuum.DOMAIN, DEFAULT_CONFIG_2 + hass, + mqtt_mock_entry_no_yaml_config, + caplog, + vacuum.DOMAIN, + DEFAULT_CONFIG_2_LEGACY, ) @@ -511,42 +539,42 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT vacuum device registry integration.""" await help_test_entity_device_info_with_connection( - hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 + hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY ) async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT vacuum device registry integration.""" await help_test_entity_device_info_with_identifier( - hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 + hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY ) async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): """Test device registry update.""" await help_test_entity_device_info_update( - hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 + hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY ) async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test device registry remove.""" await help_test_entity_device_info_remove( - hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 + hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY ) async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_config): """Test MQTT subscriptions are managed when entity_id is updated.""" await help_test_entity_id_update_subscriptions( - hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 + hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY ) async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 + hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY ) @@ -556,7 +584,7 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, - DEFAULT_CONFIG_2, + DEFAULT_CONFIG_2_LEGACY, vacuum.SERVICE_START, command_payload="start", state_payload="{}", @@ -615,7 +643,7 @@ async def test_publishing_with_custom_encoding( ): """Test publishing MQTT payload with different encoding.""" domain = vacuum.DOMAIN - config = deepcopy(DEFAULT_CONFIG) + config = deepcopy(DEFAULT_CONFIG_LEGACY[domain]) config["supported_features"] = [ "battery", "clean_spot", @@ -646,7 +674,7 @@ async def test_publishing_with_custom_encoding( async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = vacuum.DOMAIN - config = DEFAULT_CONFIG + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) @@ -655,7 +683,7 @@ async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_pa async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = vacuum.DOMAIN - config = DEFAULT_CONFIG + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable_late(hass, caplog, tmp_path, domain, config) @@ -691,7 +719,7 @@ async def test_encoding_subscribable_topics( mqtt_mock_entry_with_yaml_config, caplog, vacuum.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY[vacuum.DOMAIN], topic, value, attribute, @@ -703,8 +731,21 @@ async def test_encoding_subscribable_topics( async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = vacuum.DOMAIN - config = deepcopy(DEFAULT_CONFIG) + config = deepcopy(DEFAULT_CONFIG_LEGACY[platform]) config["name"] = "test" del config["platform"] await help_test_setup_manual_entity_from_yaml(hass, platform, config) assert hass.states.get(f"{platform}.test") is not None + + +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +async def test_setup_with_legacy_schema(hass, mqtt_mock_entry_with_yaml_config): + """Test a setup with deprecated yaml platform schema.""" + domain = vacuum.DOMAIN + config = deepcopy(DEFAULT_CONFIG_LEGACY[domain]) + config["name"] = "test" + assert await async_setup_component(hass, domain, {domain: config}) + await hass.async_block_till_done() + await mqtt_mock_entry_with_yaml_config() + assert hass.states.get(f"{domain}.test") is not None diff --git a/tests/components/mqtt/test_switch.py b/tests/components/mqtt/test_switch.py index ac69b17e18e94..87d919f41c5f7 100644 --- a/tests/components/mqtt/test_switch.py +++ b/tests/components/mqtt/test_switch.py @@ -4,7 +4,7 @@ import pytest -from homeassistant.components import switch +from homeassistant.components import mqtt, switch from homeassistant.const import ( ATTR_ASSUMED_STATE, ATTR_DEVICE_CLASS, @@ -51,9 +51,14 @@ from tests.components.switch import common DEFAULT_CONFIG = { - switch.DOMAIN: {"platform": "mqtt", "name": "test", "command_topic": "test-topic"} + mqtt.DOMAIN: {switch.DOMAIN: {"name": "test", "command_topic": "test-topic"}} } +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +DEFAULT_CONFIG_LEGACY = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) +DEFAULT_CONFIG_LEGACY[switch.DOMAIN]["platform"] = mqtt.DOMAIN + @pytest.fixture(autouse=True) def switch_platform_only(): @@ -66,16 +71,17 @@ async def test_controlling_state_via_topic(hass, mqtt_mock_entry_with_yaml_confi """Test the controlling state via topic.""" assert await async_setup_component( hass, - switch.DOMAIN, + mqtt.DOMAIN, { - switch.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "payload_on": 1, - "payload_off": 0, - "device_class": "switch", + mqtt.DOMAIN: { + switch.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "payload_on": 1, + "payload_off": 0, + "device_class": "switch", + } } }, ) @@ -112,15 +118,16 @@ async def test_sending_mqtt_commands_and_optimistic( assert await async_setup_component( hass, - switch.DOMAIN, + mqtt.DOMAIN, { - switch.DOMAIN: { - "platform": "mqtt", - "name": "test", - "command_topic": "command-topic", - "payload_on": "beer on", - "payload_off": "beer off", - "qos": "2", + mqtt.DOMAIN: { + switch.DOMAIN: { + "name": "test", + "command_topic": "command-topic", + "payload_on": "beer on", + "payload_off": "beer off", + "qos": "2", + } } }, ) @@ -155,12 +162,13 @@ async def test_sending_inital_state_and_optimistic( """Test the initial state in optimistic mode.""" assert await async_setup_component( hass, - switch.DOMAIN, + mqtt.DOMAIN, { - switch.DOMAIN: { - "platform": "mqtt", - "name": "test", - "command_topic": "command-topic", + mqtt.DOMAIN: { + switch.DOMAIN: { + "name": "test", + "command_topic": "command-topic", + } } }, ) @@ -178,16 +186,17 @@ async def test_controlling_state_via_topic_and_json_message( """Test the controlling state via topic and JSON message.""" assert await async_setup_component( hass, - switch.DOMAIN, + mqtt.DOMAIN, { - switch.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "payload_on": "beer on", - "payload_off": "beer off", - "value_template": "{{ value_json.val }}", + mqtt.DOMAIN: { + switch.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "payload_on": "beer on", + "payload_off": "beer off", + "value_template": "{{ value_json.val }}", + } } }, ) @@ -218,14 +227,14 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, switch.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, switch.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, switch.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, switch.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -281,17 +290,18 @@ async def test_custom_state_payload(hass, mqtt_mock_entry_with_yaml_config): """Test the state payload.""" assert await async_setup_component( hass, - switch.DOMAIN, + mqtt.DOMAIN, { - switch.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "payload_on": 1, - "payload_off": 0, - "state_on": "HIGH", - "state_off": "LOW", + mqtt.DOMAIN: { + switch.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "payload_on": 1, + "payload_off": 0, + "state_on": "HIGH", + "state_off": "LOW", + } } }, ) @@ -318,7 +328,7 @@ async def test_setting_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_with_yaml_config, switch.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, switch.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -327,14 +337,14 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_blocked_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_no_yaml_config, switch.DOMAIN, DEFAULT_CONFIG, {} + hass, mqtt_mock_entry_no_yaml_config, switch.DOMAIN, DEFAULT_CONFIG_LEGACY, {} ) async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_with_template( - hass, mqtt_mock_entry_with_yaml_config, switch.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, switch.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -343,7 +353,11 @@ async def test_update_with_json_attrs_not_dict( ): """Test attributes get extracted from a JSON result.""" await help_test_update_with_json_attrs_not_dict( - hass, mqtt_mock_entry_with_yaml_config, caplog, switch.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_with_yaml_config, + caplog, + switch.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) @@ -352,14 +366,22 @@ async def test_update_with_json_attrs_bad_JSON( ): """Test attributes get extracted from a JSON result.""" await help_test_update_with_json_attrs_bad_JSON( - hass, mqtt_mock_entry_with_yaml_config, caplog, switch.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_with_yaml_config, + caplog, + switch.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test update of discovered MQTTAttributes.""" await help_test_discovery_update_attr( - hass, mqtt_mock_entry_no_yaml_config, caplog, switch.DOMAIN, DEFAULT_CONFIG + hass, + mqtt_mock_entry_no_yaml_config, + caplog, + switch.DOMAIN, + DEFAULT_CONFIG_LEGACY, ) @@ -404,8 +426,8 @@ async def test_discovery_update_switch_topic_template( hass, mqtt_mock_entry_no_yaml_config, caplog ): """Test update of discovered switch.""" - config1 = copy.deepcopy(DEFAULT_CONFIG[switch.DOMAIN]) - config2 = copy.deepcopy(DEFAULT_CONFIG[switch.DOMAIN]) + config1 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[switch.DOMAIN]) + config2 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[switch.DOMAIN]) config1["name"] = "Beer" config2["name"] = "Milk" config1["state_topic"] = "switch/state1" @@ -441,8 +463,8 @@ async def test_discovery_update_switch_template( hass, mqtt_mock_entry_no_yaml_config, caplog ): """Test update of discovered switch.""" - config1 = copy.deepcopy(DEFAULT_CONFIG[switch.DOMAIN]) - config2 = copy.deepcopy(DEFAULT_CONFIG[switch.DOMAIN]) + config1 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[switch.DOMAIN]) + config2 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[switch.DOMAIN]) config1["name"] = "Beer" config2["name"] = "Milk" config1["state_topic"] = "switch/state1" @@ -512,42 +534,42 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT switch device registry integration.""" await help_test_entity_device_info_with_connection( - hass, mqtt_mock_entry_no_yaml_config, switch.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, switch.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT switch device registry integration.""" await help_test_entity_device_info_with_identifier( - hass, mqtt_mock_entry_no_yaml_config, switch.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, switch.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): """Test device registry update.""" await help_test_entity_device_info_update( - hass, mqtt_mock_entry_no_yaml_config, switch.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, switch.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test device registry remove.""" await help_test_entity_device_info_remove( - hass, mqtt_mock_entry_no_yaml_config, switch.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, switch.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_config): """Test MQTT subscriptions are managed when entity_id is updated.""" await help_test_entity_id_update_subscriptions( - hass, mqtt_mock_entry_with_yaml_config, switch.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_with_yaml_config, switch.DOMAIN, DEFAULT_CONFIG_LEGACY ) async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, switch.DOMAIN, DEFAULT_CONFIG + hass, mqtt_mock_entry_no_yaml_config, switch.DOMAIN, DEFAULT_CONFIG_LEGACY ) @@ -557,7 +579,7 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): hass, mqtt_mock_entry_no_yaml_config, switch.DOMAIN, - DEFAULT_CONFIG, + DEFAULT_CONFIG_LEGACY, switch.SERVICE_TURN_ON, ) @@ -593,7 +615,7 @@ async def test_publishing_with_custom_encoding( ): """Test publishing MQTT payload with different encoding.""" domain = switch.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_publishing_with_custom_encoding( hass, @@ -612,7 +634,7 @@ async def test_publishing_with_custom_encoding( async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = switch.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) @@ -621,7 +643,7 @@ async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_pa async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = switch.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_reloadable_late(hass, caplog, tmp_path, domain, config) @@ -646,7 +668,7 @@ async def test_encoding_subscribable_topics( mqtt_mock_entry_with_yaml_config, caplog, switch.DOMAIN, - DEFAULT_CONFIG[switch.DOMAIN], + DEFAULT_CONFIG_LEGACY[switch.DOMAIN], topic, value, attribute, @@ -657,7 +679,7 @@ async def test_encoding_subscribable_topics( async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = switch.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG[platform]) + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) config["name"] = "test" del config["platform"] await help_test_setup_manual_entity_from_yaml(hass, platform, config) @@ -667,7 +689,20 @@ async def test_setup_manual_entity_from_yaml(hass): async def test_unload_entry(hass, mqtt_mock_entry_with_yaml_config, tmp_path): """Test unloading the config entry.""" domain = switch.DOMAIN - config = DEFAULT_CONFIG[domain] + config = DEFAULT_CONFIG_LEGACY[domain] await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry_with_yaml_config, tmp_path, domain, config ) + + +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 +async def test_setup_with_legacy_schema(hass, mqtt_mock_entry_with_yaml_config): + """Test a setup with deprecated yaml platform schema.""" + domain = switch.DOMAIN + config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[domain]) + config["name"] = "test" + assert await async_setup_component(hass, domain, {domain: config}) + await hass.async_block_till_done() + await mqtt_mock_entry_with_yaml_config() + assert hass.states.get(f"{domain}.test") is not None From 4894e2e5a43e80a2f64d8f9486c7eb215fcdaa6b Mon Sep 17 00:00:00 2001 From: Jan Bouwhuis Date: Fri, 9 Sep 2022 11:15:48 +0200 Subject: [PATCH 04/23] Refactor common MQTT tests to use modern schema (#77583) * Common tests availability * Common tests attributes * Common tests unique id * Common tests discovery * Common tests encoding * Common tests device info * Common tests entity_id updated * Common tests entity debug info * Common test entity category * Common tests setup reload unload+corrections * Cleanup sweep * Comments from curent change * Cleanup * Remove unused legacy config --- .../mqtt/test_alarm_control_panel.py | 103 +++++---- tests/components/mqtt/test_binary_sensor.py | 103 +++++---- tests/components/mqtt/test_button.py | 103 ++++----- tests/components/mqtt/test_camera.py | 83 ++++--- tests/components/mqtt/test_climate.py | 113 +++++----- tests/components/mqtt/test_common.py | 202 +++++++++--------- tests/components/mqtt/test_cover.py | 85 ++++---- .../mqtt/test_device_tracker_discovery.py | 14 +- tests/components/mqtt/test_fan.py | 89 ++++---- tests/components/mqtt/test_humidifier.py | 93 ++++---- tests/components/mqtt/test_init.py | 38 +++- tests/components/mqtt/test_legacy_vacuum.py | 117 +++++----- tests/components/mqtt/test_light.py | 95 ++++---- tests/components/mqtt/test_light_json.py | 99 ++++----- tests/components/mqtt/test_light_template.py | 116 +++++----- tests/components/mqtt/test_lock.py | 87 ++++---- tests/components/mqtt/test_number.py | 93 ++++---- tests/components/mqtt/test_scene.py | 71 +++--- tests/components/mqtt/test_select.py | 99 +++++---- tests/components/mqtt/test_sensor.py | 110 +++++----- tests/components/mqtt/test_siren.py | 125 +++++------ tests/components/mqtt/test_state_vacuum.py | 87 ++++---- tests/components/mqtt/test_switch.py | 123 +++++------ 23 files changed, 1125 insertions(+), 1123 deletions(-) diff --git a/tests/components/mqtt/test_alarm_control_panel.py b/tests/components/mqtt/test_alarm_control_panel.py index e51ed9aeae951..d305d2ae7aacf 100644 --- a/tests/components/mqtt/test_alarm_control_panel.py +++ b/tests/components/mqtt/test_alarm_control_panel.py @@ -61,7 +61,7 @@ help_test_setup_manual_entity_from_yaml, help_test_unique_id, help_test_unload_config_entry_with_platform, - help_test_update_with_json_attrs_bad_JSON, + help_test_update_with_json_attrs_bad_json, help_test_update_with_json_attrs_not_dict, ) @@ -121,8 +121,6 @@ # Scheduled to be removed in HA core 2022.12 DEFAULT_CONFIG_LEGACY = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) DEFAULT_CONFIG_LEGACY[alarm_control_panel.DOMAIN]["platform"] = mqtt.DOMAIN -DEFAULT_CONFIG_CODE_LEGACY = copy.deepcopy(DEFAULT_CONFIG_CODE[mqtt.DOMAIN]) -DEFAULT_CONFIG_CODE_LEGACY[alarm_control_panel.DOMAIN]["platform"] = mqtt.DOMAIN @pytest.fixture(autouse=True) @@ -588,7 +586,7 @@ async def test_availability_when_connection_lost( hass, mqtt_mock_entry_with_yaml_config, alarm_control_panel.DOMAIN, - DEFAULT_CONFIG_CODE_LEGACY, + DEFAULT_CONFIG_CODE, ) @@ -598,7 +596,7 @@ async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config hass, mqtt_mock_entry_with_yaml_config, alarm_control_panel.DOMAIN, - DEFAULT_CONFIG_CODE_LEGACY, + DEFAULT_CONFIG_CODE, ) @@ -608,7 +606,7 @@ async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_conf hass, mqtt_mock_entry_with_yaml_config, alarm_control_panel.DOMAIN, - DEFAULT_CONFIG_CODE_LEGACY, + DEFAULT_CONFIG_CODE, ) @@ -618,7 +616,7 @@ async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_confi hass, mqtt_mock_entry_with_yaml_config, alarm_control_panel.DOMAIN, - DEFAULT_CONFIG_CODE_LEGACY, + DEFAULT_CONFIG, ) @@ -630,7 +628,7 @@ async def test_setting_attribute_via_mqtt_json_message( hass, mqtt_mock_entry_with_yaml_config, alarm_control_panel.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -642,7 +640,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( hass, mqtt_mock_entry_no_yaml_config, alarm_control_panel.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, MQTT_ALARM_ATTRIBUTES_BLOCKED, ) @@ -653,7 +651,7 @@ async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_c hass, mqtt_mock_entry_with_yaml_config, alarm_control_panel.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -666,20 +664,20 @@ async def test_update_with_json_attrs_not_dict( mqtt_mock_entry_with_yaml_config, caplog, alarm_control_panel.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) -async def test_update_with_json_attrs_bad_JSON( +async def test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog ): """Test attributes get extracted from a JSON result.""" - await help_test_update_with_json_attrs_bad_JSON( + await help_test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog, alarm_control_panel.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -690,29 +688,29 @@ async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplo mqtt_mock_entry_no_yaml_config, caplog, alarm_control_panel.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) async def test_unique_id(hass, mqtt_mock_entry_with_yaml_config): """Test unique id option only creates one alarm per unique_id.""" config = { - alarm_control_panel.DOMAIN: [ - { - "platform": "mqtt", - "name": "Test 1", - "state_topic": "test-topic", - "command_topic": "command-topic", - "unique_id": "TOTALLY_UNIQUE", - }, - { - "platform": "mqtt", - "name": "Test 2", - "state_topic": "test-topic", - "command_topic": "command-topic", - "unique_id": "TOTALLY_UNIQUE", - }, - ] + mqtt.DOMAIN: { + alarm_control_panel.DOMAIN: [ + { + "name": "Test 1", + "state_topic": "test-topic", + "command_topic": "command-topic", + "unique_id": "TOTALLY_UNIQUE", + }, + { + "name": "Test 2", + "state_topic": "test-topic", + "command_topic": "command-topic", + "unique_id": "TOTALLY_UNIQUE", + }, + ] + } } await help_test_unique_id( hass, mqtt_mock_entry_with_yaml_config, alarm_control_panel.DOMAIN, config @@ -721,7 +719,7 @@ async def test_unique_id(hass, mqtt_mock_entry_with_yaml_config): async def test_discovery_removal_alarm(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test removal of discovered alarm_control_panel.""" - data = json.dumps(DEFAULT_CONFIG_LEGACY[alarm_control_panel.DOMAIN]) + data = json.dumps(DEFAULT_CONFIG[mqtt.DOMAIN][alarm_control_panel.DOMAIN]) await help_test_discovery_removal( hass, mqtt_mock_entry_no_yaml_config, caplog, alarm_control_panel.DOMAIN, data ) @@ -731,8 +729,8 @@ async def test_discovery_update_alarm_topic_and_template( hass, mqtt_mock_entry_no_yaml_config, caplog ): """Test update of discovered alarm_control_panel.""" - config1 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[alarm_control_panel.DOMAIN]) - config2 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[alarm_control_panel.DOMAIN]) + config1 = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][alarm_control_panel.DOMAIN]) + config2 = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][alarm_control_panel.DOMAIN]) config1["name"] = "Beer" config2["name"] = "Milk" config1["state_topic"] = "alarm/state1" @@ -766,8 +764,8 @@ async def test_discovery_update_alarm_template( hass, mqtt_mock_entry_no_yaml_config, caplog ): """Test update of discovered alarm_control_panel.""" - config1 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[alarm_control_panel.DOMAIN]) - config2 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[alarm_control_panel.DOMAIN]) + config1 = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][alarm_control_panel.DOMAIN]) + config2 = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][alarm_control_panel.DOMAIN]) config1["name"] = "Beer" config2["name"] = "Milk" config1["state_topic"] = "alarm/state1" @@ -799,7 +797,7 @@ async def test_discovery_update_unchanged_alarm( hass, mqtt_mock_entry_no_yaml_config, caplog ): """Test update of discovered alarm_control_panel.""" - config1 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[alarm_control_panel.DOMAIN]) + config1 = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][alarm_control_panel.DOMAIN]) config1["name"] = "Beer" data1 = json.dumps(config1) @@ -851,7 +849,7 @@ async def test_encoding_subscribable_topics( mqtt_mock_entry_with_yaml_config, caplog, alarm_control_panel.DOMAIN, - DEFAULT_CONFIG_LEGACY[alarm_control_panel.DOMAIN], + DEFAULT_CONFIG[mqtt.DOMAIN][alarm_control_panel.DOMAIN], topic, value, ) @@ -863,7 +861,7 @@ async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_ hass, mqtt_mock_entry_no_yaml_config, alarm_control_panel.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -873,7 +871,7 @@ async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_ hass, mqtt_mock_entry_no_yaml_config, alarm_control_panel.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -883,7 +881,7 @@ async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): hass, mqtt_mock_entry_no_yaml_config, alarm_control_panel.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -893,7 +891,7 @@ async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): hass, mqtt_mock_entry_no_yaml_config, alarm_control_panel.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -903,7 +901,7 @@ async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_co hass, mqtt_mock_entry_with_yaml_config, alarm_control_panel.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -913,7 +911,7 @@ async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_c hass, mqtt_mock_entry_no_yaml_config, alarm_control_panel.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -923,7 +921,7 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): hass, mqtt_mock_entry_no_yaml_config, alarm_control_panel.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, alarm_control_panel.SERVICE_ALARM_DISARM, command_payload="DISARM", ) @@ -966,7 +964,7 @@ async def test_publishing_with_custom_encoding( ): """Test publishing MQTT payload with different encoding.""" domain = alarm_control_panel.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_publishing_with_custom_encoding( hass, @@ -987,12 +985,14 @@ async def test_publishing_with_custom_encoding( async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = alarm_control_panel.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = alarm_control_panel.DOMAIN @@ -1003,17 +1003,14 @@ async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = alarm_control_panel.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) - config["name"] = "test" - del config["platform"] - await help_test_setup_manual_entity_from_yaml(hass, platform, config) - assert hass.states.get(f"{platform}.test") is not None + await help_test_setup_manual_entity_from_yaml(hass, DEFAULT_CONFIG) + assert hass.states.get(f"{platform}.test") async def test_unload_entry(hass, mqtt_mock_entry_with_yaml_config, tmp_path): """Test unloading the config entry.""" domain = alarm_control_panel.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry_with_yaml_config, tmp_path, domain, config ) diff --git a/tests/components/mqtt/test_binary_sensor.py b/tests/components/mqtt/test_binary_sensor.py index bbe8b97870768..48acde5c6c942 100644 --- a/tests/components/mqtt/test_binary_sensor.py +++ b/tests/components/mqtt/test_binary_sensor.py @@ -45,7 +45,7 @@ help_test_setup_manual_entity_from_yaml, help_test_unique_id, help_test_unload_config_entry_with_platform, - help_test_update_with_json_attrs_bad_JSON, + help_test_update_with_json_attrs_bad_json, help_test_update_with_json_attrs_not_dict, ) @@ -542,7 +542,7 @@ async def test_availability_when_connection_lost( hass, mqtt_mock_entry_with_yaml_config, binary_sensor.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -552,7 +552,7 @@ async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config hass, mqtt_mock_entry_with_yaml_config, binary_sensor.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -562,7 +562,7 @@ async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_conf hass, mqtt_mock_entry_with_yaml_config, binary_sensor.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -572,7 +572,7 @@ async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_confi hass, mqtt_mock_entry_with_yaml_config, binary_sensor.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -708,7 +708,7 @@ async def test_setting_attribute_via_mqtt_json_message( hass, mqtt_mock_entry_with_yaml_config, binary_sensor.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -718,7 +718,7 @@ async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_c hass, mqtt_mock_entry_with_yaml_config, binary_sensor.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -731,20 +731,20 @@ async def test_update_with_json_attrs_not_dict( mqtt_mock_entry_with_yaml_config, caplog, binary_sensor.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) -async def test_update_with_json_attrs_bad_JSON( +async def test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog ): """Test attributes get extracted from a JSON result.""" - await help_test_update_with_json_attrs_bad_JSON( + await help_test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog, binary_sensor.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -755,27 +755,27 @@ async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplo mqtt_mock_entry_no_yaml_config, caplog, binary_sensor.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) async def test_unique_id(hass, mqtt_mock_entry_with_yaml_config): """Test unique id option only creates one sensor per unique_id.""" config = { - binary_sensor.DOMAIN: [ - { - "platform": "mqtt", - "name": "Test 1", - "state_topic": "test-topic", - "unique_id": "TOTALLY_UNIQUE", - }, - { - "platform": "mqtt", - "name": "Test 2", - "state_topic": "test-topic", - "unique_id": "TOTALLY_UNIQUE", - }, - ] + mqtt.DOMAIN: { + binary_sensor.DOMAIN: [ + { + "name": "Test 1", + "state_topic": "test-topic", + "unique_id": "TOTALLY_UNIQUE", + }, + { + "name": "Test 2", + "state_topic": "test-topic", + "unique_id": "TOTALLY_UNIQUE", + }, + ] + } } await help_test_unique_id( hass, mqtt_mock_entry_with_yaml_config, binary_sensor.DOMAIN, config @@ -786,7 +786,7 @@ async def test_discovery_removal_binary_sensor( hass, mqtt_mock_entry_no_yaml_config, caplog ): """Test removal of discovered binary_sensor.""" - data = json.dumps(DEFAULT_CONFIG_LEGACY[binary_sensor.DOMAIN]) + data = json.dumps(DEFAULT_CONFIG[mqtt.DOMAIN][binary_sensor.DOMAIN]) await help_test_discovery_removal( hass, mqtt_mock_entry_no_yaml_config, caplog, binary_sensor.DOMAIN, data ) @@ -796,8 +796,8 @@ async def test_discovery_update_binary_sensor_topic_template( hass, mqtt_mock_entry_no_yaml_config, caplog ): """Test update of discovered binary_sensor.""" - config1 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[binary_sensor.DOMAIN]) - config2 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[binary_sensor.DOMAIN]) + config1 = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][binary_sensor.DOMAIN]) + config2 = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][binary_sensor.DOMAIN]) config1["name"] = "Beer" config2["name"] = "Milk" config1["state_topic"] = "sensor/state1" @@ -833,8 +833,8 @@ async def test_discovery_update_binary_sensor_template( hass, mqtt_mock_entry_no_yaml_config, caplog ): """Test update of discovered binary_sensor.""" - config1 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[binary_sensor.DOMAIN]) - config2 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[binary_sensor.DOMAIN]) + config1 = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][binary_sensor.DOMAIN]) + config2 = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][binary_sensor.DOMAIN]) config1["name"] = "Beer" config2["name"] = "Milk" config1["state_topic"] = "sensor/state1" @@ -892,7 +892,7 @@ async def test_encoding_subscribable_topics( mqtt_mock_entry_with_yaml_config, caplog, binary_sensor.DOMAIN, - DEFAULT_CONFIG_LEGACY[binary_sensor.DOMAIN], + DEFAULT_CONFIG[mqtt.DOMAIN][binary_sensor.DOMAIN], topic, value, attribute, @@ -904,7 +904,7 @@ async def test_discovery_update_unchanged_binary_sensor( hass, mqtt_mock_entry_no_yaml_config, caplog ): """Test update of discovered binary_sensor.""" - config1 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[binary_sensor.DOMAIN]) + config1 = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][binary_sensor.DOMAIN]) config1["name"] = "Beer" data1 = json.dumps(config1) @@ -942,7 +942,7 @@ async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_ hass, mqtt_mock_entry_no_yaml_config, binary_sensor.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -952,7 +952,7 @@ async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_ hass, mqtt_mock_entry_no_yaml_config, binary_sensor.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -962,7 +962,7 @@ async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): hass, mqtt_mock_entry_no_yaml_config, binary_sensor.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -972,7 +972,7 @@ async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): hass, mqtt_mock_entry_no_yaml_config, binary_sensor.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -982,7 +982,7 @@ async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_co hass, mqtt_mock_entry_with_yaml_config, binary_sensor.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -992,7 +992,7 @@ async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_c hass, mqtt_mock_entry_no_yaml_config, binary_sensor.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -1002,7 +1002,7 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): hass, mqtt_mock_entry_no_yaml_config, binary_sensor.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, None, ) @@ -1010,12 +1010,14 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = binary_sensor.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = binary_sensor.DOMAIN @@ -1040,11 +1042,11 @@ async def test_cleanup_triggers_and_restoring_state( ): """Test cleanup old triggers at reloading and restoring the state.""" domain = binary_sensor.DOMAIN - config1 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[domain]) + config1 = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][domain]) config1["name"] = "test1" config1["expire_after"] = 30 config1["state_topic"] = "test-topic1" - config2 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[domain]) + config2 = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][domain]) config2["name"] = "test2" config2["expire_after"] = 5 config2["state_topic"] = "test-topic2" @@ -1053,8 +1055,8 @@ async def test_cleanup_triggers_and_restoring_state( assert await async_setup_component( hass, - binary_sensor.DOMAIN, - {binary_sensor.DOMAIN: [config1, config2]}, + mqtt.DOMAIN, + {mqtt.DOMAIN: {binary_sensor.DOMAIN: [config1, config2]}}, ) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -1070,7 +1072,7 @@ async def test_cleanup_triggers_and_restoring_state( freezer.move_to("2022-02-02 12:01:10+01:00") await help_test_reload_with_config( - hass, caplog, tmp_path, {domain: [config1, config2]} + hass, caplog, tmp_path, {mqtt.DOMAIN: {domain: [config1, config2]}} ) assert "Clean up expire after trigger for binary_sensor.test1" in caplog.text assert "Clean up expire after trigger for binary_sensor.test2" not in caplog.text @@ -1125,17 +1127,14 @@ async def test_skip_restoring_state_with_over_due_expire_trigger( async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = binary_sensor.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) - config["name"] = "test" - del config["platform"] - await help_test_setup_manual_entity_from_yaml(hass, platform, config) - assert hass.states.get(f"{platform}.test") is not None + await help_test_setup_manual_entity_from_yaml(hass, DEFAULT_CONFIG) + assert hass.states.get(f"{platform}.test") async def test_unload_entry(hass, mqtt_mock_entry_with_yaml_config, tmp_path): """Test unloading the config entry.""" domain = binary_sensor.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry_with_yaml_config, tmp_path, domain, config ) diff --git a/tests/components/mqtt/test_button.py b/tests/components/mqtt/test_button.py index 1274c700800b8..80e5ce60a474d 100644 --- a/tests/components/mqtt/test_button.py +++ b/tests/components/mqtt/test_button.py @@ -38,7 +38,7 @@ help_test_setup_manual_entity_from_yaml, help_test_unique_id, help_test_unload_config_entry_with_platform, - help_test_update_with_json_attrs_bad_JSON, + help_test_update_with_json_attrs_bad_json, help_test_update_with_json_attrs_not_dict, ) @@ -140,25 +140,26 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, button.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, button.DOMAIN, DEFAULT_CONFIG ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, button.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, button.DOMAIN, DEFAULT_CONFIG ) async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by default payload with defined topic.""" config = { - button.DOMAIN: { - "platform": "mqtt", - "name": "test", - "command_topic": "command-topic", - "payload_press": 1, + mqtt.DOMAIN: { + button.DOMAIN: { + "name": "test", + "command_topic": "command-topic", + "payload_press": 1, + } } } @@ -176,11 +177,12 @@ async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_conf async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by custom payload with defined topic.""" config = { - button.DOMAIN: { - "platform": "mqtt", - "name": "test", - "command_topic": "command-topic", - "payload_press": 1, + mqtt.DOMAIN: { + button.DOMAIN: { + "name": "test", + "command_topic": "command-topic", + "payload_press": 1, + } } } @@ -200,7 +202,7 @@ async def test_setting_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_with_yaml_config, button.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, button.DOMAIN, DEFAULT_CONFIG ) @@ -209,14 +211,14 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_blocked_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_no_yaml_config, button.DOMAIN, DEFAULT_CONFIG_LEGACY, None + hass, mqtt_mock_entry_no_yaml_config, button.DOMAIN, DEFAULT_CONFIG, None ) async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_with_template( - hass, mqtt_mock_entry_with_yaml_config, button.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, button.DOMAIN, DEFAULT_CONFIG ) @@ -229,20 +231,20 @@ async def test_update_with_json_attrs_not_dict( mqtt_mock_entry_with_yaml_config, caplog, button.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) -async def test_update_with_json_attrs_bad_JSON( +async def test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog ): """Test attributes get extracted from a JSON result.""" - await help_test_update_with_json_attrs_bad_JSON( + await help_test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog, button.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -253,27 +255,27 @@ async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplo mqtt_mock_entry_no_yaml_config, caplog, button.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) async def test_unique_id(hass, mqtt_mock_entry_with_yaml_config): """Test unique id option only creates one button per unique_id.""" config = { - button.DOMAIN: [ - { - "platform": "mqtt", - "name": "Test 1", - "command_topic": "command-topic", - "unique_id": "TOTALLY_UNIQUE", - }, - { - "platform": "mqtt", - "name": "Test 2", - "command_topic": "command-topic", - "unique_id": "TOTALLY_UNIQUE", - }, - ] + mqtt.DOMAIN: { + button.DOMAIN: [ + { + "name": "Test 1", + "command_topic": "command-topic", + "unique_id": "TOTALLY_UNIQUE", + }, + { + "name": "Test 2", + "command_topic": "command-topic", + "unique_id": "TOTALLY_UNIQUE", + }, + ] + } } await help_test_unique_id( hass, mqtt_mock_entry_with_yaml_config, button.DOMAIN, config @@ -290,8 +292,8 @@ async def test_discovery_removal_button(hass, mqtt_mock_entry_no_yaml_config, ca async def test_discovery_update_button(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test update of discovered button.""" - config1 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[button.DOMAIN]) - config2 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[button.DOMAIN]) + config1 = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][button.DOMAIN]) + config2 = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][button.DOMAIN]) config1["name"] = "Beer" config2["name"] = "Milk" @@ -340,35 +342,35 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT button device registry integration.""" await help_test_entity_device_info_with_connection( - hass, mqtt_mock_entry_no_yaml_config, button.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, button.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT button device registry integration.""" await help_test_entity_device_info_with_identifier( - hass, mqtt_mock_entry_no_yaml_config, button.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, button.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): """Test device registry update.""" await help_test_entity_device_info_update( - hass, mqtt_mock_entry_no_yaml_config, button.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, button.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test device registry remove.""" await help_test_entity_device_info_remove( - hass, mqtt_mock_entry_no_yaml_config, button.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, button.DOMAIN, DEFAULT_CONFIG ) async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, button.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, button.DOMAIN, DEFAULT_CONFIG ) @@ -378,7 +380,7 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): hass, mqtt_mock_entry_no_yaml_config, button.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, button.SERVICE_PRESS, command_payload="PRESS", state_topic=None, @@ -457,7 +459,7 @@ async def test_publishing_with_custom_encoding( ): """Test publishing MQTT payload with different encoding.""" domain = button.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_publishing_with_custom_encoding( hass, @@ -476,12 +478,14 @@ async def test_publishing_with_custom_encoding( async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = button.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = button.DOMAIN @@ -492,17 +496,14 @@ async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = button.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) - config["name"] = "test" - del config["platform"] - await help_test_setup_manual_entity_from_yaml(hass, platform, config) - assert hass.states.get(f"{platform}.test") is not None + await help_test_setup_manual_entity_from_yaml(hass, DEFAULT_CONFIG) + assert hass.states.get(f"{platform}.test") async def test_unload_entry(hass, mqtt_mock_entry_with_yaml_config, tmp_path): """Test unloading the config entry.""" domain = button.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry_with_yaml_config, tmp_path, domain, config ) diff --git a/tests/components/mqtt/test_camera.py b/tests/components/mqtt/test_camera.py index 4d0b2fbfca062..4cb6afb64953d 100644 --- a/tests/components/mqtt/test_camera.py +++ b/tests/components/mqtt/test_camera.py @@ -37,7 +37,7 @@ help_test_setup_manual_entity_from_yaml, help_test_unique_id, help_test_unload_config_entry_with_platform, - help_test_update_with_json_attrs_bad_JSON, + help_test_update_with_json_attrs_bad_json, help_test_update_with_json_attrs_not_dict, ) @@ -195,28 +195,28 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, camera.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, camera.DOMAIN, DEFAULT_CONFIG ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, camera.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, camera.DOMAIN, DEFAULT_CONFIG ) async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by default payload with defined topic.""" await help_test_default_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, camera.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, camera.DOMAIN, DEFAULT_CONFIG ) async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by custom payload with defined topic.""" await help_test_custom_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, camera.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, camera.DOMAIN, DEFAULT_CONFIG ) @@ -225,7 +225,7 @@ async def test_setting_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_with_yaml_config, camera.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, camera.DOMAIN, DEFAULT_CONFIG ) @@ -237,7 +237,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( hass, mqtt_mock_entry_no_yaml_config, camera.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, MQTT_CAMERA_ATTRIBUTES_BLOCKED, ) @@ -245,7 +245,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_with_template( - hass, mqtt_mock_entry_with_yaml_config, camera.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, camera.DOMAIN, DEFAULT_CONFIG ) @@ -258,20 +258,20 @@ async def test_update_with_json_attrs_not_dict( mqtt_mock_entry_with_yaml_config, caplog, camera.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) -async def test_update_with_json_attrs_bad_JSON( +async def test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog ): """Test attributes get extracted from a JSON result.""" - await help_test_update_with_json_attrs_bad_JSON( + await help_test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog, camera.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -282,27 +282,27 @@ async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplo mqtt_mock_entry_no_yaml_config, caplog, camera.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) async def test_unique_id(hass, mqtt_mock_entry_with_yaml_config): """Test unique id option only creates one camera per unique_id.""" config = { - camera.DOMAIN: [ - { - "platform": "mqtt", - "name": "Test 1", - "topic": "test-topic", - "unique_id": "TOTALLY_UNIQUE", - }, - { - "platform": "mqtt", - "name": "Test 2", - "topic": "test-topic", - "unique_id": "TOTALLY_UNIQUE", - }, - ] + mqtt.DOMAIN: { + camera.DOMAIN: [ + { + "name": "Test 1", + "topic": "test-topic", + "unique_id": "TOTALLY_UNIQUE", + }, + { + "name": "Test 2", + "topic": "test-topic", + "unique_id": "TOTALLY_UNIQUE", + }, + ] + } } await help_test_unique_id( hass, mqtt_mock_entry_with_yaml_config, camera.DOMAIN, config @@ -311,7 +311,7 @@ async def test_unique_id(hass, mqtt_mock_entry_with_yaml_config): async def test_discovery_removal_camera(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test removal of discovered camera.""" - data = json.dumps(DEFAULT_CONFIG_LEGACY[camera.DOMAIN]) + data = json.dumps(DEFAULT_CONFIG[mqtt.DOMAIN][camera.DOMAIN]) await help_test_discovery_removal( hass, mqtt_mock_entry_no_yaml_config, caplog, camera.DOMAIN, data ) @@ -359,28 +359,28 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT camera device registry integration.""" await help_test_entity_device_info_with_connection( - hass, mqtt_mock_entry_no_yaml_config, camera.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, camera.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT camera device registry integration.""" await help_test_entity_device_info_with_identifier( - hass, mqtt_mock_entry_no_yaml_config, camera.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, camera.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): """Test device registry update.""" await help_test_entity_device_info_update( - hass, mqtt_mock_entry_no_yaml_config, camera.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, camera.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test device registry remove.""" await help_test_entity_device_info_remove( - hass, mqtt_mock_entry_no_yaml_config, camera.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, camera.DOMAIN, DEFAULT_CONFIG ) @@ -390,7 +390,7 @@ async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_co hass, mqtt_mock_entry_with_yaml_config, camera.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ["test_topic"], ) @@ -398,7 +398,7 @@ async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_co async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, camera.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, camera.DOMAIN, DEFAULT_CONFIG ) @@ -408,7 +408,7 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): hass, mqtt_mock_entry_no_yaml_config, camera.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, None, state_topic="test_topic", state_payload=b"ON", @@ -418,12 +418,14 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = camera.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = camera.DOMAIN @@ -434,17 +436,14 @@ async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = camera.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) - config["name"] = "test" - del config["platform"] - await help_test_setup_manual_entity_from_yaml(hass, platform, config) - assert hass.states.get(f"{platform}.test") is not None + await help_test_setup_manual_entity_from_yaml(hass, DEFAULT_CONFIG) + assert hass.states.get(f"{platform}.test") async def test_unload_entry(hass, mqtt_mock_entry_with_yaml_config, tmp_path): """Test unloading the config entry.""" domain = camera.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry_with_yaml_config, tmp_path, domain, config ) diff --git a/tests/components/mqtt/test_climate.py b/tests/components/mqtt/test_climate.py index 14bd9084abe4e..ec2501e11d3f6 100644 --- a/tests/components/mqtt/test_climate.py +++ b/tests/components/mqtt/test_climate.py @@ -52,7 +52,7 @@ help_test_setup_manual_entity_from_yaml, help_test_unique_id, help_test_unload_config_entry_with_platform, - help_test_update_with_json_attrs_bad_JSON, + help_test_update_with_json_attrs_bad_json, help_test_update_with_json_attrs_not_dict, ) @@ -686,28 +686,28 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, climate.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, climate.DOMAIN, DEFAULT_CONFIG ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, climate.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, climate.DOMAIN, DEFAULT_CONFIG ) async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by default payload with defined topic.""" await help_test_default_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, climate.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, climate.DOMAIN, DEFAULT_CONFIG ) async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by custom payload with defined topic.""" await help_test_custom_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, climate.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, climate.DOMAIN, DEFAULT_CONFIG ) @@ -994,7 +994,7 @@ async def test_setting_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_with_yaml_config, climate.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, climate.DOMAIN, DEFAULT_CONFIG ) @@ -1006,7 +1006,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( hass, mqtt_mock_entry_no_yaml_config, climate.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, MQTT_CLIMATE_ATTRIBUTES_BLOCKED, ) @@ -1014,7 +1014,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_with_template( - hass, mqtt_mock_entry_with_yaml_config, climate.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, climate.DOMAIN, DEFAULT_CONFIG ) @@ -1027,20 +1027,20 @@ async def test_update_with_json_attrs_not_dict( mqtt_mock_entry_with_yaml_config, caplog, climate.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) -async def test_update_with_json_attrs_bad_JSON( +async def test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog ): """Test attributes get extracted from a JSON result.""" - await help_test_update_with_json_attrs_bad_JSON( + await help_test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog, climate.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -1051,29 +1051,29 @@ async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplo mqtt_mock_entry_no_yaml_config, caplog, climate.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) async def test_unique_id(hass, mqtt_mock_entry_with_yaml_config): """Test unique id option only creates one climate per unique_id.""" config = { - climate.DOMAIN: [ - { - "platform": "mqtt", - "name": "Test 1", - "power_state_topic": "test-topic", - "power_command_topic": "test_topic", - "unique_id": "TOTALLY_UNIQUE", - }, - { - "platform": "mqtt", - "name": "Test 2", - "power_state_topic": "test-topic", - "power_command_topic": "test_topic", - "unique_id": "TOTALLY_UNIQUE", - }, - ] + mqtt.DOMAIN: { + climate.DOMAIN: [ + { + "name": "Test 1", + "power_state_topic": "test-topic", + "power_command_topic": "test_topic", + "unique_id": "TOTALLY_UNIQUE", + }, + { + "name": "Test 2", + "power_state_topic": "test-topic", + "power_command_topic": "test_topic", + "unique_id": "TOTALLY_UNIQUE", + }, + ] + } } await help_test_unique_id( hass, mqtt_mock_entry_with_yaml_config, climate.DOMAIN, config @@ -1106,7 +1106,7 @@ async def test_encoding_subscribable_topics( attribute_value, ): """Test handling of incoming encoded payload.""" - config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[climate.DOMAIN]) + config = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][climate.DOMAIN]) await help_test_encoding_subscribable_topics( hass, mqtt_mock_entry_with_yaml_config, @@ -1122,7 +1122,7 @@ async def test_encoding_subscribable_topics( async def test_discovery_removal_climate(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test removal of discovered climate.""" - data = json.dumps(DEFAULT_CONFIG_LEGACY[climate.DOMAIN]) + data = json.dumps(DEFAULT_CONFIG[mqtt.DOMAIN][climate.DOMAIN]) await help_test_discovery_removal( hass, mqtt_mock_entry_no_yaml_config, caplog, climate.DOMAIN, data ) @@ -1168,39 +1168,40 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT climate device registry integration.""" await help_test_entity_device_info_with_connection( - hass, mqtt_mock_entry_no_yaml_config, climate.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, climate.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT climate device registry integration.""" await help_test_entity_device_info_with_identifier( - hass, mqtt_mock_entry_no_yaml_config, climate.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, climate.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): """Test device registry update.""" await help_test_entity_device_info_update( - hass, mqtt_mock_entry_no_yaml_config, climate.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, climate.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test device registry remove.""" await help_test_entity_device_info_remove( - hass, mqtt_mock_entry_no_yaml_config, climate.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, climate.DOMAIN, DEFAULT_CONFIG ) async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_config): """Test MQTT subscriptions are managed when entity_id is updated.""" config = { - climate.DOMAIN: { - "platform": "mqtt", - "name": "test", - "mode_state_topic": "test-topic", - "availability_topic": "avty-topic", + mqtt.DOMAIN: { + climate.DOMAIN: { + "name": "test", + "mode_state_topic": "test-topic", + "availability_topic": "avty-topic", + } } } await help_test_entity_id_update_subscriptions( @@ -1215,18 +1216,19 @@ async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_co async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, climate.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, climate.DOMAIN, DEFAULT_CONFIG ) async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT debug info.""" config = { - climate.DOMAIN: { - "platform": "mqtt", - "name": "test", - "mode_command_topic": "command-topic", - "mode_state_topic": "test-topic", + mqtt.DOMAIN: { + climate.DOMAIN: { + "name": "test", + "mode_command_topic": "command-topic", + "mode_state_topic": "test-topic", + } } } await help_test_entity_debug_info_message( @@ -1375,10 +1377,10 @@ async def test_publishing_with_custom_encoding( ): """Test publishing MQTT payload with different encoding.""" domain = climate.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[domain]) + config = copy.deepcopy(DEFAULT_CONFIG) if topic != "preset_mode_command_topic": - del config["preset_mode_command_topic"] - del config["preset_modes"] + del config[mqtt.DOMAIN][domain]["preset_mode_command_topic"] + del config[mqtt.DOMAIN][domain]["preset_modes"] await help_test_publishing_with_custom_encoding( hass, @@ -1397,12 +1399,14 @@ async def test_publishing_with_custom_encoding( async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = climate.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = climate.DOMAIN @@ -1413,17 +1417,14 @@ async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = climate.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) - config["name"] = "test" - del config["platform"] - await help_test_setup_manual_entity_from_yaml(hass, platform, config) - assert hass.states.get(f"{platform}.test") is not None + await help_test_setup_manual_entity_from_yaml(hass, DEFAULT_CONFIG) + assert hass.states.get(f"{platform}.test") async def test_unload_entry(hass, mqtt_mock_entry_with_yaml_config, tmp_path): """Test unloading the config entry.""" domain = climate.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry_with_yaml_config, tmp_path, domain, config ) diff --git a/tests/components/mqtt/test_common.py b/tests/components/mqtt/test_common.py index ac8ef98531eb0..e2411f9fc6c94 100644 --- a/tests/components/mqtt/test_common.py +++ b/tests/components/mqtt/test_common.py @@ -53,7 +53,7 @@ async def help_test_availability_when_connection_lost( hass, mqtt_mock_entry_with_yaml_config, domain, config ): """Test availability after MQTT disconnection.""" - assert await async_setup_component(hass, domain, config) + assert await async_setup_component(hass, mqtt.DOMAIN, config) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -72,8 +72,8 @@ async def help_test_availability_without_topic( hass, mqtt_mock_entry_with_yaml_config, domain, config ): """Test availability without defined availability topic.""" - assert "availability_topic" not in config[domain] - assert await async_setup_component(hass, domain, config) + assert "availability_topic" not in config[mqtt.DOMAIN][domain] + assert await async_setup_component(hass, mqtt.DOMAIN, config) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -96,10 +96,10 @@ async def help_test_default_availability_payload( """ # Add availability settings to config config = copy.deepcopy(config) - config[domain]["availability_topic"] = "availability-topic" + config[mqtt.DOMAIN][domain]["availability_topic"] = "availability-topic" assert await async_setup_component( hass, - domain, + mqtt.DOMAIN, config, ) await hass.async_block_till_done() @@ -147,13 +147,13 @@ async def help_test_default_availability_list_payload( """ # Add availability settings to config config = copy.deepcopy(config) - config[domain]["availability"] = [ + config[mqtt.DOMAIN][domain]["availability"] = [ {"topic": "availability-topic1"}, {"topic": "availability-topic2"}, ] assert await async_setup_component( hass, - domain, + mqtt.DOMAIN, config, ) await hass.async_block_till_done() @@ -213,14 +213,14 @@ async def help_test_default_availability_list_payload_all( """ # Add availability settings to config config = copy.deepcopy(config) - config[domain]["availability_mode"] = "all" - config[domain]["availability"] = [ + config[mqtt.DOMAIN][domain]["availability_mode"] = "all" + config[mqtt.DOMAIN][domain]["availability"] = [ {"topic": "availability-topic1"}, {"topic": "availability-topic2"}, ] assert await async_setup_component( hass, - domain, + mqtt.DOMAIN, config, ) await hass.async_block_till_done() @@ -281,14 +281,14 @@ async def help_test_default_availability_list_payload_any( """ # Add availability settings to config config = copy.deepcopy(config) - config[domain]["availability_mode"] = "any" - config[domain]["availability"] = [ + config[mqtt.DOMAIN][domain]["availability_mode"] = "any" + config[mqtt.DOMAIN][domain]["availability"] = [ {"topic": "availability-topic1"}, {"topic": "availability-topic2"}, ] assert await async_setup_component( hass, - domain, + mqtt.DOMAIN, config, ) await hass.async_block_till_done() @@ -331,7 +331,6 @@ async def help_test_default_availability_list_payload_any( async def help_test_default_availability_list_single( hass, - mqtt_mock_entry_with_yaml_config, caplog, domain, config, @@ -345,22 +344,17 @@ async def help_test_default_availability_list_single( """ # Add availability settings to config config = copy.deepcopy(config) - config[domain]["availability"] = [ + config[mqtt.DOMAIN][domain]["availability"] = [ {"topic": "availability-topic1"}, ] - config[domain]["availability_topic"] = "availability-topic" - assert await async_setup_component( + config[mqtt.DOMAIN][domain]["availability_topic"] = "availability-topic" + assert not await async_setup_component( hass, - domain, + mqtt.DOMAIN, config, ) - await hass.async_block_till_done() - await mqtt_mock_entry_with_yaml_config() - - state = hass.states.get(f"{domain}.test") - assert state is None assert ( - "Invalid config for [sensor.mqtt]: two or more values in the same group of exclusion 'availability'" + "Invalid config for [mqtt]: two or more values in the same group of exclusion 'availability'" in caplog.text ) @@ -380,12 +374,12 @@ async def help_test_custom_availability_payload( """ # Add availability settings to config config = copy.deepcopy(config) - config[domain]["availability_topic"] = "availability-topic" - config[domain]["payload_available"] = "good" - config[domain]["payload_not_available"] = "nogood" + config[mqtt.DOMAIN][domain]["availability_topic"] = "availability-topic" + config[mqtt.DOMAIN][domain]["payload_available"] = "good" + config[mqtt.DOMAIN][domain]["payload_not_available"] = "nogood" assert await async_setup_component( hass, - domain, + mqtt.DOMAIN, config, ) await hass.async_block_till_done() @@ -434,17 +428,17 @@ async def help_test_discovery_update_availability( await mqtt_mock_entry_no_yaml_config() # Add availability settings to config config1 = copy.deepcopy(config) - config1[domain]["availability_topic"] = "availability-topic1" + config1[mqtt.DOMAIN][domain]["availability_topic"] = "availability-topic1" config2 = copy.deepcopy(config) - config2[domain]["availability"] = [ + config2[mqtt.DOMAIN][domain]["availability"] = [ {"topic": "availability-topic2"}, {"topic": "availability-topic3"}, ] config3 = copy.deepcopy(config) - config3[domain]["availability_topic"] = "availability-topic4" - data1 = json.dumps(config1[domain]) - data2 = json.dumps(config2[domain]) - data3 = json.dumps(config3[domain]) + config3[mqtt.DOMAIN][domain]["availability_topic"] = "availability-topic4" + data1 = json.dumps(config1[mqtt.DOMAIN][domain]) + data2 = json.dumps(config2[mqtt.DOMAIN][domain]) + data3 = json.dumps(config3[mqtt.DOMAIN][domain]) async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", data1) await hass.async_block_till_done() @@ -508,10 +502,10 @@ async def help_test_setting_attribute_via_mqtt_json_message( """ # Add JSON attributes settings to config config = copy.deepcopy(config) - config[domain]["json_attributes_topic"] = "attr-topic" + config[mqtt.DOMAIN][domain]["json_attributes_topic"] = "attr-topic" assert await async_setup_component( hass, - domain, + mqtt.DOMAIN, config, ) await hass.async_block_till_done() @@ -535,8 +529,8 @@ async def help_test_setting_blocked_attribute_via_mqtt_json_message( # Add JSON attributes settings to config config = copy.deepcopy(config) - config[domain]["json_attributes_topic"] = "attr-topic" - data = json.dumps(config[domain]) + config[mqtt.DOMAIN][domain]["json_attributes_topic"] = "attr-topic" + data = json.dumps(config[mqtt.DOMAIN][domain]) async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", data) await hass.async_block_till_done() val = "abc123" @@ -561,11 +555,13 @@ async def help_test_setting_attribute_with_template( """ # Add JSON attributes settings to config config = copy.deepcopy(config) - config[domain]["json_attributes_topic"] = "attr-topic" - config[domain]["json_attributes_template"] = "{{ value_json['Timer1'] | tojson }}" + config[mqtt.DOMAIN][domain]["json_attributes_topic"] = "attr-topic" + config[mqtt.DOMAIN][domain][ + "json_attributes_template" + ] = "{{ value_json['Timer1'] | tojson }}" assert await async_setup_component( hass, - domain, + mqtt.DOMAIN, config, ) await hass.async_block_till_done() @@ -589,10 +585,10 @@ async def help_test_update_with_json_attrs_not_dict( """ # Add JSON attributes settings to config config = copy.deepcopy(config) - config[domain]["json_attributes_topic"] = "attr-topic" + config[mqtt.DOMAIN][domain]["json_attributes_topic"] = "attr-topic" assert await async_setup_component( hass, - domain, + mqtt.DOMAIN, config, ) await hass.async_block_till_done() @@ -605,7 +601,7 @@ async def help_test_update_with_json_attrs_not_dict( assert "JSON result was not a dictionary" in caplog.text -async def help_test_update_with_json_attrs_bad_JSON( +async def help_test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog, domain, config ): """Test JSON validation of attributes. @@ -614,10 +610,10 @@ async def help_test_update_with_json_attrs_bad_JSON( """ # Add JSON attributes settings to config config = copy.deepcopy(config) - config[domain]["json_attributes_topic"] = "attr-topic" + config[mqtt.DOMAIN][domain]["json_attributes_topic"] = "attr-topic" assert await async_setup_component( hass, - domain, + mqtt.DOMAIN, config, ) await hass.async_block_till_done() @@ -640,11 +636,11 @@ async def help_test_discovery_update_attr( await mqtt_mock_entry_no_yaml_config() # Add JSON attributes settings to config config1 = copy.deepcopy(config) - config1[domain]["json_attributes_topic"] = "attr-topic1" + config1[mqtt.DOMAIN][domain]["json_attributes_topic"] = "attr-topic1" config2 = copy.deepcopy(config) - config2[domain]["json_attributes_topic"] = "attr-topic2" - data1 = json.dumps(config1[domain]) - data2 = json.dumps(config2[domain]) + config2[mqtt.DOMAIN][domain]["json_attributes_topic"] = "attr-topic2" + data1 = json.dumps(config1[mqtt.DOMAIN][domain]) + data2 = json.dumps(config2[mqtt.DOMAIN][domain]) async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", data1) await hass.async_block_till_done() @@ -669,7 +665,7 @@ async def help_test_discovery_update_attr( async def help_test_unique_id(hass, mqtt_mock_entry_with_yaml_config, domain, config): """Test unique id option only creates one entity per unique_id.""" - assert await async_setup_component(hass, domain, config) + assert await async_setup_component(hass, mqtt.DOMAIN, config) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() assert len(hass.states.async_entity_ids(domain)) == 1 @@ -881,7 +877,7 @@ async def _test_encoding( await hass.async_block_till_done() assert await async_setup_component( - hass, domain, {domain: [config1, config2, config3]} + hass, mqtt.DOMAIN, {mqtt.DOMAIN: {domain: [config1, config2, config3]}} ) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -944,7 +940,7 @@ async def help_test_entity_device_info_with_identifier( """ await mqtt_mock_entry_no_yaml_config() # Add device settings to config - config = copy.deepcopy(config[domain]) + config = copy.deepcopy(config[mqtt.DOMAIN][domain]) config["device"] = copy.deepcopy(DEFAULT_CONFIG_DEVICE_INFO_ID) config["unique_id"] = "veryunique" @@ -975,7 +971,7 @@ async def help_test_entity_device_info_with_connection( """ await mqtt_mock_entry_no_yaml_config() # Add device settings to config - config = copy.deepcopy(config[domain]) + config = copy.deepcopy(config[mqtt.DOMAIN][domain]) config["device"] = copy.deepcopy(DEFAULT_CONFIG_DEVICE_INFO_MAC) config["unique_id"] = "veryunique" @@ -1005,7 +1001,7 @@ async def help_test_entity_device_info_remove( """Test device registry remove.""" await mqtt_mock_entry_no_yaml_config() # Add device settings to config - config = copy.deepcopy(config[domain]) + config = copy.deepcopy(config[mqtt.DOMAIN][domain]) config["device"] = copy.deepcopy(DEFAULT_CONFIG_DEVICE_INFO_ID) config["unique_id"] = "veryunique" @@ -1037,7 +1033,7 @@ async def help_test_entity_device_info_update( """ await mqtt_mock_entry_no_yaml_config() # Add device settings to config - config = copy.deepcopy(config[domain]) + config = copy.deepcopy(config[mqtt.DOMAIN][domain]) config["device"] = copy.deepcopy(DEFAULT_CONFIG_DEVICE_INFO_ID) config["unique_id"] = "veryunique" @@ -1067,19 +1063,19 @@ async def help_test_entity_id_update_subscriptions( """Test MQTT subscriptions are managed when entity_id is updated.""" # Add unique_id to config config = copy.deepcopy(config) - config[domain]["unique_id"] = "TOTALLY_UNIQUE" + config[mqtt.DOMAIN][domain]["unique_id"] = "TOTALLY_UNIQUE" if topics is None: # Add default topics to config - config[domain]["availability_topic"] = "avty-topic" - config[domain]["state_topic"] = "test-topic" + config[mqtt.DOMAIN][domain]["availability_topic"] = "avty-topic" + config[mqtt.DOMAIN][domain]["state_topic"] = "test-topic" topics = ["avty-topic", "test-topic"] assert len(topics) > 0 registry = mock_registry(hass, {}) assert await async_setup_component( hass, - domain, + mqtt.DOMAIN, config, ) await hass.async_block_till_done() @@ -1111,16 +1107,16 @@ async def help_test_entity_id_update_discovery_update( # Add unique_id to config await mqtt_mock_entry_no_yaml_config() config = copy.deepcopy(config) - config[domain]["unique_id"] = "TOTALLY_UNIQUE" + config[mqtt.DOMAIN][domain]["unique_id"] = "TOTALLY_UNIQUE" if topic is None: # Add default topic to config - config[domain]["availability_topic"] = "avty-topic" + config[mqtt.DOMAIN][domain]["availability_topic"] = "avty-topic" topic = "avty-topic" ent_registry = mock_registry(hass, {}) - data = json.dumps(config[domain]) + data = json.dumps(config[mqtt.DOMAIN][domain]) async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", data) await hass.async_block_till_done() @@ -1135,8 +1131,8 @@ async def help_test_entity_id_update_discovery_update( ent_registry.async_update_entity(f"{domain}.test", new_entity_id=f"{domain}.milk") await hass.async_block_till_done() - config[domain]["availability_topic"] = f"{topic}_2" - data = json.dumps(config[domain]) + config[mqtt.DOMAIN][domain]["availability_topic"] = f"{topic}_2" + data = json.dumps(config[mqtt.DOMAIN][domain]) async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", data) await hass.async_block_till_done() assert len(hass.states.async_entity_ids(domain)) == 1 @@ -1155,9 +1151,10 @@ async def help_test_entity_debug_info( """ await mqtt_mock_entry_no_yaml_config() # Add device settings to config - config = copy.deepcopy(config[domain]) + config = copy.deepcopy(config[mqtt.DOMAIN][domain]) config["device"] = copy.deepcopy(DEFAULT_CONFIG_DEVICE_INFO_ID) config["unique_id"] = "veryunique" + config["platform"] = "mqtt" registry = dr.async_get(hass) @@ -1192,7 +1189,7 @@ async def help_test_entity_debug_info_max_messages( """ await mqtt_mock_entry_no_yaml_config() # Add device settings to config - config = copy.deepcopy(config[domain]) + config = copy.deepcopy(config[mqtt.DOMAIN][domain]) config["device"] = copy.deepcopy(DEFAULT_CONFIG_DEVICE_INFO_ID) config["unique_id"] = "veryunique" @@ -1256,7 +1253,7 @@ async def help_test_entity_debug_info_message( """ # Add device settings to config await mqtt_mock_entry_no_yaml_config() - config = copy.deepcopy(config[domain]) + config = copy.deepcopy(config[mqtt.DOMAIN][domain]) config["device"] = copy.deepcopy(DEFAULT_CONFIG_DEVICE_INFO_ID) config["unique_id"] = "veryunique" @@ -1359,9 +1356,10 @@ async def help_test_entity_debug_info_remove( """ await mqtt_mock_entry_no_yaml_config() # Add device settings to config - config = copy.deepcopy(config[domain]) + config = copy.deepcopy(config[mqtt.DOMAIN][domain]) config["device"] = copy.deepcopy(DEFAULT_CONFIG_DEVICE_INFO_ID) config["unique_id"] = "veryunique" + config["platform"] = "mqtt" registry = dr.async_get(hass) @@ -1405,9 +1403,10 @@ async def help_test_entity_debug_info_update_entity_id( """ await mqtt_mock_entry_no_yaml_config() # Add device settings to config - config = copy.deepcopy(config[domain]) + config = copy.deepcopy(config[mqtt.DOMAIN][domain]) config["device"] = copy.deepcopy(DEFAULT_CONFIG_DEVICE_INFO_ID) config["unique_id"] = "veryunique" + config["platform"] = "mqtt" dev_registry = dr.async_get(hass) ent_registry = mock_registry(hass, {}) @@ -1461,7 +1460,7 @@ async def help_test_entity_disabled_by_default( """Test device registry remove.""" await mqtt_mock_entry_no_yaml_config() # Add device settings to config - config = copy.deepcopy(config[domain]) + config = copy.deepcopy(config[mqtt.DOMAIN][domain]) config["device"] = copy.deepcopy(DEFAULT_CONFIG_DEVICE_INFO_ID) config["enabled_by_default"] = False config["unique_id"] = "veryunique1" @@ -1500,7 +1499,7 @@ async def help_test_entity_category( """Test device registry remove.""" await mqtt_mock_entry_no_yaml_config() # Add device settings to config - config = copy.deepcopy(config[domain]) + config = copy.deepcopy(config[mqtt.DOMAIN][domain]) config["device"] = copy.deepcopy(DEFAULT_CONFIG_DEVICE_INFO_ID) ent_registry = er.async_get(hass) @@ -1564,7 +1563,7 @@ async def help_test_publishing_with_custom_encoding( setup_config = [] service_data = {} for test_id, test_data in test_config.items(): - test_config_setup = copy.deepcopy(config) + test_config_setup = copy.deepcopy(config[mqtt.DOMAIN][domain]) test_config_setup.update( { topic: f"cmd/{test_id}", @@ -1573,7 +1572,7 @@ async def help_test_publishing_with_custom_encoding( ) if test_data["encoding"] is not None: test_config_setup["encoding"] = test_data["encoding"] - if test_data["cmd_tpl"]: + if template and test_data["cmd_tpl"]: test_config_setup[ template ] = f"{{{{ (('%.1f'|format({tpl_par}))[0] if is_number({tpl_par}) else {tpl_par}[0]) | ord | pack('b') }}}}" @@ -1587,8 +1586,8 @@ async def help_test_publishing_with_custom_encoding( # setup test entities assert await async_setup_component( hass, - domain, - {domain: setup_config}, + mqtt.DOMAIN, + {mqtt.DOMAIN: {domain: setup_config}}, ) await hass.async_block_till_done() mqtt_mock = await mqtt_mock_entry_with_yaml_config() @@ -1698,24 +1697,29 @@ async def help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ): """Test reloading an MQTT platform.""" + config = copy.deepcopy(config[mqtt.DOMAIN][domain]) # Create and test an old config of 2 entities based on the config supplied old_config_1 = copy.deepcopy(config) old_config_1["name"] = "test_old_1" old_config_2 = copy.deepcopy(config) old_config_2["name"] = "test_old_2" + + # Test deprecated YAML configuration under the platform key + # Scheduled to be removed in HA core 2022.12 old_config_3 = copy.deepcopy(config) old_config_3["name"] = "test_old_3" - old_config_3.pop("platform") + old_config_3["platform"] = mqtt.DOMAIN old_config_4 = copy.deepcopy(config) old_config_4["name"] = "test_old_4" - old_config_4.pop("platform") + old_config_4["platform"] = mqtt.DOMAIN old_config = { - domain: [old_config_1, old_config_2], - "mqtt": {domain: [old_config_3, old_config_4]}, + mqtt.DOMAIN: {domain: [old_config_1, old_config_2]}, + domain: [old_config_3, old_config_4], } assert await async_setup_component(hass, domain, old_config) + assert await async_setup_component(hass, mqtt.DOMAIN, old_config) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() @@ -1731,21 +1735,24 @@ async def help_test_reloadable( new_config_1["name"] = "test_new_1" new_config_2 = copy.deepcopy(config) new_config_2["name"] = "test_new_2" + new_config_extra = copy.deepcopy(config) + new_config_extra["name"] = "test_new_5" + + # Test deprecated YAML configuration under the platform key + # Scheduled to be removed in HA core 2022.12 new_config_3 = copy.deepcopy(config) new_config_3["name"] = "test_new_3" - new_config_3.pop("platform") + new_config_3["platform"] = mqtt.DOMAIN new_config_4 = copy.deepcopy(config) new_config_4["name"] = "test_new_4" - new_config_4.pop("platform") - new_config_5 = copy.deepcopy(config) - new_config_5["name"] = "test_new_5" - new_config_6 = copy.deepcopy(config) - new_config_6["name"] = "test_new_6" - new_config_6.pop("platform") + new_config_4["platform"] = mqtt.DOMAIN + new_config_extra_legacy = copy.deepcopy(config) + new_config_extra_legacy["name"] = "test_new_6" + new_config_extra_legacy["platform"] = mqtt.DOMAIN new_config = { - domain: [new_config_1, new_config_2, new_config_5], - "mqtt": {domain: [new_config_3, new_config_4, new_config_6]}, + mqtt.DOMAIN: {domain: [new_config_1, new_config_2, new_config_extra]}, + domain: [new_config_3, new_config_4, new_config_extra_legacy], } await help_test_reload_with_config(hass, caplog, tmp_path, new_config) @@ -1760,9 +1767,12 @@ async def help_test_reloadable( assert hass.states.get(f"{domain}.test_new_6") +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 async def help_test_reloadable_late(hass, caplog, tmp_path, domain, config): - """Test reloading an MQTT platform when config entry is setup late.""" + """Test reloading an MQTT platform when config entry is setup is late.""" # Create and test an old config of 2 entities based on the config supplied + # using the deprecated platform schema old_config_1 = copy.deepcopy(config) old_config_1["name"] = "test_old_1" old_config_2 = copy.deepcopy(config) @@ -1815,7 +1825,7 @@ async def help_test_reloadable_late(hass, caplog, tmp_path, domain, config): assert hass.states.get(f"{domain}.test_new_3") -async def help_test_setup_manual_entity_from_yaml(hass, platform, config): +async def help_test_setup_manual_entity_from_yaml(hass, config): """Help to test setup from yaml through configuration entry.""" calls = MagicMock() @@ -1823,9 +1833,7 @@ async def mock_reload(hass): """Mock reload.""" calls() - config_structure = {mqtt.DOMAIN: {platform: config}} - - await async_setup_component(hass, mqtt.DOMAIN, config_structure) + assert await async_setup_component(hass, mqtt.DOMAIN, config) # Mock config entry entry = MockConfigEntry(domain=mqtt.DOMAIN, data={mqtt.CONF_BROKER: "test-broker"}) entry.add_to_hass(hass) @@ -1864,14 +1872,14 @@ async def help_test_unload_config_entry_with_platform( """Test unloading the MQTT config entry with a specific platform domain.""" # prepare setup through configuration.yaml config_setup = copy.deepcopy(config) - config_setup["name"] = "config_setup" + config_setup[mqtt.DOMAIN][domain]["name"] = "config_setup" config_name = config_setup - assert await async_setup_component(hass, domain, {domain: [config_setup]}) + assert await async_setup_component(hass, mqtt.DOMAIN, config_setup) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() # prepare setup through discovery - discovery_setup = copy.deepcopy(config) + discovery_setup = copy.deepcopy(config[mqtt.DOMAIN][domain]) discovery_setup["name"] = "discovery_setup" async_fire_mqtt_message( hass, f"homeassistant/{domain}/bla/config", json.dumps(discovery_setup) diff --git a/tests/components/mqtt/test_cover.py b/tests/components/mqtt/test_cover.py index a91f0ecc6cab5..fb7df111d96f7 100644 --- a/tests/components/mqtt/test_cover.py +++ b/tests/components/mqtt/test_cover.py @@ -74,7 +74,7 @@ help_test_setup_manual_entity_from_yaml, help_test_unique_id, help_test_unload_config_entry_with_platform, - help_test_update_with_json_attrs_bad_JSON, + help_test_update_with_json_attrs_bad_json, help_test_update_with_json_attrs_not_dict, ) @@ -2444,28 +2444,28 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, cover.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, cover.DOMAIN, DEFAULT_CONFIG ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, cover.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, cover.DOMAIN, DEFAULT_CONFIG ) async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by default payload with defined topic.""" await help_test_default_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, cover.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, cover.DOMAIN, DEFAULT_CONFIG ) async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by custom payload with defined topic.""" await help_test_custom_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, cover.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, cover.DOMAIN, DEFAULT_CONFIG ) @@ -2514,7 +2514,7 @@ async def test_setting_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_with_yaml_config, cover.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, cover.DOMAIN, DEFAULT_CONFIG ) @@ -2526,7 +2526,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( hass, mqtt_mock_entry_no_yaml_config, cover.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, MQTT_COVER_ATTRIBUTES_BLOCKED, ) @@ -2534,7 +2534,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_with_template( - hass, mqtt_mock_entry_with_yaml_config, cover.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, cover.DOMAIN, DEFAULT_CONFIG ) @@ -2547,7 +2547,7 @@ async def test_update_with_json_attrs_not_dict( mqtt_mock_entry_with_yaml_config, caplog, cover.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -2555,12 +2555,12 @@ async def test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog ): """Test attributes get extracted from a JSON result.""" - await help_test_update_with_json_attrs_bad_JSON( + await help_test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog, cover.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -2571,27 +2571,27 @@ async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplo mqtt_mock_entry_no_yaml_config, caplog, cover.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) async def test_unique_id(hass, mqtt_mock_entry_with_yaml_config): """Test unique_id option only creates one cover per id.""" config = { - cover.DOMAIN: [ - { - "platform": "mqtt", - "name": "Test 1", - "state_topic": "test-topic", - "unique_id": "TOTALLY_UNIQUE", - }, - { - "platform": "mqtt", - "name": "Test 2", - "state_topic": "test-topic", - "unique_id": "TOTALLY_UNIQUE", - }, - ] + mqtt.DOMAIN: { + cover.DOMAIN: [ + { + "name": "Test 1", + "state_topic": "test-topic", + "unique_id": "TOTALLY_UNIQUE", + }, + { + "name": "Test 2", + "state_topic": "test-topic", + "unique_id": "TOTALLY_UNIQUE", + }, + ] + } } await help_test_unique_id( hass, mqtt_mock_entry_with_yaml_config, cover.DOMAIN, config @@ -2646,42 +2646,42 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT cover device registry integration.""" await help_test_entity_device_info_with_connection( - hass, mqtt_mock_entry_no_yaml_config, cover.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, cover.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT cover device registry integration.""" await help_test_entity_device_info_with_identifier( - hass, mqtt_mock_entry_no_yaml_config, cover.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, cover.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): """Test device registry update.""" await help_test_entity_device_info_update( - hass, mqtt_mock_entry_no_yaml_config, cover.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, cover.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test device registry remove.""" await help_test_entity_device_info_remove( - hass, mqtt_mock_entry_no_yaml_config, cover.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, cover.DOMAIN, DEFAULT_CONFIG ) async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_config): """Test MQTT subscriptions are managed when entity_id is updated.""" await help_test_entity_id_update_subscriptions( - hass, mqtt_mock_entry_with_yaml_config, cover.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, cover.DOMAIN, DEFAULT_CONFIG ) async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, cover.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, cover.DOMAIN, DEFAULT_CONFIG ) @@ -2691,7 +2691,7 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): hass, mqtt_mock_entry_no_yaml_config, cover.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, SERVICE_OPEN_COVER, command_payload="OPEN", ) @@ -3342,8 +3342,8 @@ async def test_publishing_with_custom_encoding( ): """Test publishing MQTT payload with different encoding.""" domain = cover.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] - config["position_topic"] = "some-position-topic" + config = DEFAULT_CONFIG + config[mqtt.DOMAIN][domain]["position_topic"] = "some-position-topic" await help_test_publishing_with_custom_encoding( hass, @@ -3362,12 +3362,14 @@ async def test_publishing_with_custom_encoding( async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = cover.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = cover.DOMAIN @@ -3399,7 +3401,7 @@ async def test_encoding_subscribable_topics( mqtt_mock_entry_with_yaml_config, caplog, cover.DOMAIN, - DEFAULT_CONFIG_LEGACY[cover.DOMAIN], + DEFAULT_CONFIG[mqtt.DOMAIN][cover.DOMAIN], topic, value, attribute, @@ -3411,17 +3413,14 @@ async def test_encoding_subscribable_topics( async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = cover.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) - config["name"] = "test" - del config["platform"] - await help_test_setup_manual_entity_from_yaml(hass, platform, config) - assert hass.states.get(f"{platform}.test") is not None + await help_test_setup_manual_entity_from_yaml(hass, DEFAULT_CONFIG) + assert hass.states.get(f"{platform}.test") async def test_unload_entry(hass, mqtt_mock_entry_with_yaml_config, tmp_path): """Test unloading the config entry.""" domain = cover.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry_with_yaml_config, tmp_path, domain, config ) diff --git a/tests/components/mqtt/test_device_tracker_discovery.py b/tests/components/mqtt/test_device_tracker_discovery.py index 923ae7c9f757c..876b66e8a4da1 100644 --- a/tests/components/mqtt/test_device_tracker_discovery.py +++ b/tests/components/mqtt/test_device_tracker_discovery.py @@ -1,6 +1,5 @@ """The tests for the MQTT device_tracker platform.""" -import copy from unittest.mock import patch import pytest @@ -27,11 +26,6 @@ } } -# Test deprecated YAML configuration under the platform key -# Scheduled to be removed in HA core 2022.12 -DEFAULT_CONFIG_LEGACY = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) -DEFAULT_CONFIG_LEGACY[device_tracker.DOMAIN]["platform"] = mqtt.DOMAIN - @pytest.fixture(autouse=True) def device_tracker_platform_only(): @@ -440,7 +434,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( hass, mqtt_mock_entry_no_yaml_config, device_tracker.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, None, ) @@ -451,8 +445,10 @@ async def test_setup_with_modern_schema(hass, mock_device_tracker_conf): entity_id = f"{device_tracker.DOMAIN}.{dev_id}" topic = "/location/jan" - config = {"name": dev_id, "state_topic": topic} + config = { + mqtt.DOMAIN: {device_tracker.DOMAIN: {"name": dev_id, "state_topic": topic}} + } - await help_test_setup_manual_entity_from_yaml(hass, device_tracker.DOMAIN, config) + await help_test_setup_manual_entity_from_yaml(hass, config) assert hass.states.get(entity_id) is not None diff --git a/tests/components/mqtt/test_fan.py b/tests/components/mqtt/test_fan.py index efe38234aeee0..1666ccee6cef6 100644 --- a/tests/components/mqtt/test_fan.py +++ b/tests/components/mqtt/test_fan.py @@ -59,7 +59,7 @@ help_test_setup_manual_entity_from_yaml, help_test_unique_id, help_test_unload_config_entry_with_platform, - help_test_update_with_json_attrs_bad_JSON, + help_test_update_with_json_attrs_bad_json, help_test_update_with_json_attrs_not_dict, ) @@ -1365,7 +1365,7 @@ async def test_encoding_subscribable_topics( attribute_value, ): """Test handling of incoming encoded payload.""" - config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[fan.DOMAIN]) + config = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][fan.DOMAIN]) config[ATTR_PRESET_MODES] = ["eco", "auto"] config[CONF_PRESET_MODE_COMMAND_TOPIC] = "fan/some_preset_mode_command_topic" config[CONF_PERCENTAGE_COMMAND_TOPIC] = "fan/some_percentage_command_topic" @@ -1639,14 +1639,14 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, fan.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, fan.DOMAIN, DEFAULT_CONFIG ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, fan.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, fan.DOMAIN, DEFAULT_CONFIG ) @@ -1656,7 +1656,7 @@ async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_conf hass, mqtt_mock_entry_with_yaml_config, fan.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, True, "state-topic", "1", @@ -1669,7 +1669,7 @@ async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_confi hass, mqtt_mock_entry_with_yaml_config, fan.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, True, "state-topic", "1", @@ -1681,7 +1681,7 @@ async def test_setting_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_with_yaml_config, fan.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, fan.DOMAIN, DEFAULT_CONFIG ) @@ -1693,7 +1693,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( hass, mqtt_mock_entry_no_yaml_config, fan.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, MQTT_FAN_ATTRIBUTES_BLOCKED, ) @@ -1701,7 +1701,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_with_template( - hass, mqtt_mock_entry_with_yaml_config, fan.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, fan.DOMAIN, DEFAULT_CONFIG ) @@ -1714,7 +1714,7 @@ async def test_update_with_json_attrs_not_dict( mqtt_mock_entry_with_yaml_config, caplog, fan.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -1722,41 +1722,41 @@ async def test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog ): """Test attributes get extracted from a JSON result.""" - await help_test_update_with_json_attrs_bad_JSON( + await help_test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog, fan.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test update of discovered MQTTAttributes.""" await help_test_discovery_update_attr( - hass, mqtt_mock_entry_no_yaml_config, caplog, fan.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, caplog, fan.DOMAIN, DEFAULT_CONFIG ) async def test_unique_id(hass, mqtt_mock_entry_with_yaml_config): """Test unique_id option only creates one fan per id.""" config = { - fan.DOMAIN: [ - { - "platform": "mqtt", - "name": "Test 1", - "state_topic": "test-topic", - "command_topic": "test_topic", - "unique_id": "TOTALLY_UNIQUE", - }, - { - "platform": "mqtt", - "name": "Test 2", - "state_topic": "test-topic", - "command_topic": "test_topic", - "unique_id": "TOTALLY_UNIQUE", - }, - ] + mqtt.DOMAIN: { + fan.DOMAIN: [ + { + "name": "Test 1", + "state_topic": "test-topic", + "command_topic": "test_topic", + "unique_id": "TOTALLY_UNIQUE", + }, + { + "name": "Test 2", + "state_topic": "test-topic", + "command_topic": "test_topic", + "unique_id": "TOTALLY_UNIQUE", + }, + ] + } } await help_test_unique_id( hass, mqtt_mock_entry_with_yaml_config, fan.DOMAIN, config @@ -1812,42 +1812,42 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT fan device registry integration.""" await help_test_entity_device_info_with_connection( - hass, mqtt_mock_entry_no_yaml_config, fan.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, fan.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT fan device registry integration.""" await help_test_entity_device_info_with_identifier( - hass, mqtt_mock_entry_no_yaml_config, fan.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, fan.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): """Test device registry update.""" await help_test_entity_device_info_update( - hass, mqtt_mock_entry_no_yaml_config, fan.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, fan.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test device registry remove.""" await help_test_entity_device_info_remove( - hass, mqtt_mock_entry_no_yaml_config, fan.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, fan.DOMAIN, DEFAULT_CONFIG ) async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_config): """Test MQTT subscriptions are managed when entity_id is updated.""" await help_test_entity_id_update_subscriptions( - hass, mqtt_mock_entry_with_yaml_config, fan.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, fan.DOMAIN, DEFAULT_CONFIG ) async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, fan.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, fan.DOMAIN, DEFAULT_CONFIG ) @@ -1857,7 +1857,7 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): hass, mqtt_mock_entry_no_yaml_config, fan.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, fan.SERVICE_TURN_ON, ) @@ -1914,9 +1914,9 @@ async def test_publishing_with_custom_encoding( ): """Test publishing MQTT payload with different encoding.""" domain = fan.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[domain]) + config = copy.deepcopy(DEFAULT_CONFIG) if topic == "preset_mode_command_topic": - config["preset_modes"] = ["auto", "eco"] + config[mqtt.DOMAIN][domain]["preset_modes"] = ["auto", "eco"] await help_test_publishing_with_custom_encoding( hass, @@ -1935,12 +1935,14 @@ async def test_publishing_with_custom_encoding( async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = fan.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = fan.DOMAIN @@ -1951,17 +1953,14 @@ async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = fan.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) - config["name"] = "test" - del config["platform"] - await help_test_setup_manual_entity_from_yaml(hass, platform, config) - assert hass.states.get(f"{platform}.test") is not None + await help_test_setup_manual_entity_from_yaml(hass, DEFAULT_CONFIG) + assert hass.states.get(f"{platform}.test") async def test_unload_entry(hass, mqtt_mock_entry_with_yaml_config, tmp_path): """Test unloading the config entry.""" domain = fan.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry_with_yaml_config, tmp_path, domain, config ) diff --git a/tests/components/mqtt/test_humidifier.py b/tests/components/mqtt/test_humidifier.py index 0cc2be638bfb3..1e2d64b66cfdc 100644 --- a/tests/components/mqtt/test_humidifier.py +++ b/tests/components/mqtt/test_humidifier.py @@ -61,7 +61,7 @@ help_test_setup_manual_entity_from_yaml, help_test_unique_id, help_test_unload_config_entry_with_platform, - help_test_update_with_json_attrs_bad_JSON, + help_test_update_with_json_attrs_bad_json, help_test_update_with_json_attrs_not_dict, ) @@ -750,7 +750,7 @@ async def test_encoding_subscribable_topics( attribute_value, ): """Test handling of incoming encoded payload.""" - config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[humidifier.DOMAIN]) + config = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][humidifier.DOMAIN]) config["modes"] = ["eco", "auto"] config[CONF_MODE_COMMAND_TOPIC] = "humidifier/some_mode_command_topic" await help_test_encoding_subscribable_topics( @@ -996,14 +996,14 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG ) @@ -1013,7 +1013,7 @@ async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_conf hass, mqtt_mock_entry_with_yaml_config, humidifier.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, True, "state-topic", "1", @@ -1026,7 +1026,7 @@ async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_confi hass, mqtt_mock_entry_with_yaml_config, humidifier.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, True, "state-topic", "1", @@ -1038,7 +1038,7 @@ async def test_setting_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_with_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG ) @@ -1050,7 +1050,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( hass, mqtt_mock_entry_no_yaml_config, humidifier.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, MQTT_HUMIDIFIER_ATTRIBUTES_BLOCKED, ) @@ -1058,7 +1058,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_with_template( - hass, mqtt_mock_entry_with_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG ) @@ -1071,7 +1071,7 @@ async def test_update_with_json_attrs_not_dict( mqtt_mock_entry_with_yaml_config, caplog, humidifier.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -1079,12 +1079,12 @@ async def test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog ): """Test attributes get extracted from a JSON result.""" - await help_test_update_with_json_attrs_bad_JSON( + await help_test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog, humidifier.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -1095,31 +1095,31 @@ async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplo mqtt_mock_entry_no_yaml_config, caplog, humidifier.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) async def test_unique_id(hass, mqtt_mock_entry_with_yaml_config): """Test unique_id option only creates one fan per id.""" config = { - humidifier.DOMAIN: [ - { - "platform": "mqtt", - "name": "Test 1", - "state_topic": "test-topic", - "command_topic": "test_topic", - "target_humidity_command_topic": "humidity-command-topic", - "unique_id": "TOTALLY_UNIQUE", - }, - { - "platform": "mqtt", - "name": "Test 2", - "state_topic": "test-topic", - "command_topic": "test_topic", - "target_humidity_command_topic": "humidity-command-topic", - "unique_id": "TOTALLY_UNIQUE", - }, - ] + mqtt.DOMAIN: { + humidifier.DOMAIN: [ + { + "name": "Test 1", + "state_topic": "test-topic", + "command_topic": "test_topic", + "target_humidity_command_topic": "humidity-command-topic", + "unique_id": "TOTALLY_UNIQUE", + }, + { + "name": "Test 2", + "state_topic": "test-topic", + "command_topic": "test_topic", + "target_humidity_command_topic": "humidity-command-topic", + "unique_id": "TOTALLY_UNIQUE", + }, + ] + } } await help_test_unique_id( hass, mqtt_mock_entry_with_yaml_config, humidifier.DOMAIN, config @@ -1191,42 +1191,42 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT fan device registry integration.""" await help_test_entity_device_info_with_connection( - hass, mqtt_mock_entry_no_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT fan device registry integration.""" await help_test_entity_device_info_with_identifier( - hass, mqtt_mock_entry_no_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): """Test device registry update.""" await help_test_entity_device_info_update( - hass, mqtt_mock_entry_no_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test device registry remove.""" await help_test_entity_device_info_remove( - hass, mqtt_mock_entry_no_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG ) async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_config): """Test MQTT subscriptions are managed when entity_id is updated.""" await help_test_entity_id_update_subscriptions( - hass, mqtt_mock_entry_with_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG ) async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, humidifier.DOMAIN, DEFAULT_CONFIG ) @@ -1236,7 +1236,7 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): hass, mqtt_mock_entry_no_yaml_config, humidifier.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, humidifier.SERVICE_TURN_ON, ) @@ -1286,9 +1286,9 @@ async def test_publishing_with_custom_encoding( ): """Test publishing MQTT payload with different encoding.""" domain = humidifier.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[domain]) + config = copy.deepcopy(DEFAULT_CONFIG) if topic == "mode_command_topic": - config["modes"] = ["auto", "eco"] + config[mqtt.DOMAIN][domain]["modes"] = ["auto", "eco"] await help_test_publishing_with_custom_encoding( hass, @@ -1307,12 +1307,14 @@ async def test_publishing_with_custom_encoding( async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = humidifier.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = humidifier.DOMAIN @@ -1323,11 +1325,8 @@ async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = humidifier.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) - config["name"] = "test" - del config["platform"] - await help_test_setup_manual_entity_from_yaml(hass, platform, config) - assert hass.states.get(f"{platform}.test") is not None + await help_test_setup_manual_entity_from_yaml(hass, DEFAULT_CONFIG) + assert hass.states.get(f"{platform}.test") async def test_config_schema_validation(hass): @@ -1344,7 +1343,7 @@ async def test_config_schema_validation(hass): async def test_unload_config_entry(hass, mqtt_mock_entry_with_yaml_config, tmp_path): """Test unloading the config entry.""" domain = humidifier.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry_with_yaml_config, tmp_path, domain, config ) diff --git a/tests/components/mqtt/test_init.py b/tests/components/mqtt/test_init.py index b794d9260ba7f..b76979cc990d4 100644 --- a/tests/components/mqtt/test_init.py +++ b/tests/components/mqtt/test_init.py @@ -1485,9 +1485,17 @@ def mock_usename_password_set(username, password): @patch("homeassistant.components.mqtt.PLATFORMS", []) async def test_setup_manual_mqtt_with_platform_key(hass, caplog): """Test set up a manual MQTT item with a platform key.""" - config = {"platform": "mqtt", "name": "test", "command_topic": "test-topic"} + config = { + mqtt.DOMAIN: { + "light": { + "platform": "mqtt", + "name": "test", + "command_topic": "test-topic", + } + } + } with pytest.raises(AssertionError): - await help_test_setup_manual_entity_from_yaml(hass, "light", config) + await help_test_setup_manual_entity_from_yaml(hass, config) assert ( "Invalid config for [mqtt]: [platform] is an invalid option for [mqtt]" in caplog.text @@ -1497,9 +1505,9 @@ async def test_setup_manual_mqtt_with_platform_key(hass, caplog): @patch("homeassistant.components.mqtt.PLATFORMS", []) async def test_setup_manual_mqtt_with_invalid_config(hass, caplog): """Test set up a manual MQTT item with an invalid config.""" - config = {"name": "test"} + config = {mqtt.DOMAIN: {"light": {"name": "test"}}} with pytest.raises(AssertionError): - await help_test_setup_manual_entity_from_yaml(hass, "light", config) + await help_test_setup_manual_entity_from_yaml(hass, config) assert ( "Invalid config for [mqtt]: required key not provided @ data['mqtt']['light'][0]['command_topic']." " Got None. (See ?, line ?)" in caplog.text @@ -1509,8 +1517,8 @@ async def test_setup_manual_mqtt_with_invalid_config(hass, caplog): @patch("homeassistant.components.mqtt.PLATFORMS", []) async def test_setup_manual_mqtt_empty_platform(hass, caplog): """Test set up a manual MQTT platform without items.""" - config = [] - await help_test_setup_manual_entity_from_yaml(hass, "light", config) + config = {mqtt.DOMAIN: {"light": []}} + await help_test_setup_manual_entity_from_yaml(hass, config) assert "voluptuous.error.MultipleInvalid" not in caplog.text @@ -2797,7 +2805,11 @@ async def test_publish_or_subscribe_without_valid_config_entry(hass, caplog): @patch("homeassistant.components.mqtt.PLATFORMS", [Platform.LIGHT]) async def test_reload_entry_with_new_config(hass, tmp_path): """Test reloading the config entry with a new yaml config.""" - config_old = [{"name": "test_old1", "command_topic": "test-topic_old"}] + # Test deprecated YAML configuration under the platform key + # Scheduled to be removed in HA core 2022.12 + config_old = { + "mqtt": {"light": [{"name": "test_old1", "command_topic": "test-topic_old"}]} + } config_yaml_new = { "mqtt": { "light": [{"name": "test_new_modern", "command_topic": "test-topic_new"}] @@ -2812,7 +2824,7 @@ async def test_reload_entry_with_new_config(hass, tmp_path): } ], } - await help_test_setup_manual_entity_from_yaml(hass, "light", config_old) + await help_test_setup_manual_entity_from_yaml(hass, config_old) assert hass.states.get("light.test_old1") is not None await help_test_entry_reload_with_new_config(hass, tmp_path, config_yaml_new) @@ -2824,7 +2836,9 @@ async def test_reload_entry_with_new_config(hass, tmp_path): @patch("homeassistant.components.mqtt.PLATFORMS", [Platform.LIGHT]) async def test_disabling_and_enabling_entry(hass, tmp_path, caplog): """Test disabling and enabling the config entry.""" - config_old = [{"name": "test_old1", "command_topic": "test-topic_old"}] + config_old = { + "mqtt": {"light": [{"name": "test_old1", "command_topic": "test-topic_old"}]} + } config_yaml_new = { "mqtt": { "light": [{"name": "test_new_modern", "command_topic": "test-topic_new"}] @@ -2839,7 +2853,7 @@ async def test_disabling_and_enabling_entry(hass, tmp_path, caplog): } ], } - await help_test_setup_manual_entity_from_yaml(hass, "light", config_old) + await help_test_setup_manual_entity_from_yaml(hass, config_old) assert hass.states.get("light.test_old1") is not None mqtt_config_entry = hass.config_entries.async_entries(mqtt.DOMAIN)[0] @@ -2929,7 +2943,9 @@ async def test_setup_manual_items_with_unique_ids( hass, tmp_path, caplog, config, unique ): """Test setup manual items is generating unique id's.""" - await help_test_setup_manual_entity_from_yaml(hass, "light", config) + await help_test_setup_manual_entity_from_yaml( + hass, {mqtt.DOMAIN: {"light": config}} + ) assert hass.states.get("light.test1") is not None assert (hass.states.get("light.test2") is not None) == unique diff --git a/tests/components/mqtt/test_legacy_vacuum.py b/tests/components/mqtt/test_legacy_vacuum.py index ffe9183fe4cf3..4b44807b7c95b 100644 --- a/tests/components/mqtt/test_legacy_vacuum.py +++ b/tests/components/mqtt/test_legacy_vacuum.py @@ -58,7 +58,7 @@ help_test_setting_blocked_attribute_via_mqtt_json_message, help_test_setup_manual_entity_from_yaml, help_test_unique_id, - help_test_update_with_json_attrs_bad_JSON, + help_test_update_with_json_attrs_bad_json, help_test_update_with_json_attrs_not_dict, ) @@ -95,8 +95,6 @@ # Scheduled to be removed in HA core 2022.12 DEFAULT_CONFIG_LEGACY = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN]) DEFAULT_CONFIG_LEGACY[vacuum.DOMAIN][CONF_PLATFORM] = mqtt.DOMAIN -DEFAULT_CONFIG_2_LEGACY = deepcopy(DEFAULT_CONFIG_2[mqtt.DOMAIN]) -DEFAULT_CONFIG_2_LEGACY[vacuum.DOMAIN][CONF_PLATFORM] = mqtt.DOMAIN @pytest.fixture(autouse=True) @@ -108,7 +106,7 @@ def vacuum_platform_only(): async def test_default_supported_features(hass, mqtt_mock_entry_with_yaml_config): """Test that the correct supported features.""" - assert await async_setup_component(hass, vacuum.DOMAIN, DEFAULT_CONFIG_LEGACY) + assert await async_setup_component(hass, mqtt.DOMAIN, DEFAULT_CONFIG) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() entity = hass.states.get("vacuum.mqtttest") @@ -616,28 +614,28 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY + hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY + hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 ) async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by default payload with defined topic.""" await help_test_default_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY + hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 ) async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by custom payload with defined topic.""" await help_test_custom_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY + hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 ) @@ -646,7 +644,7 @@ async def test_setting_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY + hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 ) @@ -658,7 +656,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, - DEFAULT_CONFIG_2_LEGACY, + DEFAULT_CONFIG_2, MQTT_LEGACY_VACUUM_ATTRIBUTES_BLOCKED, ) @@ -666,7 +664,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_with_template( - hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY + hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 ) @@ -679,20 +677,20 @@ async def test_update_with_json_attrs_not_dict( mqtt_mock_entry_with_yaml_config, caplog, vacuum.DOMAIN, - DEFAULT_CONFIG_2_LEGACY, + DEFAULT_CONFIG_2, ) -async def test_update_with_json_attrs_bad_JSON( +async def test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog ): """Test attributes get extracted from a JSON result.""" - await help_test_update_with_json_attrs_bad_JSON( + await help_test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog, vacuum.DOMAIN, - DEFAULT_CONFIG_2_LEGACY, + DEFAULT_CONFIG_2, ) @@ -703,27 +701,27 @@ async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplo mqtt_mock_entry_no_yaml_config, caplog, vacuum.DOMAIN, - DEFAULT_CONFIG_2_LEGACY, + DEFAULT_CONFIG_2, ) async def test_unique_id(hass, mqtt_mock_entry_with_yaml_config): """Test unique id option only creates one vacuum per unique_id.""" config = { - vacuum.DOMAIN: [ - { - "platform": "mqtt", - "name": "Test 1", - "command_topic": "test_topic", - "unique_id": "TOTALLY_UNIQUE", - }, - { - "platform": "mqtt", - "name": "Test 2", - "command_topic": "test_topic", - "unique_id": "TOTALLY_UNIQUE", - }, - ] + mqtt.DOMAIN: { + vacuum.DOMAIN: [ + { + "name": "Test 1", + "command_topic": "test_topic", + "unique_id": "TOTALLY_UNIQUE", + }, + { + "name": "Test 2", + "command_topic": "test_topic", + "unique_id": "TOTALLY_UNIQUE", + }, + ] + } } await help_test_unique_id( hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, config @@ -732,7 +730,7 @@ async def test_unique_id(hass, mqtt_mock_entry_with_yaml_config): async def test_discovery_removal_vacuum(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test removal of discovered vacuum.""" - data = json.dumps(DEFAULT_CONFIG_2_LEGACY[vacuum.DOMAIN]) + data = json.dumps(DEFAULT_CONFIG_2[mqtt.DOMAIN][vacuum.DOMAIN]) await help_test_discovery_removal( hass, mqtt_mock_entry_no_yaml_config, caplog, vacuum.DOMAIN, data ) @@ -778,41 +776,42 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT vacuum device registry integration.""" await help_test_entity_device_info_with_connection( - hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY + hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 ) async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT vacuum device registry integration.""" await help_test_entity_device_info_with_identifier( - hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY + hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 ) async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): """Test device registry update.""" await help_test_entity_device_info_update( - hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY + hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 ) async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test device registry remove.""" await help_test_entity_device_info_remove( - hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY + hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 ) async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_config): """Test MQTT subscriptions are managed when entity_id is updated.""" config = { - vacuum.DOMAIN: { - "platform": "mqtt", - "name": "test", - "battery_level_topic": "test-topic", - "battery_level_template": "{{ value_json.battery_level }}", - "command_topic": "command-topic", - "availability_topic": "avty-topic", + mqtt.DOMAIN: { + vacuum.DOMAIN: { + "name": "test", + "battery_level_topic": "test-topic", + "battery_level_template": "{{ value_json.battery_level }}", + "command_topic": "command-topic", + "availability_topic": "avty-topic", + } } } await help_test_entity_id_update_subscriptions( @@ -827,20 +826,21 @@ async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_co async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY + hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 ) async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT debug info.""" config = { - vacuum.DOMAIN: { - "platform": "mqtt", - "name": "test", - "battery_level_topic": "state-topic", - "battery_level_template": "{{ value_json.battery_level }}", - "command_topic": "command-topic", - "payload_turn_on": "ON", + mqtt.DOMAIN: { + vacuum.DOMAIN: { + "name": "test", + "battery_level_topic": "state-topic", + "battery_level_template": "{{ value_json.battery_level }}", + "command_topic": "command-topic", + "payload_turn_on": "ON", + } } } await help_test_entity_debug_info_message( @@ -904,8 +904,8 @@ async def test_publishing_with_custom_encoding( ): """Test publishing MQTT payload with different encoding.""" domain = vacuum.DOMAIN - config = deepcopy(DEFAULT_CONFIG_LEGACY[domain]) - config["supported_features"] = [ + config = deepcopy(DEFAULT_CONFIG) + config[mqtt.DOMAIN][domain]["supported_features"] = [ "turn_on", "turn_off", "clean_spot", @@ -930,12 +930,14 @@ async def test_publishing_with_custom_encoding( async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = vacuum.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = vacuum.DOMAIN @@ -975,7 +977,7 @@ async def test_encoding_subscribable_topics( ): """Test handling of incoming encoded payload.""" domain = vacuum.DOMAIN - config = deepcopy(DEFAULT_CONFIG_LEGACY[domain]) + config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][domain]) config[CONF_SUPPORTED_FEATURES] = [ "turn_on", "turn_off", @@ -1007,11 +1009,8 @@ async def test_encoding_subscribable_topics( async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = vacuum.DOMAIN - config = deepcopy(DEFAULT_CONFIG_LEGACY[platform]) - config["name"] = "test" - del config["platform"] - await help_test_setup_manual_entity_from_yaml(hass, platform, config) - assert hass.states.get(f"{platform}.test") is not None + await help_test_setup_manual_entity_from_yaml(hass, DEFAULT_CONFIG) + assert hass.states.get(f"{platform}.mqtttest") # Test deprecated YAML configuration under the platform key diff --git a/tests/components/mqtt/test_light.py b/tests/components/mqtt/test_light.py index b34406f42bc31..05f9d0e72f037 100644 --- a/tests/components/mqtt/test_light.py +++ b/tests/components/mqtt/test_light.py @@ -223,7 +223,7 @@ help_test_setup_manual_entity_from_yaml, help_test_unique_id, help_test_unload_config_entry_with_platform, - help_test_update_with_json_attrs_bad_JSON, + help_test_update_with_json_attrs_bad_json, help_test_update_with_json_attrs_not_dict, ) @@ -2094,28 +2094,28 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG ) async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by default payload with defined topic.""" await help_test_default_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG ) async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by custom payload with defined topic.""" await help_test_custom_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG ) @@ -2124,7 +2124,7 @@ async def test_setting_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG ) @@ -2136,7 +2136,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, MQTT_LIGHT_ATTRIBUTES_BLOCKED, ) @@ -2144,7 +2144,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_with_template( - hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG ) @@ -2157,20 +2157,20 @@ async def test_update_with_json_attrs_not_dict( mqtt_mock_entry_with_yaml_config, caplog, light.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) -async def test_update_with_json_attrs_bad_JSON( +async def test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog ): """Test attributes get extracted from a JSON result.""" - await help_test_update_with_json_attrs_bad_JSON( + await help_test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog, light.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -2181,29 +2181,29 @@ async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplo mqtt_mock_entry_no_yaml_config, caplog, light.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) async def test_unique_id(hass, mqtt_mock_entry_with_yaml_config): """Test unique id option only creates one light per unique_id.""" config = { - light.DOMAIN: [ - { - "platform": "mqtt", - "name": "Test 1", - "state_topic": "test-topic", - "command_topic": "test_topic", - "unique_id": "TOTALLY_UNIQUE", - }, - { - "platform": "mqtt", - "name": "Test 2", - "state_topic": "test-topic", - "command_topic": "test_topic", - "unique_id": "TOTALLY_UNIQUE", - }, - ] + mqtt.DOMAIN: { + light.DOMAIN: [ + { + "name": "Test 1", + "state_topic": "test-topic", + "command_topic": "test_topic", + "unique_id": "TOTALLY_UNIQUE", + }, + { + "name": "Test 2", + "state_topic": "test-topic", + "command_topic": "test_topic", + "unique_id": "TOTALLY_UNIQUE", + }, + ] + } } await help_test_unique_id( hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, config @@ -2744,42 +2744,42 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT light device registry integration.""" await help_test_entity_device_info_with_connection( - hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT light device registry integration.""" await help_test_entity_device_info_with_identifier( - hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): """Test device registry update.""" await help_test_entity_device_info_update( - hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test device registry remove.""" await help_test_entity_device_info_remove( - hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG ) async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_config): """Test MQTT subscriptions are managed when entity_id is updated.""" await help_test_entity_id_update_subscriptions( - hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG ) async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG ) @@ -2789,7 +2789,7 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, light.SERVICE_TURN_ON, ) @@ -2914,11 +2914,11 @@ async def test_publishing_with_custom_encoding( ): """Test publishing MQTT payload with different encoding.""" domain = light.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[domain]) + config = copy.deepcopy(DEFAULT_CONFIG) if topic == "effect_command_topic": - config["effect_list"] = ["random", "color_loop"] + config[mqtt.DOMAIN][domain]["effect_list"] = ["random", "color_loop"] elif topic == "white_command_topic": - config["rgb_command_topic"] = "some-cmd-topic" + config[mqtt.DOMAIN][domain]["rgb_command_topic"] = "some-cmd-topic" await help_test_publishing_with_custom_encoding( hass, @@ -2939,12 +2939,14 @@ async def test_publishing_with_custom_encoding( async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = light.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = light.DOMAIN @@ -2993,7 +2995,7 @@ async def test_encoding_subscribable_topics( init_payload, ): """Test handling of incoming encoded payload.""" - config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[light.DOMAIN]) + config = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][light.DOMAIN]) config[CONF_EFFECT_COMMAND_TOPIC] = "light/CONF_EFFECT_COMMAND_TOPIC" config[CONF_RGB_COMMAND_TOPIC] = "light/CONF_RGB_COMMAND_TOPIC" config[CONF_BRIGHTNESS_COMMAND_TOPIC] = "light/CONF_BRIGHTNESS_COMMAND_TOPIC" @@ -3036,7 +3038,7 @@ async def test_encoding_subscribable_topics_brightness( init_payload, ): """Test handling of incoming encoded payload for a brightness only light.""" - config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[light.DOMAIN]) + config = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][light.DOMAIN]) config[CONF_BRIGHTNESS_COMMAND_TOPIC] = "light/CONF_BRIGHTNESS_COMMAND_TOPIC" await help_test_encoding_subscribable_topics( @@ -3138,17 +3140,14 @@ async def test_sending_mqtt_effect_command_with_template( async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = light.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) - config["name"] = "test" - del config["platform"] - await help_test_setup_manual_entity_from_yaml(hass, platform, config) - assert hass.states.get(f"{platform}.test") is not None + await help_test_setup_manual_entity_from_yaml(hass, DEFAULT_CONFIG) + assert hass.states.get(f"{platform}.test") async def test_unload_entry(hass, mqtt_mock_entry_with_yaml_config, tmp_path): """Test unloading the config entry.""" domain = light.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry_with_yaml_config, tmp_path, domain, config ) diff --git a/tests/components/mqtt/test_light_json.py b/tests/components/mqtt/test_light_json.py index e61d4e772865e..77ccd73f21b3e 100644 --- a/tests/components/mqtt/test_light_json.py +++ b/tests/components/mqtt/test_light_json.py @@ -125,7 +125,7 @@ help_test_setting_blocked_attribute_via_mqtt_json_message, help_test_setup_manual_entity_from_yaml, help_test_unique_id, - help_test_update_with_json_attrs_bad_JSON, + help_test_update_with_json_attrs_bad_json, help_test_update_with_json_attrs_not_dict, ) @@ -1830,28 +1830,28 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG ) async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by default payload with defined topic.""" await help_test_default_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG ) async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by custom payload with defined topic.""" await help_test_custom_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG ) @@ -1860,7 +1860,7 @@ async def test_setting_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG ) @@ -1872,7 +1872,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, MQTT_LIGHT_ATTRIBUTES_BLOCKED, ) @@ -1880,7 +1880,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_with_template( - hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG ) @@ -1893,20 +1893,20 @@ async def test_update_with_json_attrs_not_dict( mqtt_mock_entry_with_yaml_config, caplog, light.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) -async def test_update_with_json_attrs_bad_JSON( +async def test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog ): """Test attributes get extracted from a JSON result.""" - await help_test_update_with_json_attrs_bad_JSON( + await help_test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog, light.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -1917,31 +1917,31 @@ async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplo mqtt_mock_entry_no_yaml_config, caplog, light.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) async def test_unique_id(hass, mqtt_mock_entry_with_yaml_config): """Test unique id option only creates one light per unique_id.""" config = { - light.DOMAIN: [ - { - "platform": "mqtt", - "name": "Test 1", - "schema": "json", - "state_topic": "test-topic", - "command_topic": "test_topic", - "unique_id": "TOTALLY_UNIQUE", - }, - { - "platform": "mqtt", - "name": "Test 2", - "schema": "json", - "state_topic": "test-topic", - "command_topic": "test_topic", - "unique_id": "TOTALLY_UNIQUE", - }, - ] + mqtt.DOMAIN: { + light.DOMAIN: [ + { + "name": "Test 1", + "schema": "json", + "state_topic": "test-topic", + "command_topic": "test_topic", + "unique_id": "TOTALLY_UNIQUE", + }, + { + "name": "Test 2", + "schema": "json", + "state_topic": "test-topic", + "command_topic": "test_topic", + "unique_id": "TOTALLY_UNIQUE", + }, + ] + } } await help_test_unique_id( hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, config @@ -2033,7 +2033,7 @@ async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_ hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -2043,7 +2043,7 @@ async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_ hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -2053,7 +2053,7 @@ async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -2063,27 +2063,21 @@ async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_config): """Test MQTT subscriptions are managed when entity_id is updated.""" await help_test_entity_id_update_subscriptions( - hass, - mqtt_mock_entry_with_yaml_config, - light.DOMAIN, - DEFAULT_CONFIG_LEGACY, + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG ) async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, - mqtt_mock_entry_no_yaml_config, - light.DOMAIN, - DEFAULT_CONFIG_LEGACY, + hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG ) @@ -2093,7 +2087,7 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, light.SERVICE_TURN_ON, command_payload='{"state":"ON"}', state_payload='{"state":"ON"}', @@ -2158,9 +2152,9 @@ async def test_publishing_with_custom_encoding( ): """Test publishing MQTT payload with different encoding.""" domain = light.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[domain]) + config = copy.deepcopy(DEFAULT_CONFIG) if topic == "effect_command_topic": - config["effect_list"] = ["random", "color_loop"] + config[mqtt.DOMAIN][domain]["effect_list"] = ["random", "color_loop"] await help_test_publishing_with_custom_encoding( hass, @@ -2181,12 +2175,14 @@ async def test_publishing_with_custom_encoding( async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = light.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = light.DOMAIN @@ -2217,7 +2213,7 @@ async def test_encoding_subscribable_topics( init_payload, ): """Test handling of incoming encoded payload.""" - config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[light.DOMAIN]) + config = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][light.DOMAIN]) config["color_mode"] = True config["supported_color_modes"] = [ "color_temp", @@ -2245,11 +2241,8 @@ async def test_encoding_subscribable_topics( async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = light.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) - config["name"] = "test" - del config["platform"] - await help_test_setup_manual_entity_from_yaml(hass, platform, config) - assert hass.states.get(f"{platform}.test") is not None + await help_test_setup_manual_entity_from_yaml(hass, DEFAULT_CONFIG) + assert hass.states.get(f"{platform}.test") # Test deprecated YAML configuration under the platform key diff --git a/tests/components/mqtt/test_light_template.py b/tests/components/mqtt/test_light_template.py index d88480f9f5aa3..2b53097f502dd 100644 --- a/tests/components/mqtt/test_light_template.py +++ b/tests/components/mqtt/test_light_template.py @@ -71,7 +71,7 @@ help_test_setup_manual_entity_from_yaml, help_test_unique_id, help_test_unload_config_entry_with_platform, - help_test_update_with_json_attrs_bad_JSON, + help_test_update_with_json_attrs_bad_json, help_test_update_with_json_attrs_not_dict, ) @@ -824,28 +824,28 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG ) async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by default payload with defined topic.""" await help_test_default_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG ) async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by custom payload with defined topic.""" await help_test_custom_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG ) @@ -854,7 +854,7 @@ async def test_setting_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG ) @@ -866,7 +866,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, MQTT_LIGHT_ATTRIBUTES_BLOCKED, ) @@ -874,7 +874,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_with_template( - hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG ) @@ -887,20 +887,20 @@ async def test_update_with_json_attrs_not_dict( mqtt_mock_entry_with_yaml_config, caplog, light.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) -async def test_update_with_json_attrs_bad_JSON( +async def test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog ): """Test attributes get extracted from a JSON result.""" - await help_test_update_with_json_attrs_bad_JSON( + await help_test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog, light.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -911,33 +911,35 @@ async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplo mqtt_mock_entry_no_yaml_config, caplog, light.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) async def test_unique_id(hass, mqtt_mock_entry_with_yaml_config): """Test unique id option only creates one light per unique_id.""" config = { - light.DOMAIN: [ - { - "platform": "mqtt", - "name": "Test 1", - "schema": "template", - "state_topic": "test-topic", - "command_topic": "test_topic", - "command_on_template": "on,{{ transition }}", - "command_off_template": "off,{{ transition|d }}", - "unique_id": "TOTALLY_UNIQUE", - }, - { - "platform": "mqtt", - "name": "Test 2", - "schema": "template", - "state_topic": "test-topic", - "command_topic": "test_topic", - "unique_id": "TOTALLY_UNIQUE", - }, - ] + mqtt.DOMAIN: { + light.DOMAIN: [ + { + "name": "Test 1", + "schema": "template", + "state_topic": "test-topic", + "command_topic": "test_topic", + "command_on_template": "on,{{ transition }}", + "command_off_template": "off,{{ transition|d }}", + "unique_id": "TOTALLY_UNIQUE", + }, + { + "name": "Test 2", + "schema": "template", + "state_topic": "test-topic2", + "command_topic": "test_topic2", + "command_on_template": "on,{{ transition }}", + "command_off_template": "off,{{ transition|d }}", + "unique_id": "TOTALLY_UNIQUE", + }, + ] + } } await help_test_unique_id( hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, config @@ -1026,56 +1028,57 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT light device registry integration.""" await help_test_entity_device_info_with_connection( - hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT light device registry integration.""" await help_test_entity_device_info_with_identifier( - hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): """Test device registry update.""" await help_test_entity_device_info_update( - hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test device registry remove.""" await help_test_entity_device_info_remove( - hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG ) async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_config): """Test MQTT subscriptions are managed when entity_id is updated.""" await help_test_entity_id_update_subscriptions( - hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, light.DOMAIN, DEFAULT_CONFIG ) async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, light.DOMAIN, DEFAULT_CONFIG ) async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT debug info.""" config = { - light.DOMAIN: { - "platform": "mqtt", - "schema": "template", - "name": "test", - "command_topic": "test-topic", - "command_on_template": "ON", - "command_off_template": "off,{{ transition|d }}", - "state_template": '{{ value.split(",")[0] }}', + mqtt.DOMAIN: { + light.DOMAIN: { + "schema": "template", + "name": "test", + "command_topic": "test-topic", + "command_on_template": "ON", + "command_off_template": "off,{{ transition|d }}", + "state_template": '{{ value.split(",")[0] }}', + } } } await help_test_entity_debug_info_message( @@ -1147,9 +1150,9 @@ async def test_publishing_with_custom_encoding( ): """Test publishing MQTT payload with different encoding.""" domain = light.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[domain]) + config = copy.deepcopy(DEFAULT_CONFIG) if topic == "effect_command_topic": - config["effect_list"] = ["random", "color_loop"] + config[mqtt.DOMAIN][domain]["effect_list"] = ["random", "color_loop"] await help_test_publishing_with_custom_encoding( hass, @@ -1170,12 +1173,14 @@ async def test_publishing_with_custom_encoding( async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = light.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = light.DOMAIN @@ -1200,7 +1205,7 @@ async def test_encoding_subscribable_topics( init_payload, ): """Test handling of incoming encoded payload.""" - config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[light.DOMAIN]) + config = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][light.DOMAIN]) config["state_template"] = "{{ value }}" await help_test_encoding_subscribable_topics( hass, @@ -1219,17 +1224,14 @@ async def test_encoding_subscribable_topics( async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = light.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) - config["name"] = "test" - del config["platform"] - await help_test_setup_manual_entity_from_yaml(hass, platform, config) - assert hass.states.get(f"{platform}.test") is not None + await help_test_setup_manual_entity_from_yaml(hass, DEFAULT_CONFIG) + assert hass.states.get(f"{platform}.test") async def test_unload_entry(hass, mqtt_mock_entry_with_yaml_config, tmp_path): """Test unloading the config entry.""" domain = light.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry_with_yaml_config, tmp_path, domain, config ) diff --git a/tests/components/mqtt/test_lock.py b/tests/components/mqtt/test_lock.py index de97de23a1e17..0784065ddbec3 100644 --- a/tests/components/mqtt/test_lock.py +++ b/tests/components/mqtt/test_lock.py @@ -49,7 +49,7 @@ help_test_setup_manual_entity_from_yaml, help_test_unique_id, help_test_unload_config_entry_with_platform, - help_test_update_with_json_attrs_bad_JSON, + help_test_update_with_json_attrs_bad_json, help_test_update_with_json_attrs_not_dict, ) @@ -452,28 +452,28 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, lock.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, lock.DOMAIN, DEFAULT_CONFIG ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, lock.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, lock.DOMAIN, DEFAULT_CONFIG ) async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by default payload with defined topic.""" await help_test_default_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, lock.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, lock.DOMAIN, DEFAULT_CONFIG ) async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by custom payload with defined topic.""" await help_test_custom_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, lock.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, lock.DOMAIN, DEFAULT_CONFIG ) @@ -482,7 +482,7 @@ async def test_setting_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_with_yaml_config, lock.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, lock.DOMAIN, DEFAULT_CONFIG ) @@ -494,7 +494,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( hass, mqtt_mock_entry_no_yaml_config, lock.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, MQTT_LOCK_ATTRIBUTES_BLOCKED, ) @@ -502,7 +502,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_with_template( - hass, mqtt_mock_entry_with_yaml_config, lock.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, lock.DOMAIN, DEFAULT_CONFIG ) @@ -515,7 +515,7 @@ async def test_update_with_json_attrs_not_dict( mqtt_mock_entry_with_yaml_config, caplog, lock.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -523,41 +523,41 @@ async def test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog ): """Test attributes get extracted from a JSON result.""" - await help_test_update_with_json_attrs_bad_JSON( + await help_test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog, lock.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test update of discovered MQTTAttributes.""" await help_test_discovery_update_attr( - hass, mqtt_mock_entry_no_yaml_config, caplog, lock.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, caplog, lock.DOMAIN, DEFAULT_CONFIG ) async def test_unique_id(hass, mqtt_mock_entry_with_yaml_config): """Test unique id option only creates one lock per unique_id.""" config = { - lock.DOMAIN: [ - { - "platform": "mqtt", - "name": "Test 1", - "state_topic": "test-topic", - "command_topic": "test_topic", - "unique_id": "TOTALLY_UNIQUE", - }, - { - "platform": "mqtt", - "name": "Test 2", - "state_topic": "test-topic", - "command_topic": "test_topic", - "unique_id": "TOTALLY_UNIQUE", - }, - ] + mqtt.DOMAIN: { + lock.DOMAIN: [ + { + "name": "Test 1", + "state_topic": "test-topic", + "command_topic": "test_topic", + "unique_id": "TOTALLY_UNIQUE", + }, + { + "name": "Test 2", + "state_topic": "test-topic", + "command_topic": "test_topic", + "unique_id": "TOTALLY_UNIQUE", + }, + ] + } } await help_test_unique_id( hass, mqtt_mock_entry_with_yaml_config, lock.DOMAIN, config @@ -626,42 +626,42 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT lock device registry integration.""" await help_test_entity_device_info_with_connection( - hass, mqtt_mock_entry_no_yaml_config, lock.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, lock.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT lock device registry integration.""" await help_test_entity_device_info_with_identifier( - hass, mqtt_mock_entry_no_yaml_config, lock.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, lock.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): """Test device registry update.""" await help_test_entity_device_info_update( - hass, mqtt_mock_entry_no_yaml_config, lock.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, lock.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test device registry remove.""" await help_test_entity_device_info_remove( - hass, mqtt_mock_entry_no_yaml_config, lock.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, lock.DOMAIN, DEFAULT_CONFIG ) async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_config): """Test MQTT subscriptions are managed when entity_id is updated.""" await help_test_entity_id_update_subscriptions( - hass, mqtt_mock_entry_with_yaml_config, lock.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, lock.DOMAIN, DEFAULT_CONFIG ) async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, lock.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, lock.DOMAIN, DEFAULT_CONFIG ) @@ -671,7 +671,7 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): hass, mqtt_mock_entry_no_yaml_config, lock.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, SERVICE_LOCK, command_payload="LOCK", ) @@ -701,7 +701,7 @@ async def test_publishing_with_custom_encoding( ): """Test publishing MQTT payload with different encoding.""" domain = lock.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_publishing_with_custom_encoding( hass, @@ -720,12 +720,14 @@ async def test_publishing_with_custom_encoding( async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = lock.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = lock.DOMAIN @@ -754,7 +756,7 @@ async def test_encoding_subscribable_topics( mqtt_mock_entry_with_yaml_config, caplog, lock.DOMAIN, - DEFAULT_CONFIG_LEGACY[lock.DOMAIN], + DEFAULT_CONFIG[mqtt.DOMAIN][lock.DOMAIN], topic, value, attribute, @@ -765,17 +767,14 @@ async def test_encoding_subscribable_topics( async def test_setup_manual_entity_from_yaml(hass, caplog, tmp_path): """Test setup manual configured MQTT entity.""" platform = lock.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) - config["name"] = "test" - del config["platform"] - await help_test_setup_manual_entity_from_yaml(hass, platform, config) - assert hass.states.get(f"{platform}.test") is not None + await help_test_setup_manual_entity_from_yaml(hass, DEFAULT_CONFIG) + assert hass.states.get(f"{platform}.test") async def test_unload_entry(hass, mqtt_mock_entry_with_yaml_config, tmp_path): """Test unloading the config entry.""" domain = lock.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry_with_yaml_config, tmp_path, domain, config ) diff --git a/tests/components/mqtt/test_number.py b/tests/components/mqtt/test_number.py index 69b0473fb9d0e..65c8655472c11 100644 --- a/tests/components/mqtt/test_number.py +++ b/tests/components/mqtt/test_number.py @@ -59,7 +59,7 @@ help_test_setup_manual_entity_from_yaml, help_test_unique_id, help_test_unload_config_entry_with_platform, - help_test_update_with_json_attrs_bad_JSON, + help_test_update_with_json_attrs_bad_json, help_test_update_with_json_attrs_not_dict, ) @@ -446,28 +446,28 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, number.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, number.DOMAIN, DEFAULT_CONFIG ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, number.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, number.DOMAIN, DEFAULT_CONFIG ) async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by default payload with defined topic.""" await help_test_default_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, number.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, number.DOMAIN, DEFAULT_CONFIG ) async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by custom payload with defined topic.""" await help_test_custom_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, number.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, number.DOMAIN, DEFAULT_CONFIG ) @@ -476,7 +476,7 @@ async def test_setting_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_with_yaml_config, number.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, number.DOMAIN, DEFAULT_CONFIG ) @@ -488,7 +488,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( hass, mqtt_mock_entry_no_yaml_config, number.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, MQTT_NUMBER_ATTRIBUTES_BLOCKED, ) @@ -496,7 +496,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_with_template( - hass, mqtt_mock_entry_with_yaml_config, number.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, number.DOMAIN, DEFAULT_CONFIG ) @@ -509,20 +509,20 @@ async def test_update_with_json_attrs_not_dict( mqtt_mock_entry_with_yaml_config, caplog, number.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) -async def test_update_with_json_attrs_bad_JSON( +async def test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog ): """Test attributes get extracted from a JSON result.""" - await help_test_update_with_json_attrs_bad_JSON( + await help_test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog, number.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -533,29 +533,29 @@ async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplo mqtt_mock_entry_no_yaml_config, caplog, number.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) async def test_unique_id(hass, mqtt_mock_entry_with_yaml_config): """Test unique id option only creates one number per unique_id.""" config = { - number.DOMAIN: [ - { - "platform": "mqtt", - "name": "Test 1", - "state_topic": "test-topic", - "command_topic": "test-topic", - "unique_id": "TOTALLY_UNIQUE", - }, - { - "platform": "mqtt", - "name": "Test 2", - "state_topic": "test-topic", - "command_topic": "test-topic", - "unique_id": "TOTALLY_UNIQUE", - }, - ] + mqtt.DOMAIN: { + number.DOMAIN: [ + { + "name": "Test 1", + "state_topic": "test-topic", + "command_topic": "test-topic", + "unique_id": "TOTALLY_UNIQUE", + }, + { + "name": "Test 2", + "state_topic": "test-topic", + "command_topic": "test-topic", + "unique_id": "TOTALLY_UNIQUE", + }, + ] + } } await help_test_unique_id( hass, mqtt_mock_entry_with_yaml_config, number.DOMAIN, config @@ -564,7 +564,7 @@ async def test_unique_id(hass, mqtt_mock_entry_with_yaml_config): async def test_discovery_removal_number(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test removal of discovered number.""" - data = json.dumps(DEFAULT_CONFIG_LEGACY[number.DOMAIN]) + data = json.dumps(DEFAULT_CONFIG[mqtt.DOMAIN][number.DOMAIN]) await help_test_discovery_removal( hass, mqtt_mock_entry_no_yaml_config, caplog, number.DOMAIN, data ) @@ -624,42 +624,42 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT number device registry integration.""" await help_test_entity_device_info_with_connection( - hass, mqtt_mock_entry_no_yaml_config, number.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, number.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT number device registry integration.""" await help_test_entity_device_info_with_identifier( - hass, mqtt_mock_entry_no_yaml_config, number.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, number.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): """Test device registry update.""" await help_test_entity_device_info_update( - hass, mqtt_mock_entry_no_yaml_config, number.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, number.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test device registry remove.""" await help_test_entity_device_info_remove( - hass, mqtt_mock_entry_no_yaml_config, number.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, number.DOMAIN, DEFAULT_CONFIG ) async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_config): """Test MQTT subscriptions are managed when entity_id is updated.""" await help_test_entity_id_update_subscriptions( - hass, mqtt_mock_entry_with_yaml_config, number.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, number.DOMAIN, DEFAULT_CONFIG ) async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, number.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, number.DOMAIN, DEFAULT_CONFIG ) @@ -669,7 +669,7 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): hass, mqtt_mock_entry_no_yaml_config, number.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, SERVICE_SET_VALUE, service_parameters={ATTR_VALUE: 45}, command_payload="45", @@ -882,7 +882,7 @@ async def test_publishing_with_custom_encoding( ): """Test publishing MQTT payload with different encoding.""" domain = NUMBER_DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_publishing_with_custom_encoding( hass, @@ -901,12 +901,14 @@ async def test_publishing_with_custom_encoding( async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = number.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = number.DOMAIN @@ -935,8 +937,8 @@ async def test_encoding_subscribable_topics( hass, mqtt_mock_entry_with_yaml_config, caplog, - "number", - DEFAULT_CONFIG_LEGACY["number"], + number.DOMAIN, + DEFAULT_CONFIG[mqtt.DOMAIN][number.DOMAIN], topic, value, attribute, @@ -947,17 +949,14 @@ async def test_encoding_subscribable_topics( async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = number.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) - config["name"] = "test" - del config["platform"] - await help_test_setup_manual_entity_from_yaml(hass, platform, config) - assert hass.states.get(f"{platform}.test") is not None + await help_test_setup_manual_entity_from_yaml(hass, DEFAULT_CONFIG) + assert hass.states.get(f"{platform}.test") async def test_unload_entry(hass, mqtt_mock_entry_with_yaml_config, tmp_path): """Test unloading the config entry.""" domain = number.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry_with_yaml_config, tmp_path, domain, config ) diff --git a/tests/components/mqtt/test_scene.py b/tests/components/mqtt/test_scene.py index a1c1644cc37ac..122c32caa036c 100644 --- a/tests/components/mqtt/test_scene.py +++ b/tests/components/mqtt/test_scene.py @@ -87,25 +87,26 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, scene.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, scene.DOMAIN, DEFAULT_CONFIG ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, scene.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, scene.DOMAIN, DEFAULT_CONFIG ) async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by default payload with defined topic.""" config = { - scene.DOMAIN: { - "platform": "mqtt", - "name": "test", - "command_topic": "command-topic", - "payload_on": 1, + mqtt.DOMAIN: { + scene.DOMAIN: { + "name": "test", + "command_topic": "command-topic", + "payload_on": 1, + } } } @@ -123,11 +124,12 @@ async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_conf async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by custom payload with defined topic.""" config = { - scene.DOMAIN: { - "platform": "mqtt", - "name": "test", - "command_topic": "command-topic", - "payload_on": 1, + mqtt.DOMAIN: { + scene.DOMAIN: { + "name": "test", + "command_topic": "command-topic", + "payload_on": 1, + } } } @@ -145,20 +147,20 @@ async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_confi async def test_unique_id(hass, mqtt_mock_entry_with_yaml_config): """Test unique id option only creates one scene per unique_id.""" config = { - scene.DOMAIN: [ - { - "platform": "mqtt", - "name": "Test 1", - "command_topic": "command-topic", - "unique_id": "TOTALLY_UNIQUE", - }, - { - "platform": "mqtt", - "name": "Test 2", - "command_topic": "command-topic", - "unique_id": "TOTALLY_UNIQUE", - }, - ] + mqtt.DOMAIN: { + scene.DOMAIN: [ + { + "name": "Test 1", + "command_topic": "command-topic", + "unique_id": "TOTALLY_UNIQUE", + }, + { + "name": "Test 2", + "command_topic": "command-topic", + "unique_id": "TOTALLY_UNIQUE", + }, + ] + } } await help_test_unique_id( hass, mqtt_mock_entry_with_yaml_config, scene.DOMAIN, config @@ -175,8 +177,8 @@ async def test_discovery_removal_scene(hass, mqtt_mock_entry_no_yaml_config, cap async def test_discovery_update_payload(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test update of discovered scene.""" - config1 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[scene.DOMAIN]) - config2 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[scene.DOMAIN]) + config1 = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][scene.DOMAIN]) + config2 = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][scene.DOMAIN]) config1["name"] = "Beer" config2["name"] = "Milk" config1["payload_on"] = "ON" @@ -223,12 +225,14 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = scene.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = scene.DOMAIN @@ -239,17 +243,14 @@ async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = scene.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) - config["name"] = "test" - del config["platform"] - await help_test_setup_manual_entity_from_yaml(hass, platform, config) - assert hass.states.get(f"{platform}.test") is not None + await help_test_setup_manual_entity_from_yaml(hass, DEFAULT_CONFIG) + assert hass.states.get(f"{platform}.test") async def test_unload_entry(hass, mqtt_mock_entry_with_yaml_config, tmp_path): """Test unloading the config entry.""" domain = scene.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry_with_yaml_config, tmp_path, domain, config ) diff --git a/tests/components/mqtt/test_select.py b/tests/components/mqtt/test_select.py index c66638a18af96..5b5883040616e 100644 --- a/tests/components/mqtt/test_select.py +++ b/tests/components/mqtt/test_select.py @@ -49,7 +49,7 @@ help_test_setup_manual_entity_from_yaml, help_test_unique_id, help_test_unload_config_entry_with_platform, - help_test_update_with_json_attrs_bad_JSON, + help_test_update_with_json_attrs_bad_json, help_test_update_with_json_attrs_not_dict, ) @@ -323,28 +323,28 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, select.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, select.DOMAIN, DEFAULT_CONFIG ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, select.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, select.DOMAIN, DEFAULT_CONFIG ) async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by default payload with defined topic.""" await help_test_default_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, select.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, select.DOMAIN, DEFAULT_CONFIG ) async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by custom payload with defined topic.""" await help_test_custom_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, select.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, select.DOMAIN, DEFAULT_CONFIG ) @@ -353,7 +353,7 @@ async def test_setting_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_with_yaml_config, select.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, select.DOMAIN, DEFAULT_CONFIG ) @@ -365,7 +365,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( hass, mqtt_mock_entry_no_yaml_config, select.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, MQTT_SELECT_ATTRIBUTES_BLOCKED, ) @@ -373,7 +373,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_with_template( - hass, mqtt_mock_entry_with_yaml_config, select.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, select.DOMAIN, DEFAULT_CONFIG ) @@ -386,20 +386,20 @@ async def test_update_with_json_attrs_not_dict( mqtt_mock_entry_with_yaml_config, caplog, select.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) -async def test_update_with_json_attrs_bad_JSON( +async def test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog ): """Test attributes get extracted from a JSON result.""" - await help_test_update_with_json_attrs_bad_JSON( + await help_test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog, select.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -410,31 +410,31 @@ async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplo mqtt_mock_entry_no_yaml_config, caplog, select.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) async def test_unique_id(hass, mqtt_mock_entry_with_yaml_config): """Test unique id option only creates one select per unique_id.""" config = { - select.DOMAIN: [ - { - "platform": "mqtt", - "name": "Test 1", - "state_topic": "test-topic", - "command_topic": "test-topic", - "unique_id": "TOTALLY_UNIQUE", - "options": ["milk", "beer"], - }, - { - "platform": "mqtt", - "name": "Test 2", - "state_topic": "test-topic", - "command_topic": "test-topic", - "unique_id": "TOTALLY_UNIQUE", - "options": ["milk", "beer"], - }, - ] + mqtt.DOMAIN: { + select.DOMAIN: [ + { + "name": "Test 1", + "state_topic": "test-topic", + "command_topic": "test-topic", + "unique_id": "TOTALLY_UNIQUE", + "options": ["milk", "beer"], + }, + { + "name": "Test 2", + "state_topic": "test-topic", + "command_topic": "test-topic", + "unique_id": "TOTALLY_UNIQUE", + "options": ["milk", "beer"], + }, + ] + } } await help_test_unique_id( hass, mqtt_mock_entry_with_yaml_config, select.DOMAIN, config @@ -443,7 +443,7 @@ async def test_unique_id(hass, mqtt_mock_entry_with_yaml_config): async def test_discovery_removal_select(hass, mqtt_mock_entry_no_yaml_config, caplog): """Test removal of discovered select.""" - data = json.dumps(DEFAULT_CONFIG_LEGACY[select.DOMAIN]) + data = json.dumps(DEFAULT_CONFIG[mqtt.DOMAIN][select.DOMAIN]) await help_test_discovery_removal( hass, mqtt_mock_entry_no_yaml_config, caplog, select.DOMAIN, data ) @@ -501,42 +501,42 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT select device registry integration.""" await help_test_entity_device_info_with_connection( - hass, mqtt_mock_entry_no_yaml_config, select.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, select.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT select device registry integration.""" await help_test_entity_device_info_with_identifier( - hass, mqtt_mock_entry_no_yaml_config, select.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, select.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): """Test device registry update.""" await help_test_entity_device_info_update( - hass, mqtt_mock_entry_no_yaml_config, select.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, select.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test device registry remove.""" await help_test_entity_device_info_remove( - hass, mqtt_mock_entry_no_yaml_config, select.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, select.DOMAIN, DEFAULT_CONFIG ) async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_config): """Test MQTT subscriptions are managed when entity_id is updated.""" await help_test_entity_id_update_subscriptions( - hass, mqtt_mock_entry_with_yaml_config, select.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, select.DOMAIN, DEFAULT_CONFIG ) async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, select.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, select.DOMAIN, DEFAULT_CONFIG ) @@ -546,7 +546,7 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): hass, mqtt_mock_entry_no_yaml_config, select.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, select.SERVICE_SELECT_OPTION, service_parameters={ATTR_OPTION: "beer"}, command_payload="beer", @@ -635,8 +635,8 @@ async def test_publishing_with_custom_encoding( ): """Test publishing MQTT payload with different encoding.""" domain = select.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] - config["options"] = ["milk", "beer"] + config = DEFAULT_CONFIG + config[mqtt.DOMAIN][domain]["options"] = ["milk", "beer"] await help_test_publishing_with_custom_encoding( hass, @@ -655,12 +655,14 @@ async def test_publishing_with_custom_encoding( async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = select.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = select.DOMAIN @@ -685,13 +687,13 @@ async def test_encoding_subscribable_topics( attribute_value, ): """Test handling of incoming encoded payload.""" - config = copy.deepcopy(DEFAULT_CONFIG_LEGACY["select"]) + config = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][select.DOMAIN]) config["options"] = ["milk", "beer"] await help_test_encoding_subscribable_topics( hass, mqtt_mock_entry_with_yaml_config, caplog, - "select", + select.DOMAIN, config, topic, value, @@ -703,17 +705,14 @@ async def test_encoding_subscribable_topics( async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = select.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) - config["name"] = "test" - del config["platform"] - await help_test_setup_manual_entity_from_yaml(hass, platform, config) - assert hass.states.get(f"{platform}.test") is not None + await help_test_setup_manual_entity_from_yaml(hass, DEFAULT_CONFIG) + assert hass.states.get(f"{platform}.test") async def test_unload_entry(hass, mqtt_mock_entry_with_yaml_config, tmp_path): """Test unloading the config entry.""" domain = select.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry_with_yaml_config, tmp_path, domain, config ) diff --git a/tests/components/mqtt/test_sensor.py b/tests/components/mqtt/test_sensor.py index c5cf377cf1adc..6cfaa9678bba3 100644 --- a/tests/components/mqtt/test_sensor.py +++ b/tests/components/mqtt/test_sensor.py @@ -59,7 +59,7 @@ help_test_setup_manual_entity_from_yaml, help_test_unique_id, help_test_unload_config_entry_with_platform, - help_test_update_with_json_attrs_bad_JSON, + help_test_update_with_json_attrs_bad_json, help_test_update_with_json_attrs_not_dict, ) @@ -585,21 +585,21 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG ) async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by default payload with defined topic.""" await help_test_default_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG ) @@ -608,7 +608,7 @@ async def test_default_availability_list_payload( ): """Test availability by default payload with defined topic.""" await help_test_default_availability_list_payload( - hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG ) @@ -617,7 +617,7 @@ async def test_default_availability_list_payload_all( ): """Test availability by default payload with defined topic.""" await help_test_default_availability_list_payload_all( - hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG ) @@ -626,34 +626,31 @@ async def test_default_availability_list_payload_any( ): """Test availability by default payload with defined topic.""" await help_test_default_availability_list_payload_any( - hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG ) -async def test_default_availability_list_single( - hass, mqtt_mock_entry_no_yaml_config, caplog -): +async def test_default_availability_list_single(hass, caplog): """Test availability list and availability_topic are mutually exclusive.""" await help_test_default_availability_list_single( hass, - mqtt_mock_entry_no_yaml_config, caplog, sensor.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by custom payload with defined topic.""" await help_test_custom_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG ) async def test_discovery_update_availability(hass, mqtt_mock_entry_no_yaml_config): """Test availability discovery update.""" await help_test_discovery_update_availability( - hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG ) @@ -760,7 +757,7 @@ async def test_setting_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG ) @@ -772,7 +769,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, MQTT_SENSOR_ATTRIBUTES_BLOCKED, ) @@ -780,7 +777,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_with_template( - hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG ) @@ -793,20 +790,20 @@ async def test_update_with_json_attrs_not_dict( mqtt_mock_entry_with_yaml_config, caplog, sensor.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) -async def test_update_with_json_attrs_bad_JSON( +async def test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog ): """Test attributes get extracted from a JSON result.""" - await help_test_update_with_json_attrs_bad_JSON( + await help_test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog, sensor.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -817,27 +814,27 @@ async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplo mqtt_mock_entry_no_yaml_config, caplog, sensor.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) async def test_unique_id(hass, mqtt_mock_entry_with_yaml_config): """Test unique id option only creates one sensor per unique_id.""" config = { - sensor.DOMAIN: [ - { - "platform": "mqtt", - "name": "Test 1", - "state_topic": "test-topic", - "unique_id": "TOTALLY_UNIQUE", - }, - { - "platform": "mqtt", - "name": "Test 2", - "state_topic": "test-topic", - "unique_id": "TOTALLY_UNIQUE", - }, - ] + mqtt.DOMAIN: { + sensor.DOMAIN: [ + { + "name": "Test 1", + "state_topic": "test-topic", + "unique_id": "TOTALLY_UNIQUE", + }, + { + "name": "Test 2", + "state_topic": "test-topic", + "unique_id": "TOTALLY_UNIQUE", + }, + ] + } } await help_test_unique_id( hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, config @@ -951,42 +948,42 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT sensor device registry integration.""" await help_test_entity_device_info_with_connection( - hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT sensor device registry integration.""" await help_test_entity_device_info_with_identifier( - hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): """Test device registry update.""" await help_test_entity_device_info_update( - hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test device registry remove.""" await help_test_entity_device_info_remove( - hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG ) async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_config): """Test MQTT subscriptions are managed when entity_id is updated.""" await help_test_entity_id_update_subscriptions( - hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG ) async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG ) @@ -1021,42 +1018,42 @@ async def test_entity_device_info_with_hub(hass, mqtt_mock_entry_no_yaml_config) async def test_entity_debug_info(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT sensor debug info.""" await help_test_entity_debug_info( - hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG ) async def test_entity_debug_info_max_messages(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT sensor debug info.""" await help_test_entity_debug_info_max_messages( - hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG ) async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT debug info.""" await help_test_entity_debug_info_message( - hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY, None + hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG, None ) async def test_entity_debug_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT sensor debug info.""" await help_test_entity_debug_info_remove( - hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG ) async def test_entity_debug_info_update_entity_id(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT sensor debug info.""" await help_test_entity_debug_info_update_entity_id( - hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG ) async def test_entity_disabled_by_default(hass, mqtt_mock_entry_no_yaml_config): """Test entity disabled by default.""" await help_test_entity_disabled_by_default( - hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG ) @@ -1064,7 +1061,7 @@ async def test_entity_disabled_by_default(hass, mqtt_mock_entry_no_yaml_config): async def test_entity_category(hass, mqtt_mock_entry_no_yaml_config): """Test entity category.""" await help_test_entity_category( - hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, sensor.DOMAIN, DEFAULT_CONFIG ) @@ -1101,12 +1098,14 @@ async def test_value_template_with_entity_id(hass, mqtt_mock_entry_with_yaml_con async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = sensor.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = sensor.DOMAIN @@ -1230,7 +1229,7 @@ async def test_encoding_subscribable_topics( mqtt_mock_entry_with_yaml_config, caplog, sensor.DOMAIN, - DEFAULT_CONFIG_LEGACY[sensor.DOMAIN], + DEFAULT_CONFIG[mqtt.DOMAIN][sensor.DOMAIN], topic, value, attribute, @@ -1242,17 +1241,14 @@ async def test_encoding_subscribable_topics( async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = sensor.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) - config["name"] = "test" - del config["platform"] - await help_test_setup_manual_entity_from_yaml(hass, platform, config) - assert hass.states.get(f"{platform}.test") is not None + await help_test_setup_manual_entity_from_yaml(hass, DEFAULT_CONFIG) + assert hass.states.get(f"{platform}.test") async def test_unload_entry(hass, mqtt_mock_entry_with_yaml_config, tmp_path): """Test unloading the config entry.""" domain = sensor.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry_with_yaml_config, tmp_path, domain, config ) diff --git a/tests/components/mqtt/test_siren.py b/tests/components/mqtt/test_siren.py index fd91847f7672c..7c16f3f01a3e2 100644 --- a/tests/components/mqtt/test_siren.py +++ b/tests/components/mqtt/test_siren.py @@ -46,7 +46,7 @@ help_test_setup_manual_entity_from_yaml, help_test_unique_id, help_test_unload_config_entry_with_platform, - help_test_update_with_json_attrs_bad_JSON, + help_test_update_with_json_attrs_bad_json, help_test_update_with_json_attrs_not_dict, ) @@ -457,27 +457,28 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, siren.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, siren.DOMAIN, DEFAULT_CONFIG ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, siren.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, siren.DOMAIN, DEFAULT_CONFIG ) async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by default payload with defined topic.""" config = { - siren.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "payload_on": 1, - "payload_off": 0, + mqtt.DOMAIN: { + siren.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "payload_on": 1, + "payload_off": 0, + } } } @@ -495,13 +496,14 @@ async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_conf async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by custom payload with defined topic.""" config = { - siren.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "payload_on": 1, - "payload_off": 0, + mqtt.DOMAIN: { + siren.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "payload_on": 1, + "payload_off": 0, + } } } @@ -558,7 +560,7 @@ async def test_setting_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_with_yaml_config, siren.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, siren.DOMAIN, DEFAULT_CONFIG ) @@ -567,14 +569,14 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_blocked_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_no_yaml_config, siren.DOMAIN, DEFAULT_CONFIG_LEGACY, {} + hass, mqtt_mock_entry_no_yaml_config, siren.DOMAIN, DEFAULT_CONFIG, {} ) async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_with_template( - hass, mqtt_mock_entry_with_yaml_config, siren.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, siren.DOMAIN, DEFAULT_CONFIG ) @@ -587,20 +589,20 @@ async def test_update_with_json_attrs_not_dict( mqtt_mock_entry_with_yaml_config, caplog, siren.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) -async def test_update_with_json_attrs_bad_JSON( +async def test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog ): """Test attributes get extracted from a JSON result.""" - await help_test_update_with_json_attrs_bad_JSON( + await help_test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog, siren.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -611,29 +613,29 @@ async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplo mqtt_mock_entry_no_yaml_config, caplog, siren.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) async def test_unique_id(hass, mqtt_mock_entry_with_yaml_config): """Test unique id option only creates one siren per unique_id.""" config = { - siren.DOMAIN: [ - { - "platform": "mqtt", - "name": "Test 1", - "state_topic": "test-topic", - "command_topic": "command-topic", - "unique_id": "TOTALLY_UNIQUE", - }, - { - "platform": "mqtt", - "name": "Test 2", - "state_topic": "test-topic", - "command_topic": "command-topic", - "unique_id": "TOTALLY_UNIQUE", - }, - ] + mqtt.DOMAIN: { + siren.DOMAIN: [ + { + "name": "Test 1", + "state_topic": "test-topic", + "command_topic": "command-topic", + "unique_id": "TOTALLY_UNIQUE", + }, + { + "name": "Test 2", + "state_topic": "test-topic", + "command_topic": "command-topic", + "unique_id": "TOTALLY_UNIQUE", + }, + ] + } } await help_test_unique_id( hass, mqtt_mock_entry_with_yaml_config, siren.DOMAIN, config @@ -656,8 +658,8 @@ async def test_discovery_update_siren_topic_template( hass, mqtt_mock_entry_no_yaml_config, caplog ): """Test update of discovered siren.""" - config1 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[siren.DOMAIN]) - config2 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[siren.DOMAIN]) + config1 = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][siren.DOMAIN]) + config2 = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][siren.DOMAIN]) config1["name"] = "Beer" config2["name"] = "Milk" config1["state_topic"] = "siren/state1" @@ -693,8 +695,8 @@ async def test_discovery_update_siren_template( hass, mqtt_mock_entry_no_yaml_config, caplog ): """Test update of discovered siren.""" - config1 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[siren.DOMAIN]) - config2 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[siren.DOMAIN]) + config1 = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][siren.DOMAIN]) + config2 = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][siren.DOMAIN]) config1["name"] = "Beer" config2["name"] = "Milk" config1["state_topic"] = "siren/state1" @@ -844,42 +846,42 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT siren device registry integration.""" await help_test_entity_device_info_with_connection( - hass, mqtt_mock_entry_no_yaml_config, siren.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, siren.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT siren device registry integration.""" await help_test_entity_device_info_with_identifier( - hass, mqtt_mock_entry_no_yaml_config, siren.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, siren.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): """Test device registry update.""" await help_test_entity_device_info_update( - hass, mqtt_mock_entry_no_yaml_config, siren.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, siren.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test device registry remove.""" await help_test_entity_device_info_remove( - hass, mqtt_mock_entry_no_yaml_config, siren.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, siren.DOMAIN, DEFAULT_CONFIG ) async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_config): """Test MQTT subscriptions are managed when entity_id is updated.""" await help_test_entity_id_update_subscriptions( - hass, mqtt_mock_entry_with_yaml_config, siren.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, siren.DOMAIN, DEFAULT_CONFIG ) async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, siren.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, siren.DOMAIN, DEFAULT_CONFIG ) @@ -889,7 +891,7 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): hass, mqtt_mock_entry_no_yaml_config, siren.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, siren.SERVICE_TURN_ON, command_payload='{"state":"ON"}', ) @@ -926,8 +928,8 @@ async def test_publishing_with_custom_encoding( ): """Test publishing MQTT payload with command templates and different encoding.""" domain = siren.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[domain]) - config[siren.ATTR_AVAILABLE_TONES] = ["siren", "xylophone"] + config = copy.deepcopy(DEFAULT_CONFIG) + config[mqtt.DOMAIN][domain][siren.ATTR_AVAILABLE_TONES] = ["siren", "xylophone"] await help_test_publishing_with_custom_encoding( hass, @@ -946,12 +948,14 @@ async def test_publishing_with_custom_encoding( async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = siren.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = siren.DOMAIN @@ -980,7 +984,7 @@ async def test_encoding_subscribable_topics( mqtt_mock_entry_with_yaml_config, caplog, siren.DOMAIN, - DEFAULT_CONFIG_LEGACY[siren.DOMAIN], + DEFAULT_CONFIG[mqtt.DOMAIN][siren.DOMAIN], topic, value, attribute, @@ -991,17 +995,14 @@ async def test_encoding_subscribable_topics( async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = siren.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) - config["name"] = "test" - del config["platform"] - await help_test_setup_manual_entity_from_yaml(hass, platform, config) - assert hass.states.get(f"{platform}.test") is not None + await help_test_setup_manual_entity_from_yaml(hass, DEFAULT_CONFIG) + assert hass.states.get(f"{platform}.test") async def test_unload_entry(hass, mqtt_mock_entry_with_yaml_config, tmp_path): """Test unloading the config entry.""" domain = siren.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry_with_yaml_config, tmp_path, domain, config ) diff --git a/tests/components/mqtt/test_state_vacuum.py b/tests/components/mqtt/test_state_vacuum.py index 4c2fbf3a596d5..917c5fa43d8a9 100644 --- a/tests/components/mqtt/test_state_vacuum.py +++ b/tests/components/mqtt/test_state_vacuum.py @@ -61,7 +61,7 @@ help_test_setting_blocked_attribute_via_mqtt_json_message, help_test_setup_manual_entity_from_yaml, help_test_unique_id, - help_test_update_with_json_attrs_bad_JSON, + help_test_update_with_json_attrs_bad_json, help_test_update_with_json_attrs_not_dict, ) @@ -375,28 +375,28 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY + hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY + hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 ) async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by default payload with defined topic.""" await help_test_default_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY + hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 ) async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by custom payload with defined topic.""" await help_test_custom_availability_payload( - hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY + hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 ) @@ -405,7 +405,7 @@ async def test_setting_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY + hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 ) @@ -417,7 +417,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, - DEFAULT_CONFIG_2_LEGACY, + DEFAULT_CONFIG_2, MQTT_VACUUM_ATTRIBUTES_BLOCKED, ) @@ -425,7 +425,7 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_with_template( - hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY + hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 ) @@ -438,7 +438,7 @@ async def test_update_with_json_attrs_not_dict( mqtt_mock_entry_with_yaml_config, caplog, vacuum.DOMAIN, - DEFAULT_CONFIG_2_LEGACY, + DEFAULT_CONFIG_2, ) @@ -446,12 +446,12 @@ async def test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog ): """Test attributes get extracted from a JSON result.""" - await help_test_update_with_json_attrs_bad_JSON( + await help_test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog, vacuum.DOMAIN, - DEFAULT_CONFIG_2_LEGACY, + DEFAULT_CONFIG_2, ) @@ -462,29 +462,29 @@ async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplo mqtt_mock_entry_no_yaml_config, caplog, vacuum.DOMAIN, - DEFAULT_CONFIG_2_LEGACY, + DEFAULT_CONFIG_2, ) async def test_unique_id(hass, mqtt_mock_entry_with_yaml_config): """Test unique id option only creates one vacuum per unique_id.""" config = { - vacuum.DOMAIN: [ - { - "platform": "mqtt", - "schema": "state", - "name": "Test 1", - "command_topic": "command-topic", - "unique_id": "TOTALLY_UNIQUE", - }, - { - "platform": "mqtt", - "schema": "state", - "name": "Test 2", - "command_topic": "command-topic", - "unique_id": "TOTALLY_UNIQUE", - }, - ] + mqtt.DOMAIN: { + vacuum.DOMAIN: [ + { + "schema": "state", + "name": "Test 1", + "command_topic": "command-topic", + "unique_id": "TOTALLY_UNIQUE", + }, + { + "schema": "state", + "name": "Test 2", + "command_topic": "command-topic", + "unique_id": "TOTALLY_UNIQUE", + }, + ] + } } await help_test_unique_id( hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, config @@ -539,42 +539,42 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT vacuum device registry integration.""" await help_test_entity_device_info_with_connection( - hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY + hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 ) async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT vacuum device registry integration.""" await help_test_entity_device_info_with_identifier( - hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY + hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 ) async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): """Test device registry update.""" await help_test_entity_device_info_update( - hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY + hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 ) async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test device registry remove.""" await help_test_entity_device_info_remove( - hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY + hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 ) async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_config): """Test MQTT subscriptions are managed when entity_id is updated.""" await help_test_entity_id_update_subscriptions( - hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY + hass, mqtt_mock_entry_with_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 ) async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2_LEGACY + hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, DEFAULT_CONFIG_2 ) @@ -584,7 +584,7 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): hass, mqtt_mock_entry_no_yaml_config, vacuum.DOMAIN, - DEFAULT_CONFIG_2_LEGACY, + DEFAULT_CONFIG_2, vacuum.SERVICE_START, command_payload="start", state_payload="{}", @@ -643,8 +643,8 @@ async def test_publishing_with_custom_encoding( ): """Test publishing MQTT payload with different encoding.""" domain = vacuum.DOMAIN - config = deepcopy(DEFAULT_CONFIG_LEGACY[domain]) - config["supported_features"] = [ + config = deepcopy(DEFAULT_CONFIG) + config[mqtt.DOMAIN][domain]["supported_features"] = [ "battery", "clean_spot", "fan_speed", @@ -674,12 +674,14 @@ async def test_publishing_with_custom_encoding( async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = vacuum.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = vacuum.DOMAIN @@ -719,7 +721,7 @@ async def test_encoding_subscribable_topics( mqtt_mock_entry_with_yaml_config, caplog, vacuum.DOMAIN, - DEFAULT_CONFIG_LEGACY[vacuum.DOMAIN], + DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN], topic, value, attribute, @@ -731,11 +733,8 @@ async def test_encoding_subscribable_topics( async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = vacuum.DOMAIN - config = deepcopy(DEFAULT_CONFIG_LEGACY[platform]) - config["name"] = "test" - del config["platform"] - await help_test_setup_manual_entity_from_yaml(hass, platform, config) - assert hass.states.get(f"{platform}.test") is not None + await help_test_setup_manual_entity_from_yaml(hass, DEFAULT_CONFIG) + assert hass.states.get(f"{platform}.mqtttest") # Test deprecated YAML configuration under the platform key diff --git a/tests/components/mqtt/test_switch.py b/tests/components/mqtt/test_switch.py index 87d919f41c5f7..72a0952924271 100644 --- a/tests/components/mqtt/test_switch.py +++ b/tests/components/mqtt/test_switch.py @@ -43,7 +43,7 @@ help_test_setup_manual_entity_from_yaml, help_test_unique_id, help_test_unload_config_entry_with_platform, - help_test_update_with_json_attrs_bad_JSON, + help_test_update_with_json_attrs_bad_json, help_test_update_with_json_attrs_not_dict, ) @@ -227,27 +227,28 @@ async def test_availability_when_connection_lost( ): """Test availability after MQTT disconnection.""" await help_test_availability_when_connection_lost( - hass, mqtt_mock_entry_with_yaml_config, switch.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, switch.DOMAIN, DEFAULT_CONFIG ) async def test_availability_without_topic(hass, mqtt_mock_entry_with_yaml_config): """Test availability without defined availability topic.""" await help_test_availability_without_topic( - hass, mqtt_mock_entry_with_yaml_config, switch.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, switch.DOMAIN, DEFAULT_CONFIG ) async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by default payload with defined topic.""" config = { - switch.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "payload_on": 1, - "payload_off": 0, + mqtt.DOMAIN: { + switch.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "payload_on": 1, + "payload_off": 0, + } } } @@ -265,13 +266,14 @@ async def test_default_availability_payload(hass, mqtt_mock_entry_with_yaml_conf async def test_custom_availability_payload(hass, mqtt_mock_entry_with_yaml_config): """Test availability by custom payload with defined topic.""" config = { - switch.DOMAIN: { - "platform": "mqtt", - "name": "test", - "state_topic": "state-topic", - "command_topic": "command-topic", - "payload_on": 1, - "payload_off": 0, + mqtt.DOMAIN: { + switch.DOMAIN: { + "name": "test", + "state_topic": "state-topic", + "command_topic": "command-topic", + "payload_on": 1, + "payload_off": 0, + } } } @@ -328,7 +330,7 @@ async def test_setting_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_with_yaml_config, switch.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, switch.DOMAIN, DEFAULT_CONFIG ) @@ -337,14 +339,14 @@ async def test_setting_blocked_attribute_via_mqtt_json_message( ): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_blocked_attribute_via_mqtt_json_message( - hass, mqtt_mock_entry_no_yaml_config, switch.DOMAIN, DEFAULT_CONFIG_LEGACY, {} + hass, mqtt_mock_entry_no_yaml_config, switch.DOMAIN, DEFAULT_CONFIG, {} ) async def test_setting_attribute_with_template(hass, mqtt_mock_entry_with_yaml_config): """Test the setting of attribute via MQTT with JSON payload.""" await help_test_setting_attribute_with_template( - hass, mqtt_mock_entry_with_yaml_config, switch.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, switch.DOMAIN, DEFAULT_CONFIG ) @@ -357,20 +359,20 @@ async def test_update_with_json_attrs_not_dict( mqtt_mock_entry_with_yaml_config, caplog, switch.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) -async def test_update_with_json_attrs_bad_JSON( +async def test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog ): """Test attributes get extracted from a JSON result.""" - await help_test_update_with_json_attrs_bad_JSON( + await help_test_update_with_json_attrs_bad_json( hass, mqtt_mock_entry_with_yaml_config, caplog, switch.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) @@ -381,29 +383,29 @@ async def test_discovery_update_attr(hass, mqtt_mock_entry_no_yaml_config, caplo mqtt_mock_entry_no_yaml_config, caplog, switch.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, ) async def test_unique_id(hass, mqtt_mock_entry_with_yaml_config): """Test unique id option only creates one switch per unique_id.""" config = { - switch.DOMAIN: [ - { - "platform": "mqtt", - "name": "Test 1", - "state_topic": "test-topic", - "command_topic": "command-topic", - "unique_id": "TOTALLY_UNIQUE", - }, - { - "platform": "mqtt", - "name": "Test 2", - "state_topic": "test-topic", - "command_topic": "command-topic", - "unique_id": "TOTALLY_UNIQUE", - }, - ] + mqtt.DOMAIN: { + switch.DOMAIN: [ + { + "name": "Test 1", + "state_topic": "test-topic", + "command_topic": "command-topic", + "unique_id": "TOTALLY_UNIQUE", + }, + { + "name": "Test 2", + "state_topic": "test-topic", + "command_topic": "command-topic", + "unique_id": "TOTALLY_UNIQUE", + }, + ] + } } await help_test_unique_id( hass, mqtt_mock_entry_with_yaml_config, switch.DOMAIN, config @@ -426,8 +428,8 @@ async def test_discovery_update_switch_topic_template( hass, mqtt_mock_entry_no_yaml_config, caplog ): """Test update of discovered switch.""" - config1 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[switch.DOMAIN]) - config2 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[switch.DOMAIN]) + config1 = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][switch.DOMAIN]) + config2 = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][switch.DOMAIN]) config1["name"] = "Beer" config2["name"] = "Milk" config1["state_topic"] = "switch/state1" @@ -463,8 +465,8 @@ async def test_discovery_update_switch_template( hass, mqtt_mock_entry_no_yaml_config, caplog ): """Test update of discovered switch.""" - config1 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[switch.DOMAIN]) - config2 = copy.deepcopy(DEFAULT_CONFIG_LEGACY[switch.DOMAIN]) + config1 = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][switch.DOMAIN]) + config2 = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][switch.DOMAIN]) config1["name"] = "Beer" config2["name"] = "Milk" config1["state_topic"] = "switch/state1" @@ -534,42 +536,42 @@ async def test_discovery_broken(hass, mqtt_mock_entry_no_yaml_config, caplog): async def test_entity_device_info_with_connection(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT switch device registry integration.""" await help_test_entity_device_info_with_connection( - hass, mqtt_mock_entry_no_yaml_config, switch.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, switch.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_with_identifier(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT switch device registry integration.""" await help_test_entity_device_info_with_identifier( - hass, mqtt_mock_entry_no_yaml_config, switch.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, switch.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_update(hass, mqtt_mock_entry_no_yaml_config): """Test device registry update.""" await help_test_entity_device_info_update( - hass, mqtt_mock_entry_no_yaml_config, switch.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, switch.DOMAIN, DEFAULT_CONFIG ) async def test_entity_device_info_remove(hass, mqtt_mock_entry_no_yaml_config): """Test device registry remove.""" await help_test_entity_device_info_remove( - hass, mqtt_mock_entry_no_yaml_config, switch.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, switch.DOMAIN, DEFAULT_CONFIG ) async def test_entity_id_update_subscriptions(hass, mqtt_mock_entry_with_yaml_config): """Test MQTT subscriptions are managed when entity_id is updated.""" await help_test_entity_id_update_subscriptions( - hass, mqtt_mock_entry_with_yaml_config, switch.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_with_yaml_config, switch.DOMAIN, DEFAULT_CONFIG ) async def test_entity_id_update_discovery_update(hass, mqtt_mock_entry_no_yaml_config): """Test MQTT discovery update when entity_id is updated.""" await help_test_entity_id_update_discovery_update( - hass, mqtt_mock_entry_no_yaml_config, switch.DOMAIN, DEFAULT_CONFIG_LEGACY + hass, mqtt_mock_entry_no_yaml_config, switch.DOMAIN, DEFAULT_CONFIG ) @@ -579,7 +581,7 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): hass, mqtt_mock_entry_no_yaml_config, switch.DOMAIN, - DEFAULT_CONFIG_LEGACY, + DEFAULT_CONFIG, switch.SERVICE_TURN_ON, ) @@ -615,7 +617,7 @@ async def test_publishing_with_custom_encoding( ): """Test publishing MQTT payload with different encoding.""" domain = switch.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_publishing_with_custom_encoding( hass, @@ -634,12 +636,14 @@ async def test_publishing_with_custom_encoding( async def test_reloadable(hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path): """Test reloading the MQTT platform.""" domain = switch.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_reloadable( hass, mqtt_mock_entry_with_yaml_config, caplog, tmp_path, domain, config ) +# Test deprecated YAML configuration under the platform key +# Scheduled to be removed in HA core 2022.12 async def test_reloadable_late(hass, mqtt_client_mock, caplog, tmp_path): """Test reloading the MQTT platform with late entry setup.""" domain = switch.DOMAIN @@ -668,7 +672,7 @@ async def test_encoding_subscribable_topics( mqtt_mock_entry_with_yaml_config, caplog, switch.DOMAIN, - DEFAULT_CONFIG_LEGACY[switch.DOMAIN], + DEFAULT_CONFIG[mqtt.DOMAIN][switch.DOMAIN], topic, value, attribute, @@ -679,17 +683,14 @@ async def test_encoding_subscribable_topics( async def test_setup_manual_entity_from_yaml(hass): """Test setup manual configured MQTT entity.""" platform = switch.DOMAIN - config = copy.deepcopy(DEFAULT_CONFIG_LEGACY[platform]) - config["name"] = "test" - del config["platform"] - await help_test_setup_manual_entity_from_yaml(hass, platform, config) - assert hass.states.get(f"{platform}.test") is not None + await help_test_setup_manual_entity_from_yaml(hass, DEFAULT_CONFIG) + assert hass.states.get(f"{platform}.test") async def test_unload_entry(hass, mqtt_mock_entry_with_yaml_config, tmp_path): """Test unloading the config entry.""" domain = switch.DOMAIN - config = DEFAULT_CONFIG_LEGACY[domain] + config = DEFAULT_CONFIG await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry_with_yaml_config, tmp_path, domain, config ) From 3dd0dbf38fe016e1e2a223fc6ced086a79cde4e9 Mon Sep 17 00:00:00 2001 From: Jan Bouwhuis Date: Sat, 17 Sep 2022 21:43:42 +0200 Subject: [PATCH 05/23] Make hass.data["mqtt"] an instance of a DataClass (#77972) * Use dataclass to reference hass.data globals * Add discovery_registry_hooks to dataclass * Move discovery registry hooks to dataclass * Add device triggers to dataclass * Cleanup DEVICE_TRIGGERS const * Add last_discovery to data_class * Simplify typing for class `Subscription` * Follow up on comment * Redo suggested typing change to sasisfy mypy * Restore typing * Add mypy version to CI check logging * revert changes to ci.yaml * Add docstr for protocol Co-authored-by: Marc Mueller <30130371+cdce8p@users.noreply.github.com> * Mypy update after merging #78399 * Remove mypy ignore * Correct return type Co-authored-by: Marc Mueller <30130371+cdce8p@users.noreply.github.com> --- homeassistant/components/mqtt/__init__.py | 104 ++++++++---------- homeassistant/components/mqtt/client.py | 45 +++++--- homeassistant/components/mqtt/config_flow.py | 25 +++-- homeassistant/components/mqtt/const.py | 8 -- .../components/mqtt/device_trigger.py | 35 +++--- homeassistant/components/mqtt/diagnostics.py | 2 +- homeassistant/components/mqtt/discovery.py | 15 ++- homeassistant/components/mqtt/mixins.py | 61 ++++++---- tests/common.py | 2 +- tests/components/mqtt/test_config_flow.py | 2 +- tests/components/mqtt/test_discovery.py | 2 +- tests/components/mqtt/test_init.py | 10 +- 12 files changed, 174 insertions(+), 137 deletions(-) diff --git a/homeassistant/components/mqtt/__init__.py b/homeassistant/components/mqtt/__init__.py index 842e5b6405f06..315f116ed92ef 100644 --- a/homeassistant/components/mqtt/__init__.py +++ b/homeassistant/components/mqtt/__init__.py @@ -20,13 +20,7 @@ CONF_USERNAME, SERVICE_RELOAD, ) -from homeassistant.core import ( - CALLBACK_TYPE, - HassJob, - HomeAssistant, - ServiceCall, - callback, -) +from homeassistant.core import HassJob, HomeAssistant, ServiceCall, callback from homeassistant.exceptions import TemplateError, Unauthorized from homeassistant.helpers import ( config_validation as cv, @@ -71,15 +65,7 @@ CONF_TLS_VERSION, CONF_TOPIC, CONF_WILL_MESSAGE, - CONFIG_ENTRY_IS_SETUP, DATA_MQTT, - DATA_MQTT_CONFIG, - DATA_MQTT_DISCOVERY_REGISTRY_HOOKS, - DATA_MQTT_RELOAD_DISPATCHERS, - DATA_MQTT_RELOAD_ENTRY, - DATA_MQTT_RELOAD_NEEDED, - DATA_MQTT_SUBSCRIPTIONS_TO_RESTORE, - DATA_MQTT_UPDATED_CONFIG, DEFAULT_ENCODING, DEFAULT_QOS, DEFAULT_RETAIN, @@ -89,7 +75,7 @@ PLATFORMS, RELOADABLE_PLATFORMS, ) -from .mixins import async_discover_yaml_entities +from .mixins import MqttData, async_discover_yaml_entities from .models import ( # noqa: F401 MqttCommandTemplate, MqttValueTemplate, @@ -177,6 +163,8 @@ async def _async_setup_discovery( async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: """Start the MQTT protocol service.""" + mqtt_data: MqttData = hass.data.setdefault(DATA_MQTT, MqttData()) + conf: ConfigType | None = config.get(DOMAIN) websocket_api.async_register_command(hass, websocket_subscribe) @@ -185,7 +173,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: if conf: conf = dict(conf) - hass.data[DATA_MQTT_CONFIG] = conf + mqtt_data.config = conf if (mqtt_entry_status := mqtt_config_entry_enabled(hass)) is None: # Create an import flow if the user has yaml configured entities etc. @@ -197,12 +185,12 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: context={"source": config_entries.SOURCE_INTEGRATION_DISCOVERY}, data={}, ) - hass.data[DATA_MQTT_RELOAD_NEEDED] = True + mqtt_data.reload_needed = True elif mqtt_entry_status is False: _LOGGER.info( "MQTT will be not available until the config entry is enabled", ) - hass.data[DATA_MQTT_RELOAD_NEEDED] = True + mqtt_data.reload_needed = True return True @@ -260,33 +248,34 @@ async def _async_config_entry_updated(hass: HomeAssistant, entry: ConfigEntry) - Causes for this is config entry options changing. """ - mqtt_client = hass.data[DATA_MQTT] + mqtt_data: MqttData = hass.data[DATA_MQTT] + assert (client := mqtt_data.client) is not None - if (conf := hass.data.get(DATA_MQTT_CONFIG)) is None: + if (conf := mqtt_data.config) is None: conf = CONFIG_SCHEMA_BASE(dict(entry.data)) - mqtt_client.conf = _merge_extended_config(entry, conf) - await mqtt_client.async_disconnect() - mqtt_client.init_client() - await mqtt_client.async_connect() + mqtt_data.config = _merge_extended_config(entry, conf) + await client.async_disconnect() + client.init_client() + await client.async_connect() await discovery.async_stop(hass) - if mqtt_client.conf.get(CONF_DISCOVERY): - await _async_setup_discovery(hass, mqtt_client.conf, entry) + if client.conf.get(CONF_DISCOVERY): + await _async_setup_discovery(hass, cast(ConfigType, mqtt_data.config), entry) async def async_fetch_config(hass: HomeAssistant, entry: ConfigEntry) -> dict | None: """Fetch fresh MQTT yaml config from the hass config when (re)loading the entry.""" - if DATA_MQTT_RELOAD_ENTRY in hass.data: + mqtt_data: MqttData = hass.data[DATA_MQTT] + if mqtt_data.reload_entry: hass_config = await conf_util.async_hass_config_yaml(hass) - mqtt_config = CONFIG_SCHEMA_BASE(hass_config.get(DOMAIN, {})) - hass.data[DATA_MQTT_CONFIG] = mqtt_config + mqtt_data.config = CONFIG_SCHEMA_BASE(hass_config.get(DOMAIN, {})) # Remove unknown keys from config entry data _filter_entry_config(hass, entry) # Merge basic configuration, and add missing defaults for basic options - _merge_basic_config(hass, entry, hass.data.get(DATA_MQTT_CONFIG, {})) + _merge_basic_config(hass, entry, mqtt_data.config or {}) # Bail out if broker setting is missing if CONF_BROKER not in entry.data: _LOGGER.error("MQTT broker is not configured, please configure it") @@ -294,7 +283,7 @@ async def async_fetch_config(hass: HomeAssistant, entry: ConfigEntry) -> dict | # If user doesn't have configuration.yaml config, generate default values # for options not in config entry data - if (conf := hass.data.get(DATA_MQTT_CONFIG)) is None: + if (conf := mqtt_data.config) is None: conf = CONFIG_SCHEMA_BASE(dict(entry.data)) # User has configuration.yaml config, warn about config entry overrides @@ -317,21 +306,20 @@ async def async_fetch_config(hass: HomeAssistant, entry: ConfigEntry) -> dict | async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Load a config entry.""" + mqtt_data: MqttData = hass.data.setdefault(DATA_MQTT, MqttData()) + # Merge basic configuration, and add missing defaults for basic options if (conf := await async_fetch_config(hass, entry)) is None: # Bail out return False - - hass.data[DATA_MQTT_DISCOVERY_REGISTRY_HOOKS] = {} - hass.data[DATA_MQTT] = MQTT(hass, entry, conf) + mqtt_data.client = MQTT(hass, entry, conf) # Restore saved subscriptions - if DATA_MQTT_SUBSCRIPTIONS_TO_RESTORE in hass.data: - hass.data[DATA_MQTT].subscriptions = hass.data.pop( - DATA_MQTT_SUBSCRIPTIONS_TO_RESTORE - ) + if mqtt_data.subscriptions_to_restore: + mqtt_data.client.subscriptions = mqtt_data.subscriptions_to_restore + mqtt_data.subscriptions_to_restore = [] entry.add_update_listener(_async_config_entry_updated) - await hass.data[DATA_MQTT].async_connect() + await mqtt_data.client.async_connect() async def async_publish_service(call: ServiceCall) -> None: """Handle MQTT publish service calls.""" @@ -380,7 +368,8 @@ async def async_publish_service(call: ServiceCall) -> None: ) return - await hass.data[DATA_MQTT].async_publish(msg_topic, payload, qos, retain) + assert mqtt_data.client is not None and msg_topic is not None + await mqtt_data.client.async_publish(msg_topic, payload, qos, retain) hass.services.async_register( DOMAIN, SERVICE_PUBLISH, async_publish_service, schema=MQTT_PUBLISH_SCHEMA @@ -421,7 +410,6 @@ async def finish_dump(_): ) # setup platforms and discovery - hass.data[CONFIG_ENTRY_IS_SETUP] = set() async def async_setup_reload_service() -> None: """Create the reload service for the MQTT domain.""" @@ -435,7 +423,7 @@ async def _reload_config(call: ServiceCall) -> None: # Reload the modern yaml platforms config_yaml = await async_integration_yaml_config(hass, DOMAIN) or {} - hass.data[DATA_MQTT_UPDATED_CONFIG] = config_yaml.get(DOMAIN, {}) + mqtt_data.updated_config = config_yaml.get(DOMAIN, {}) await asyncio.gather( *( [ @@ -476,13 +464,13 @@ async def async_forward_entry_setup_and_setup_discovery(config_entry): # Setup reload service after all platforms have loaded await async_setup_reload_service() # When the entry is reloaded, also reload manual set up items to enable MQTT - if DATA_MQTT_RELOAD_ENTRY in hass.data: - hass.data.pop(DATA_MQTT_RELOAD_ENTRY) + if mqtt_data.reload_entry: + mqtt_data.reload_entry = False reload_manual_setup = True # When the entry was disabled before, reload manual set up items to enable MQTT again - if DATA_MQTT_RELOAD_NEEDED in hass.data: - hass.data.pop(DATA_MQTT_RELOAD_NEEDED) + if mqtt_data.reload_needed: + mqtt_data.reload_needed = False reload_manual_setup = True if reload_manual_setup: @@ -592,7 +580,9 @@ def unsubscribe(): def is_connected(hass: HomeAssistant) -> bool: """Return if MQTT client is connected.""" - return hass.data[DATA_MQTT].connected + mqtt_data: MqttData = hass.data[DATA_MQTT] + assert mqtt_data.client is not None + return mqtt_data.client.connected async def async_remove_config_entry_device( @@ -608,6 +598,10 @@ async def async_remove_config_entry_device( async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Unload MQTT dump and publish service when the config entry is unloaded.""" + mqtt_data: MqttData = hass.data[DATA_MQTT] + assert mqtt_data.client is not None + mqtt_client = mqtt_data.client + # Unload publish and dump services. hass.services.async_remove( DOMAIN, @@ -620,7 +614,6 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: # Stop the discovery await discovery.async_stop(hass) - mqtt_client: MQTT = hass.data[DATA_MQTT] # Unload the platforms await asyncio.gather( *( @@ -630,26 +623,23 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: ) await hass.async_block_till_done() # Unsubscribe reload dispatchers - while reload_dispatchers := hass.data.setdefault(DATA_MQTT_RELOAD_DISPATCHERS, []): + while reload_dispatchers := mqtt_data.reload_dispatchers: reload_dispatchers.pop()() - hass.data[CONFIG_ENTRY_IS_SETUP] = set() # Cleanup listeners mqtt_client.cleanup() # Trigger reload manual MQTT items at entry setup if (mqtt_entry_status := mqtt_config_entry_enabled(hass)) is False: # The entry is disabled reload legacy manual items when the entry is enabled again - hass.data[DATA_MQTT_RELOAD_NEEDED] = True + mqtt_data.reload_needed = True elif mqtt_entry_status is True: # The entry is reloaded: # Trigger re-fetching the yaml config at entry setup - hass.data[DATA_MQTT_RELOAD_ENTRY] = True + mqtt_data.reload_entry = True # Reload the legacy yaml platform to make entities unavailable await async_reload_integration_platforms(hass, DOMAIN, RELOADABLE_PLATFORMS) # Cleanup entity registry hooks - registry_hooks: dict[tuple, CALLBACK_TYPE] = hass.data[ - DATA_MQTT_DISCOVERY_REGISTRY_HOOKS - ] + registry_hooks = mqtt_data.discovery_registry_hooks while registry_hooks: registry_hooks.popitem()[1]() # Wait for all ACKs and stop the loop @@ -657,6 +647,6 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: # Store remaining subscriptions to be able to restore or reload them # when the entry is set up again if mqtt_client.subscriptions: - hass.data[DATA_MQTT_SUBSCRIPTIONS_TO_RESTORE] = mqtt_client.subscriptions + mqtt_data.subscriptions_to_restore = mqtt_client.subscriptions return True diff --git a/homeassistant/components/mqtt/client.py b/homeassistant/components/mqtt/client.py index 57f51593ed49f..50674706624b3 100644 --- a/homeassistant/components/mqtt/client.py +++ b/homeassistant/components/mqtt/client.py @@ -2,7 +2,7 @@ from __future__ import annotations import asyncio -from collections.abc import Awaitable, Callable, Coroutine, Iterable +from collections.abc import Callable, Coroutine, Iterable from functools import lru_cache, partial, wraps import inspect from itertools import groupby @@ -17,6 +17,7 @@ import certifi from paho.mqtt.client import MQTTMessage +from homeassistant.config_entries import ConfigEntry from homeassistant.const import ( CONF_CLIENT_ID, CONF_PASSWORD, @@ -52,7 +53,6 @@ MQTT_DISCONNECTED, PROTOCOL_31, ) -from .discovery import LAST_DISCOVERY from .models import ( AsyncMessageCallbackType, MessageCallbackType, @@ -68,6 +68,9 @@ # because integrations should be able to optionally rely on MQTT. import paho.mqtt.client as mqtt + from .mixins import MqttData + + _LOGGER = logging.getLogger(__name__) DISCOVERY_COOLDOWN = 2 @@ -97,8 +100,12 @@ async def async_publish( encoding: str | None = DEFAULT_ENCODING, ) -> None: """Publish message to a MQTT topic.""" + # Local import to avoid circular dependencies + # pylint: disable-next=import-outside-toplevel + from .mixins import MqttData - if DATA_MQTT not in hass.data or not mqtt_config_entry_enabled(hass): + mqtt_data: MqttData = hass.data.setdefault(DATA_MQTT, MqttData()) + if mqtt_data.client is None or not mqtt_config_entry_enabled(hass): raise HomeAssistantError( f"Cannot publish to topic '{topic}', MQTT is not enabled" ) @@ -126,11 +133,13 @@ async def async_publish( ) return - await hass.data[DATA_MQTT].async_publish(topic, outgoing_payload, qos, retain) + await mqtt_data.client.async_publish( + topic, outgoing_payload, qos or 0, retain or False + ) AsyncDeprecatedMessageCallbackType = Callable[ - [str, ReceivePayloadType, int], Awaitable[None] + [str, ReceivePayloadType, int], Coroutine[Any, Any, None] ] DeprecatedMessageCallbackType = Callable[[str, ReceivePayloadType, int], None] @@ -175,13 +184,18 @@ async def async_subscribe( | DeprecatedMessageCallbackType | AsyncDeprecatedMessageCallbackType, qos: int = DEFAULT_QOS, - encoding: str | None = "utf-8", + encoding: str | None = DEFAULT_ENCODING, ): """Subscribe to an MQTT topic. Call the return value to unsubscribe. """ - if DATA_MQTT not in hass.data or not mqtt_config_entry_enabled(hass): + # Local import to avoid circular dependencies + # pylint: disable-next=import-outside-toplevel + from .mixins import MqttData + + mqtt_data: MqttData = hass.data.setdefault(DATA_MQTT, MqttData()) + if mqtt_data.client is None or not mqtt_config_entry_enabled(hass): raise HomeAssistantError( f"Cannot subscribe to topic '{topic}', MQTT is not enabled" ) @@ -206,7 +220,7 @@ async def async_subscribe( cast(DeprecatedMessageCallbackType, msg_callback) ) - async_remove = await hass.data[DATA_MQTT].async_subscribe( + async_remove = await mqtt_data.client.async_subscribe( topic, catch_log_exception( wrapped_msg_callback, @@ -309,15 +323,17 @@ class MQTT: def __init__( self, - hass, - config_entry, - conf, + hass: HomeAssistant, + config_entry: ConfigEntry, + conf: ConfigType, ) -> None: """Initialize Home Assistant MQTT client.""" # We don't import on the top because some integrations # should be able to optionally rely on MQTT. import paho.mqtt.client as mqtt # pylint: disable=import-outside-toplevel + self._mqtt_data: MqttData = hass.data[DATA_MQTT] + self.hass = hass self.config_entry = config_entry self.conf = conf @@ -634,7 +650,6 @@ def _mqtt_handle_message(self, msg: MQTTMessage) -> None: subscription.job, ) continue - self.hass.async_run_hass_job( subscription.job, ReceiveMessage( @@ -694,10 +709,10 @@ async def _wait_for_mid(self, mid: int) -> None: async def _discovery_cooldown(self): now = time.time() # Reset discovery and subscribe cooldowns - self.hass.data[LAST_DISCOVERY] = now + self._mqtt_data.last_discovery = now self._last_subscribe = now - last_discovery = self.hass.data[LAST_DISCOVERY] + last_discovery = self._mqtt_data.last_discovery last_subscribe = self._last_subscribe wait_until = max( last_discovery + DISCOVERY_COOLDOWN, last_subscribe + DISCOVERY_COOLDOWN @@ -705,7 +720,7 @@ async def _discovery_cooldown(self): while now < wait_until: await asyncio.sleep(wait_until - now) now = time.time() - last_discovery = self.hass.data[LAST_DISCOVERY] + last_discovery = self._mqtt_data.last_discovery last_subscribe = self._last_subscribe wait_until = max( last_discovery + DISCOVERY_COOLDOWN, last_subscribe + DISCOVERY_COOLDOWN diff --git a/homeassistant/components/mqtt/config_flow.py b/homeassistant/components/mqtt/config_flow.py index 538c12d258ce4..12d97b41a7404 100644 --- a/homeassistant/components/mqtt/config_flow.py +++ b/homeassistant/components/mqtt/config_flow.py @@ -18,7 +18,7 @@ CONF_PROTOCOL, CONF_USERNAME, ) -from homeassistant.core import callback +from homeassistant.core import HomeAssistant, callback from homeassistant.data_entry_flow import FlowResult from .client import MqttClientSetup @@ -30,12 +30,13 @@ CONF_BIRTH_MESSAGE, CONF_BROKER, CONF_WILL_MESSAGE, - DATA_MQTT_CONFIG, + DATA_MQTT, DEFAULT_BIRTH, DEFAULT_DISCOVERY, DEFAULT_WILL, DOMAIN, ) +from .mixins import MqttData from .util import MQTT_WILL_BIRTH_SCHEMA MQTT_TIMEOUT = 5 @@ -164,9 +165,10 @@ async def async_step_broker( self, user_input: dict[str, Any] | None = None ) -> FlowResult: """Manage the MQTT broker configuration.""" + mqtt_data: MqttData = self.hass.data.setdefault(DATA_MQTT, MqttData()) errors = {} current_config = self.config_entry.data - yaml_config = self.hass.data.get(DATA_MQTT_CONFIG, {}) + yaml_config = mqtt_data.config or {} if user_input is not None: can_connect = await self.hass.async_add_executor_job( try_connection, @@ -214,9 +216,10 @@ async def async_step_options( self, user_input: dict[str, Any] | None = None ) -> FlowResult: """Manage the MQTT options.""" + mqtt_data: MqttData = self.hass.data.setdefault(DATA_MQTT, MqttData()) errors = {} current_config = self.config_entry.data - yaml_config = self.hass.data.get(DATA_MQTT_CONFIG, {}) + yaml_config = mqtt_data.config or {} options_config: dict[str, Any] = {} if user_input is not None: bad_birth = False @@ -334,14 +337,22 @@ async def async_step_options( ) -def try_connection(hass, broker, port, username, password, protocol="3.1"): +def try_connection( + hass: HomeAssistant, + broker: str, + port: int, + username: str | None, + password: str | None, + protocol: str = "3.1", +) -> bool: """Test if we can connect to an MQTT broker.""" # We don't import on the top because some integrations # should be able to optionally rely on MQTT. import paho.mqtt.client as mqtt # pylint: disable=import-outside-toplevel # Get the config from configuration.yaml - yaml_config = hass.data.get(DATA_MQTT_CONFIG, {}) + mqtt_data: MqttData = hass.data.setdefault(DATA_MQTT, MqttData()) + yaml_config = mqtt_data.config or {} entry_config = { CONF_BROKER: broker, CONF_PORT: port, @@ -351,7 +362,7 @@ def try_connection(hass, broker, port, username, password, protocol="3.1"): } client = MqttClientSetup({**yaml_config, **entry_config}).client - result = queue.Queue(maxsize=1) + result: queue.Queue[bool] = queue.Queue(maxsize=1) def on_connect(client_, userdata, flags, result_code): """Handle connection result.""" diff --git a/homeassistant/components/mqtt/const.py b/homeassistant/components/mqtt/const.py index c8af58862e03e..93410f0c79235 100644 --- a/homeassistant/components/mqtt/const.py +++ b/homeassistant/components/mqtt/const.py @@ -30,16 +30,8 @@ CONF_TLS_INSECURE = "tls_insecure" CONF_TLS_VERSION = "tls_version" -CONFIG_ENTRY_IS_SETUP = "mqtt_config_entry_is_setup" DATA_MQTT = "mqtt" -DATA_MQTT_SUBSCRIPTIONS_TO_RESTORE = "mqtt_client_subscriptions" -DATA_MQTT_DISCOVERY_REGISTRY_HOOKS = "mqtt_discovery_registry_hooks" -DATA_MQTT_CONFIG = "mqtt_config" MQTT_DATA_DEVICE_TRACKER_LEGACY = "mqtt_device_tracker_legacy" -DATA_MQTT_RELOAD_DISPATCHERS = "mqtt_reload_dispatchers" -DATA_MQTT_RELOAD_ENTRY = "mqtt_reload_entry" -DATA_MQTT_RELOAD_NEEDED = "mqtt_reload_needed" -DATA_MQTT_UPDATED_CONFIG = "mqtt_updated_config" DEFAULT_PREFIX = "homeassistant" DEFAULT_BIRTH_WILL_TOPIC = DEFAULT_PREFIX + "/status" diff --git a/homeassistant/components/mqtt/device_trigger.py b/homeassistant/components/mqtt/device_trigger.py index 30d6fdea05f46..7e37ed72821fa 100644 --- a/homeassistant/components/mqtt/device_trigger.py +++ b/homeassistant/components/mqtt/device_trigger.py @@ -33,11 +33,13 @@ CONF_PAYLOAD, CONF_QOS, CONF_TOPIC, + DATA_MQTT, DOMAIN, ) from .discovery import MQTT_DISCOVERY_DONE from .mixins import ( MQTT_ENTITY_DEVICE_INFO_SCHEMA, + MqttData, MqttDiscoveryDeviceUpdate, send_discovery_done, update_device, @@ -81,8 +83,6 @@ extra=vol.REMOVE_EXTRA, ) -DEVICE_TRIGGERS = "mqtt_device_triggers" - LOG_NAME = "Device trigger" @@ -203,6 +203,7 @@ def __init__( self.device_id = device_id self.discovery_data = discovery_data self.hass = hass + self._mqtt_data: MqttData = hass.data[DATA_MQTT] MqttDiscoveryDeviceUpdate.__init__( self, @@ -217,8 +218,8 @@ async def async_setup(self) -> None: """Initialize the device trigger.""" discovery_hash = self.discovery_data[ATTR_DISCOVERY_HASH] discovery_id = discovery_hash[1] - if discovery_id not in self.hass.data.setdefault(DEVICE_TRIGGERS, {}): - self.hass.data[DEVICE_TRIGGERS][discovery_id] = Trigger( + if discovery_id not in self._mqtt_data.device_triggers: + self._mqtt_data.device_triggers[discovery_id] = Trigger( hass=self.hass, device_id=self.device_id, discovery_data=self.discovery_data, @@ -230,7 +231,7 @@ async def async_setup(self) -> None: value_template=self._config[CONF_VALUE_TEMPLATE], ) else: - await self.hass.data[DEVICE_TRIGGERS][discovery_id].update_trigger( + await self._mqtt_data.device_triggers[discovery_id].update_trigger( self._config ) debug_info.add_trigger_discovery_data( @@ -246,16 +247,16 @@ async def async_update(self, discovery_data: dict) -> None: ) config = TRIGGER_DISCOVERY_SCHEMA(discovery_data) update_device(self.hass, self._config_entry, config) - device_trigger: Trigger = self.hass.data[DEVICE_TRIGGERS][discovery_id] + device_trigger: Trigger = self._mqtt_data.device_triggers[discovery_id] await device_trigger.update_trigger(config) async def async_tear_down(self) -> None: """Cleanup device trigger.""" discovery_hash = self.discovery_data[ATTR_DISCOVERY_HASH] discovery_id = discovery_hash[1] - if discovery_id in self.hass.data[DEVICE_TRIGGERS]: + if discovery_id in self._mqtt_data.device_triggers: _LOGGER.info("Removing trigger: %s", discovery_hash) - trigger: Trigger = self.hass.data[DEVICE_TRIGGERS][discovery_id] + trigger: Trigger = self._mqtt_data.device_triggers[discovery_id] trigger.detach_trigger() debug_info.remove_trigger_discovery_data(self.hass, discovery_hash) @@ -280,11 +281,10 @@ async def async_setup_trigger( async def async_removed_from_device(hass: HomeAssistant, device_id: str) -> None: """Handle Mqtt removed from a device.""" + mqtt_data: MqttData = hass.data[DATA_MQTT] triggers = await async_get_triggers(hass, device_id) for trig in triggers: - device_trigger: Trigger = hass.data[DEVICE_TRIGGERS].pop( - trig[CONF_DISCOVERY_ID] - ) + device_trigger: Trigger = mqtt_data.device_triggers.pop(trig[CONF_DISCOVERY_ID]) if device_trigger: device_trigger.detach_trigger() discovery_data = cast(dict, device_trigger.discovery_data) @@ -296,12 +296,13 @@ async def async_get_triggers( hass: HomeAssistant, device_id: str ) -> list[dict[str, str]]: """List device triggers for MQTT devices.""" + mqtt_data: MqttData = hass.data[DATA_MQTT] triggers: list[dict[str, str]] = [] - if DEVICE_TRIGGERS not in hass.data: + if not mqtt_data.device_triggers: return triggers - for discovery_id, trig in hass.data[DEVICE_TRIGGERS].items(): + for discovery_id, trig in mqtt_data.device_triggers.items(): if trig.device_id != device_id or trig.topic is None: continue @@ -324,12 +325,12 @@ async def async_attach_trigger( trigger_info: TriggerInfo, ) -> CALLBACK_TYPE: """Attach a trigger.""" - hass.data.setdefault(DEVICE_TRIGGERS, {}) + mqtt_data: MqttData = hass.data[DATA_MQTT] device_id = config[CONF_DEVICE_ID] discovery_id = config[CONF_DISCOVERY_ID] - if discovery_id not in hass.data[DEVICE_TRIGGERS]: - hass.data[DEVICE_TRIGGERS][discovery_id] = Trigger( + if discovery_id not in mqtt_data.device_triggers: + mqtt_data.device_triggers[discovery_id] = Trigger( hass=hass, device_id=device_id, discovery_data=None, @@ -340,6 +341,6 @@ async def async_attach_trigger( qos=None, value_template=None, ) - return await hass.data[DEVICE_TRIGGERS][discovery_id].add_trigger( + return await mqtt_data.device_triggers[discovery_id].add_trigger( action, trigger_info ) diff --git a/homeassistant/components/mqtt/diagnostics.py b/homeassistant/components/mqtt/diagnostics.py index ea490783fc09f..2a6322cac63fe 100644 --- a/homeassistant/components/mqtt/diagnostics.py +++ b/homeassistant/components/mqtt/diagnostics.py @@ -43,7 +43,7 @@ def _async_get_diagnostics( device: DeviceEntry | None = None, ) -> dict[str, Any]: """Return diagnostics for a config entry.""" - mqtt_instance: MQTT = hass.data[DATA_MQTT] + mqtt_instance: MQTT = hass.data[DATA_MQTT].client redacted_config = async_redact_data(mqtt_instance.conf, REDACT_CONFIG) diff --git a/homeassistant/components/mqtt/discovery.py b/homeassistant/components/mqtt/discovery.py index 8a4c4d0c54200..65051ce54fcc2 100644 --- a/homeassistant/components/mqtt/discovery.py +++ b/homeassistant/components/mqtt/discovery.py @@ -7,6 +7,7 @@ import logging import re import time +from typing import TYPE_CHECKING from homeassistant.const import CONF_DEVICE, CONF_PLATFORM from homeassistant.core import HomeAssistant @@ -28,9 +29,13 @@ ATTR_DISCOVERY_TOPIC, CONF_AVAILABILITY, CONF_TOPIC, + DATA_MQTT, DOMAIN, ) +if TYPE_CHECKING: + from .mixins import MqttData + _LOGGER = logging.getLogger(__name__) TOPIC_MATCHER = re.compile( @@ -69,7 +74,6 @@ MQTT_DISCOVERY_UPDATED = "mqtt_discovery_updated_{}" MQTT_DISCOVERY_NEW = "mqtt_discovery_new_{}_{}" MQTT_DISCOVERY_DONE = "mqtt_discovery_done_{}" -LAST_DISCOVERY = "mqtt_last_discovery" TOPIC_BASE = "~" @@ -80,12 +84,12 @@ class MQTTConfig(dict): discovery_data: dict -def clear_discovery_hash(hass: HomeAssistant, discovery_hash: tuple) -> None: +def clear_discovery_hash(hass: HomeAssistant, discovery_hash: tuple[str, str]) -> None: """Clear entry in ALREADY_DISCOVERED list.""" del hass.data[ALREADY_DISCOVERED][discovery_hash] -def set_discovery_hash(hass: HomeAssistant, discovery_hash: tuple): +def set_discovery_hash(hass: HomeAssistant, discovery_hash: tuple[str, str]): """Clear entry in ALREADY_DISCOVERED list.""" hass.data[ALREADY_DISCOVERED][discovery_hash] = {} @@ -94,11 +98,12 @@ async def async_start( # noqa: C901 hass: HomeAssistant, discovery_topic, config_entry=None ) -> None: """Start MQTT Discovery.""" + mqtt_data: MqttData = hass.data[DATA_MQTT] mqtt_integrations = {} async def async_discovery_message_received(msg): """Process the received message.""" - hass.data[LAST_DISCOVERY] = time.time() + mqtt_data.last_discovery = time.time() payload = msg.payload topic = msg.topic topic_trimmed = topic.replace(f"{discovery_topic}/", "", 1) @@ -253,7 +258,7 @@ async def discovery_done(_): ) ) - hass.data[LAST_DISCOVERY] = time.time() + mqtt_data.last_discovery = time.time() mqtt_integrations = await async_get_mqtt(hass) hass.data[INTEGRATION_UNSUBSCRIBE] = {} diff --git a/homeassistant/components/mqtt/mixins.py b/homeassistant/components/mqtt/mixins.py index fddbe83830395..a16394667d8b6 100644 --- a/homeassistant/components/mqtt/mixins.py +++ b/homeassistant/components/mqtt/mixins.py @@ -4,9 +4,10 @@ from abc import abstractmethod import asyncio from collections.abc import Callable, Coroutine +from dataclasses import dataclass, field from functools import partial import logging -from typing import Any, Protocol, cast, final +from typing import TYPE_CHECKING, Any, Protocol, cast, final import voluptuous as vol @@ -60,7 +61,7 @@ from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType from . import debug_info, subscription -from .client import async_publish +from .client import MQTT, Subscription, async_publish from .const import ( ATTR_DISCOVERY_HASH, ATTR_DISCOVERY_PAYLOAD, @@ -70,11 +71,6 @@ CONF_QOS, CONF_TOPIC, DATA_MQTT, - DATA_MQTT_CONFIG, - DATA_MQTT_DISCOVERY_REGISTRY_HOOKS, - DATA_MQTT_RELOAD_DISPATCHERS, - DATA_MQTT_RELOAD_ENTRY, - DATA_MQTT_UPDATED_CONFIG, DEFAULT_ENCODING, DEFAULT_PAYLOAD_AVAILABLE, DEFAULT_PAYLOAD_NOT_AVAILABLE, @@ -98,6 +94,9 @@ ) from .util import mqtt_config_entry_enabled, valid_subscribe_topic +if TYPE_CHECKING: + from .device_trigger import Trigger + _LOGGER = logging.getLogger(__name__) AVAILABILITY_ALL = "all" @@ -274,6 +273,24 @@ def validator(config: ConfigType) -> ConfigType: return validator +@dataclass +class MqttData: + """Keep the MQTT entry data.""" + + client: MQTT | None = None + config: ConfigType | None = None + device_triggers: dict[str, Trigger] = field(default_factory=dict) + discovery_registry_hooks: dict[tuple[str, str], CALLBACK_TYPE] = field( + default_factory=dict + ) + last_discovery: float = 0.0 + reload_dispatchers: list[CALLBACK_TYPE] = field(default_factory=list) + reload_entry: bool = False + reload_needed: bool = False + subscriptions_to_restore: list[Subscription] = field(default_factory=list) + updated_config: ConfigType = field(default_factory=dict) + + class SetupEntity(Protocol): """Protocol type for async_setup_entities.""" @@ -292,11 +309,12 @@ async def async_discover_yaml_entities( hass: HomeAssistant, platform_domain: str ) -> None: """Discover entities for a platform.""" - if DATA_MQTT_UPDATED_CONFIG in hass.data: + mqtt_data: MqttData = hass.data[DATA_MQTT] + if mqtt_data.updated_config: # The platform has been reloaded - config_yaml = hass.data[DATA_MQTT_UPDATED_CONFIG] + config_yaml = mqtt_data.updated_config else: - config_yaml = hass.data.get(DATA_MQTT_CONFIG, {}) + config_yaml = mqtt_data.config or {} if not config_yaml: return if platform_domain not in config_yaml: @@ -318,8 +336,9 @@ async def async_get_platform_config_from_yaml( ) -> list[ConfigType]: """Return a list of validated configurations for the domain.""" + mqtt_data: MqttData = hass.data[DATA_MQTT] if config_yaml is None: - config_yaml = hass.data.get(DATA_MQTT_CONFIG) + config_yaml = mqtt_data.config if not config_yaml: return [] if not (platform_configs := config_yaml.get(platform_domain)): @@ -334,6 +353,7 @@ async def async_setup_entry_helper( schema: vol.Schema, ) -> None: """Set up entity, automation or tag creation dynamically through MQTT discovery.""" + mqtt_data: MqttData = hass.data[DATA_MQTT] async def async_discover(discovery_payload): """Discover and add an MQTT entity, automation or tag.""" @@ -357,7 +377,7 @@ async def async_discover(discovery_payload): ) raise - hass.data.setdefault(DATA_MQTT_RELOAD_DISPATCHERS, []).append( + mqtt_data.reload_dispatchers.append( async_dispatcher_connect( hass, MQTT_DISCOVERY_NEW.format(domain, "mqtt"), async_discover ) @@ -372,7 +392,8 @@ async def async_setup_platform_helper( async_setup_entities: SetupEntity, ) -> None: """Help to set up the platform for manual configured MQTT entities.""" - if DATA_MQTT_RELOAD_ENTRY in hass.data: + mqtt_data: MqttData = hass.data[DATA_MQTT] + if mqtt_data.reload_entry: _LOGGER.debug( "MQTT integration is %s, skipping setup of manually configured MQTT items while unloading the config entry", platform_domain, @@ -597,7 +618,10 @@ async def async_will_remove_from_hass(self): @property def available(self) -> bool: """Return if the device is available.""" - if not self.hass.data[DATA_MQTT].connected and not self.hass.is_stopping: + mqtt_data: MqttData = self.hass.data[DATA_MQTT] + assert mqtt_data.client is not None + client = mqtt_data.client + if not client.connected and not self.hass.is_stopping: return False if not self._avail_topics: return True @@ -632,7 +656,7 @@ async def cleanup_device_registry( ) -def get_discovery_hash(discovery_data: dict) -> tuple: +def get_discovery_hash(discovery_data: dict) -> tuple[str, str]: """Get the discovery hash from the discovery data.""" return discovery_data[ATTR_DISCOVERY_HASH] @@ -817,9 +841,8 @@ def __init__( self._removed_from_hass = False if discovery_data is None: return - self._registry_hooks: dict[tuple, CALLBACK_TYPE] = hass.data[ - DATA_MQTT_DISCOVERY_REGISTRY_HOOKS - ] + mqtt_data: MqttData = hass.data[DATA_MQTT] + self._registry_hooks = mqtt_data.discovery_registry_hooks discovery_hash: tuple[str, str] = discovery_data[ATTR_DISCOVERY_HASH] if discovery_hash in self._registry_hooks: self._registry_hooks.pop(discovery_hash)() @@ -897,7 +920,7 @@ async def async_removed_from_registry(self) -> None: def add_to_platform_abort(self) -> None: """Abort adding an entity to a platform.""" if self._discovery_data is not None: - discovery_hash: tuple = self._discovery_data[ATTR_DISCOVERY_HASH] + discovery_hash: tuple[str, str] = self._discovery_data[ATTR_DISCOVERY_HASH] if self.registry_entry is not None: self._registry_hooks[ discovery_hash diff --git a/tests/common.py b/tests/common.py index 89d1a1d911664..c97ee8a24f65d 100644 --- a/tests/common.py +++ b/tests/common.py @@ -369,7 +369,7 @@ def async_fire_mqtt_message(hass, topic, payload, qos=0, retain=False): if isinstance(payload, str): payload = payload.encode("utf-8") msg = ReceiveMessage(topic, payload, qos, retain) - hass.data["mqtt"]._mqtt_handle_message(msg) + hass.data["mqtt"].client._mqtt_handle_message(msg) fire_mqtt_message = threadsafe_callback_factory(async_fire_mqtt_message) diff --git a/tests/components/mqtt/test_config_flow.py b/tests/components/mqtt/test_config_flow.py index e40397fd1d4d5..dba06e5cd5b89 100644 --- a/tests/components/mqtt/test_config_flow.py +++ b/tests/components/mqtt/test_config_flow.py @@ -155,7 +155,7 @@ async def test_manual_config_set( assert await async_setup_component(hass, "mqtt", {"mqtt": {"broker": "bla"}}) await hass.async_block_till_done() # do not try to reload - del hass.data["mqtt_reload_needed"] + hass.data["mqtt"].reload_needed = False assert len(mock_finish_setup.mock_calls) == 0 mock_try_connection.return_value = True diff --git a/tests/components/mqtt/test_discovery.py b/tests/components/mqtt/test_discovery.py index c625d0a21f939..a9ac66f88513e 100644 --- a/tests/components/mqtt/test_discovery.py +++ b/tests/components/mqtt/test_discovery.py @@ -1438,7 +1438,7 @@ async def test_clean_up_registry_monitoring( ): """Test registry monitoring hook is removed after a reload.""" await mqtt_mock_entry_no_yaml_config() - hooks: dict = hass.data[mqtt.const.DATA_MQTT_DISCOVERY_REGISTRY_HOOKS] + hooks: dict = hass.data["mqtt"].discovery_registry_hooks # discover an entity that is not enabled by default config1 = { "name": "sbfspot_12345", diff --git a/tests/components/mqtt/test_init.py b/tests/components/mqtt/test_init.py index b76979cc990d4..46649bf703f17 100644 --- a/tests/components/mqtt/test_init.py +++ b/tests/components/mqtt/test_init.py @@ -1776,14 +1776,14 @@ async def test_delayed_birth_message( await hass.async_block_till_done() mqtt_component_mock = MagicMock( - return_value=hass.data["mqtt"], - spec_set=hass.data["mqtt"], - wraps=hass.data["mqtt"], + return_value=hass.data["mqtt"].client, + spec_set=hass.data["mqtt"].client, + wraps=hass.data["mqtt"].client, ) mqtt_component_mock._mqttc = mqtt_client_mock - hass.data["mqtt"] = mqtt_component_mock - mqtt_mock = hass.data["mqtt"] + hass.data["mqtt"].client = mqtt_component_mock + mqtt_mock = hass.data["mqtt"].client mqtt_mock.reset_mock() async def wait_birth(topic, payload, qos): From bfcb3332275a7c1f26426601266690aa4b9396f9 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Tue, 20 Sep 2022 17:32:10 +0200 Subject: [PATCH 06/23] Add status codes 23 and 26 to Xiaomi Miio vacuum (#78289) * Add status codes 23 and 26 * change status 26 --- homeassistant/components/xiaomi_miio/vacuum.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/homeassistant/components/xiaomi_miio/vacuum.py b/homeassistant/components/xiaomi_miio/vacuum.py index 7df38109d1677..20196f389194c 100644 --- a/homeassistant/components/xiaomi_miio/vacuum.py +++ b/homeassistant/components/xiaomi_miio/vacuum.py @@ -73,6 +73,8 @@ 17: STATE_CLEANING, # "Zoned cleaning" 18: STATE_CLEANING, # "Segment cleaning" 22: STATE_DOCKED, # "Emptying the bin" on s7+ + 23: STATE_DOCKED, # "Washing the mop" on s7maxV + 26: STATE_RETURNING, # "Going to wash the mop" on s7maxV 100: STATE_DOCKED, # "Charging complete" 101: STATE_ERROR, # "Device offline" } From dea221b155da483fc1901d054e2aec38aabf618b Mon Sep 17 00:00:00 2001 From: Jan Bouwhuis Date: Sun, 18 Sep 2022 18:55:31 +0200 Subject: [PATCH 07/23] Link manually added MQTT entities the the MQTT config entry (#78547) Co-authored-by: Erik --- homeassistant/components/mqtt/__init__.py | 17 ++++- .../components/mqtt/alarm_control_panel.py | 4 -- .../components/mqtt/binary_sensor.py | 4 -- homeassistant/components/mqtt/button.py | 4 -- homeassistant/components/mqtt/camera.py | 4 -- homeassistant/components/mqtt/climate.py | 4 -- homeassistant/components/mqtt/cover.py | 4 -- homeassistant/components/mqtt/fan.py | 4 -- homeassistant/components/mqtt/humidifier.py | 4 -- .../components/mqtt/light/__init__.py | 4 -- homeassistant/components/mqtt/lock.py | 4 -- homeassistant/components/mqtt/mixins.py | 57 ++++++++-------- homeassistant/components/mqtt/number.py | 4 -- homeassistant/components/mqtt/scene.py | 4 -- homeassistant/components/mqtt/select.py | 4 -- homeassistant/components/mqtt/sensor.py | 12 ++-- homeassistant/components/mqtt/siren.py | 4 -- homeassistant/components/mqtt/switch.py | 4 -- .../components/mqtt/vacuum/__init__.py | 9 +-- tests/components/mqtt/test_init.py | 67 +++++++++++++++++++ 20 files changed, 117 insertions(+), 105 deletions(-) diff --git a/homeassistant/components/mqtt/__init__.py b/homeassistant/components/mqtt/__init__.py index 315f116ed92ef..c14266e296f31 100644 --- a/homeassistant/components/mqtt/__init__.py +++ b/homeassistant/components/mqtt/__init__.py @@ -30,6 +30,7 @@ ) from homeassistant.helpers.device_registry import DeviceEntry from homeassistant.helpers.dispatcher import async_dispatcher_connect +from homeassistant.helpers.entity_platform import async_get_platforms from homeassistant.helpers.reload import ( async_integration_yaml_config, async_reload_integration_platforms, @@ -75,7 +76,7 @@ PLATFORMS, RELOADABLE_PLATFORMS, ) -from .mixins import MqttData, async_discover_yaml_entities +from .mixins import MqttData from .models import ( # noqa: F401 MqttCommandTemplate, MqttValueTemplate, @@ -422,13 +423,25 @@ async def _reload_config(call: ServiceCall) -> None: await async_reload_integration_platforms(hass, DOMAIN, RELOADABLE_PLATFORMS) # Reload the modern yaml platforms + mqtt_platforms = async_get_platforms(hass, DOMAIN) + tasks = [ + entity.async_remove() + for mqtt_platform in mqtt_platforms + for entity in mqtt_platform.entities.values() + if not entity._discovery_data # type: ignore[attr-defined] # pylint: disable=protected-access + if mqtt_platform.config_entry + and mqtt_platform.domain in RELOADABLE_PLATFORMS + ] + await asyncio.gather(*tasks) + config_yaml = await async_integration_yaml_config(hass, DOMAIN) or {} mqtt_data.updated_config = config_yaml.get(DOMAIN, {}) await asyncio.gather( *( [ - async_discover_yaml_entities(hass, component) + mqtt_data.reload_handlers[component]() for component in RELOADABLE_PLATFORMS + if component in mqtt_data.reload_handlers ] ) ) diff --git a/homeassistant/components/mqtt/alarm_control_panel.py b/homeassistant/components/mqtt/alarm_control_panel.py index cf7262f946809..c3502cd8e64b3 100644 --- a/homeassistant/components/mqtt/alarm_control_panel.py +++ b/homeassistant/components/mqtt/alarm_control_panel.py @@ -44,7 +44,6 @@ from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_discover_yaml_entities, async_setup_entry_helper, async_setup_platform_helper, warn_for_legacy_schema, @@ -146,9 +145,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT alarm control panel through configuration.yaml and dynamically through MQTT discovery.""" - # load and initialize platform config from configuration.yaml - await async_discover_yaml_entities(hass, alarm.DOMAIN) - # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) diff --git a/homeassistant/components/mqtt/binary_sensor.py b/homeassistant/components/mqtt/binary_sensor.py index cffb2fd8300de..32608e86f5399 100644 --- a/homeassistant/components/mqtt/binary_sensor.py +++ b/homeassistant/components/mqtt/binary_sensor.py @@ -42,7 +42,6 @@ MQTT_ENTITY_COMMON_SCHEMA, MqttAvailability, MqttEntity, - async_discover_yaml_entities, async_setup_entry_helper, async_setup_platform_helper, warn_for_legacy_schema, @@ -102,9 +101,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT binary sensor through configuration.yaml and dynamically through MQTT discovery.""" - # load and initialize platform config from configuration.yaml - await async_discover_yaml_entities(hass, binary_sensor.DOMAIN) - # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) diff --git a/homeassistant/components/mqtt/button.py b/homeassistant/components/mqtt/button.py index 0881b963b0418..a14bf87c3be39 100644 --- a/homeassistant/components/mqtt/button.py +++ b/homeassistant/components/mqtt/button.py @@ -25,7 +25,6 @@ from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_discover_yaml_entities, async_setup_entry_helper, async_setup_platform_helper, warn_for_legacy_schema, @@ -81,9 +80,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT button through configuration.yaml and dynamically through MQTT discovery.""" - # load and initialize platform config from configuration.yaml - await async_discover_yaml_entities(hass, button.DOMAIN) - # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) diff --git a/homeassistant/components/mqtt/camera.py b/homeassistant/components/mqtt/camera.py index 61c87e868885c..f6039251882da 100644 --- a/homeassistant/components/mqtt/camera.py +++ b/homeassistant/components/mqtt/camera.py @@ -23,7 +23,6 @@ from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_discover_yaml_entities, async_setup_entry_helper, async_setup_platform_helper, warn_for_legacy_schema, @@ -105,9 +104,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT camera through configuration.yaml and dynamically through MQTT discovery.""" - # load and initialize platform config from configuration.yaml - await async_discover_yaml_entities(hass, camera.DOMAIN) - # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) diff --git a/homeassistant/components/mqtt/climate.py b/homeassistant/components/mqtt/climate.py index f39d3857ec26a..7226d1f8d1fb5 100644 --- a/homeassistant/components/mqtt/climate.py +++ b/homeassistant/components/mqtt/climate.py @@ -50,7 +50,6 @@ from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_discover_yaml_entities, async_setup_entry_helper, async_setup_platform_helper, warn_for_legacy_schema, @@ -350,9 +349,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT climate device through configuration.yaml and dynamically through MQTT discovery.""" - # load and initialize platform config from configuration.yaml - await async_discover_yaml_entities(hass, climate.DOMAIN) - # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) diff --git a/homeassistant/components/mqtt/cover.py b/homeassistant/components/mqtt/cover.py index fd96fe524d971..1f5d26c3a780a 100644 --- a/homeassistant/components/mqtt/cover.py +++ b/homeassistant/components/mqtt/cover.py @@ -46,7 +46,6 @@ from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_discover_yaml_entities, async_setup_entry_helper, async_setup_platform_helper, warn_for_legacy_schema, @@ -242,9 +241,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT cover through configuration.yaml and dynamically through MQTT discovery.""" - # load and initialize platform config from configuration.yaml - await async_discover_yaml_entities(hass, cover.DOMAIN) - # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) diff --git a/homeassistant/components/mqtt/fan.py b/homeassistant/components/mqtt/fan.py index fab748d2bfc6e..584df08e7d79e 100644 --- a/homeassistant/components/mqtt/fan.py +++ b/homeassistant/components/mqtt/fan.py @@ -50,7 +50,6 @@ from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_discover_yaml_entities, async_setup_entry_helper, async_setup_platform_helper, warn_for_legacy_schema, @@ -241,9 +240,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT fan through configuration.yaml and dynamically through MQTT discovery.""" - # load and initialize platform config from configuration.yaml - await async_discover_yaml_entities(hass, fan.DOMAIN) - # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) diff --git a/homeassistant/components/mqtt/humidifier.py b/homeassistant/components/mqtt/humidifier.py index 3a1271ea2c9e7..837bbb8b9098b 100644 --- a/homeassistant/components/mqtt/humidifier.py +++ b/homeassistant/components/mqtt/humidifier.py @@ -46,7 +46,6 @@ from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_discover_yaml_entities, async_setup_entry_helper, async_setup_platform_helper, warn_for_legacy_schema, @@ -187,9 +186,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT humidifier through configuration.yaml and dynamically through MQTT discovery.""" - # load and initialize platform config from configuration.yaml - await async_discover_yaml_entities(hass, humidifier.DOMAIN) - # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) diff --git a/homeassistant/components/mqtt/light/__init__.py b/homeassistant/components/mqtt/light/__init__.py index 76c2980e63bad..b7d52919d5ef8 100644 --- a/homeassistant/components/mqtt/light/__init__.py +++ b/homeassistant/components/mqtt/light/__init__.py @@ -14,7 +14,6 @@ from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType from ..mixins import ( - async_discover_yaml_entities, async_setup_entry_helper, async_setup_platform_helper, warn_for_legacy_schema, @@ -111,9 +110,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT lights configured under the light platform key (deprecated).""" - # load and initialize platform config from configuration.yaml - await async_discover_yaml_entities(hass, light.DOMAIN) - # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) diff --git a/homeassistant/components/mqtt/lock.py b/homeassistant/components/mqtt/lock.py index 4910eafae7517..dca02f909dc2a 100644 --- a/homeassistant/components/mqtt/lock.py +++ b/homeassistant/components/mqtt/lock.py @@ -28,7 +28,6 @@ from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_discover_yaml_entities, async_setup_entry_helper, async_setup_platform_helper, warn_for_legacy_schema, @@ -102,9 +101,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT lock through configuration.yaml and dynamically through MQTT discovery.""" - # load and initialize platform config from configuration.yaml - await async_discover_yaml_entities(hass, lock.DOMAIN) - # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) diff --git a/homeassistant/components/mqtt/mixins.py b/homeassistant/components/mqtt/mixins.py index a16394667d8b6..477be399e26e5 100644 --- a/homeassistant/components/mqtt/mixins.py +++ b/homeassistant/components/mqtt/mixins.py @@ -39,7 +39,6 @@ from homeassistant.helpers import ( config_validation as cv, device_registry as dr, - discovery, entity_registry as er, ) from homeassistant.helpers.device_registry import EVENT_DEVICE_REGISTRY_UPDATED @@ -286,6 +285,9 @@ class MqttData: last_discovery: float = 0.0 reload_dispatchers: list[CALLBACK_TYPE] = field(default_factory=list) reload_entry: bool = False + reload_handlers: dict[str, Callable[[], Coroutine[Any, Any, None]]] = field( + default_factory=dict + ) reload_needed: bool = False subscriptions_to_restore: list[Subscription] = field(default_factory=list) updated_config: ConfigType = field(default_factory=dict) @@ -305,30 +307,6 @@ async def __call__( """Define setup_entities type.""" -async def async_discover_yaml_entities( - hass: HomeAssistant, platform_domain: str -) -> None: - """Discover entities for a platform.""" - mqtt_data: MqttData = hass.data[DATA_MQTT] - if mqtt_data.updated_config: - # The platform has been reloaded - config_yaml = mqtt_data.updated_config - else: - config_yaml = mqtt_data.config or {} - if not config_yaml: - return - if platform_domain not in config_yaml: - return - await asyncio.gather( - *( - discovery.async_load_platform(hass, platform_domain, DOMAIN, config, {}) - for config in await async_get_platform_config_from_yaml( - hass, platform_domain, config_yaml - ) - ) - ) - - async def async_get_platform_config_from_yaml( hass: HomeAssistant, platform_domain: str, @@ -350,7 +328,7 @@ async def async_setup_entry_helper( hass: HomeAssistant, domain: str, async_setup: partial[Coroutine[HomeAssistant, str, None]], - schema: vol.Schema, + discovery_schema: vol.Schema, ) -> None: """Set up entity, automation or tag creation dynamically through MQTT discovery.""" mqtt_data: MqttData = hass.data[DATA_MQTT] @@ -367,7 +345,7 @@ async def async_discover(discovery_payload): return discovery_data = discovery_payload.discovery_data try: - config = schema(discovery_payload) + config = discovery_schema(discovery_payload) await async_setup(config, discovery_data=discovery_data) except Exception: discovery_hash = discovery_data[ATTR_DISCOVERY_HASH] @@ -383,6 +361,31 @@ async def async_discover(discovery_payload): ) ) + async def _async_setup_entities() -> None: + """Set up MQTT items from configuration.yaml.""" + mqtt_data: MqttData = hass.data[DATA_MQTT] + if mqtt_data.updated_config: + # The platform has been reloaded + config_yaml = mqtt_data.updated_config + else: + config_yaml = mqtt_data.config or {} + if not config_yaml: + return + if domain not in config_yaml: + return + await asyncio.gather( + *[ + async_setup(config) + for config in await async_get_platform_config_from_yaml( + hass, domain, config_yaml + ) + ] + ) + + # discover manual configured MQTT items + mqtt_data.reload_handlers[domain] = _async_setup_entities + await _async_setup_entities() + async def async_setup_platform_helper( hass: HomeAssistant, diff --git a/homeassistant/components/mqtt/number.py b/homeassistant/components/mqtt/number.py index eeac406f668d1..09f9d122b988d 100644 --- a/homeassistant/components/mqtt/number.py +++ b/homeassistant/components/mqtt/number.py @@ -44,7 +44,6 @@ from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_discover_yaml_entities, async_setup_entry_helper, async_setup_platform_helper, warn_for_legacy_schema, @@ -138,9 +137,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT number through configuration.yaml and dynamically through MQTT discovery.""" - # load and initialize platform config from configuration.yaml - await async_discover_yaml_entities(hass, number.DOMAIN) - # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) diff --git a/homeassistant/components/mqtt/scene.py b/homeassistant/components/mqtt/scene.py index 62de54505eb24..861bdd14f6e37 100644 --- a/homeassistant/components/mqtt/scene.py +++ b/homeassistant/components/mqtt/scene.py @@ -22,7 +22,6 @@ CONF_OBJECT_ID, MQTT_AVAILABILITY_SCHEMA, MqttEntity, - async_discover_yaml_entities, async_setup_entry_helper, async_setup_platform_helper, warn_for_legacy_schema, @@ -78,9 +77,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT scene through configuration.yaml and dynamically through MQTT discovery.""" - # load and initialize platform config from configuration.yaml - await async_discover_yaml_entities(hass, scene.DOMAIN) - # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) diff --git a/homeassistant/components/mqtt/select.py b/homeassistant/components/mqtt/select.py index ec88b1732d4c8..a6de049569024 100644 --- a/homeassistant/components/mqtt/select.py +++ b/homeassistant/components/mqtt/select.py @@ -30,7 +30,6 @@ from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_discover_yaml_entities, async_setup_entry_helper, async_setup_platform_helper, warn_for_legacy_schema, @@ -93,9 +92,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT select through configuration.yaml and dynamically through MQTT discovery.""" - # load and initialize platform config from configuration.yaml - await async_discover_yaml_entities(hass, select.DOMAIN) - # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) diff --git a/homeassistant/components/mqtt/sensor.py b/homeassistant/components/mqtt/sensor.py index 4c04d6176f131..e95979bbacaa4 100644 --- a/homeassistant/components/mqtt/sensor.py +++ b/homeassistant/components/mqtt/sensor.py @@ -1,7 +1,7 @@ """Support for MQTT sensors.""" from __future__ import annotations -from datetime import timedelta +from datetime import datetime, timedelta import functools import logging @@ -30,7 +30,7 @@ import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.event import async_track_point_in_utc_time -from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType +from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType, StateType from homeassistant.util import dt as dt_util from . import subscription @@ -41,7 +41,6 @@ MQTT_ENTITY_COMMON_SCHEMA, MqttAvailability, MqttEntity, - async_discover_yaml_entities, async_setup_entry_helper, async_setup_platform_helper, warn_for_legacy_schema, @@ -146,9 +145,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT sensor through configuration.yaml and dynamically through MQTT discovery.""" - # load and initialize platform config from configuration.yaml - await async_discover_yaml_entities(hass, sensor.DOMAIN) - # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) @@ -346,7 +342,7 @@ def _value_is_expired(self, *_): self.async_write_ha_state() @property - def native_unit_of_measurement(self): + def native_unit_of_measurement(self) -> str | None: """Return the unit this state is expressed in.""" return self._config.get(CONF_UNIT_OF_MEASUREMENT) @@ -356,7 +352,7 @@ def force_update(self) -> bool: return self._config[CONF_FORCE_UPDATE] @property - def native_value(self): + def native_value(self) -> StateType | datetime: """Return the state of the entity.""" return self._state diff --git a/homeassistant/components/mqtt/siren.py b/homeassistant/components/mqtt/siren.py index 5ed76fd63305a..ebb0891978913 100644 --- a/homeassistant/components/mqtt/siren.py +++ b/homeassistant/components/mqtt/siren.py @@ -51,7 +51,6 @@ from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_discover_yaml_entities, async_setup_entry_helper, async_setup_platform_helper, warn_for_legacy_schema, @@ -142,9 +141,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT siren through configuration.yaml and dynamically through MQTT discovery.""" - # load and initialize platform config from configuration.yaml - await async_discover_yaml_entities(hass, siren.DOMAIN) - # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) diff --git a/homeassistant/components/mqtt/switch.py b/homeassistant/components/mqtt/switch.py index b5c7ab13dfcba..af16b14bea165 100644 --- a/homeassistant/components/mqtt/switch.py +++ b/homeassistant/components/mqtt/switch.py @@ -42,7 +42,6 @@ from .mixins import ( MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, - async_discover_yaml_entities, async_setup_entry_helper, async_setup_platform_helper, warn_for_legacy_schema, @@ -101,9 +100,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT switch through configuration.yaml and dynamically through MQTT discovery.""" - # load and initialize platform config from configuration.yaml - await async_discover_yaml_entities(hass, switch.DOMAIN) - # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) diff --git a/homeassistant/components/mqtt/vacuum/__init__.py b/homeassistant/components/mqtt/vacuum/__init__.py index cdd14e6d8e378..abab55c632c45 100644 --- a/homeassistant/components/mqtt/vacuum/__init__.py +++ b/homeassistant/components/mqtt/vacuum/__init__.py @@ -11,11 +11,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType -from ..mixins import ( - async_discover_yaml_entities, - async_setup_entry_helper, - async_setup_platform_helper, -) +from ..mixins import async_setup_entry_helper, async_setup_platform_helper from .schema import CONF_SCHEMA, LEGACY, MQTT_VACUUM_SCHEMA, STATE from .schema_legacy import ( DISCOVERY_SCHEMA_LEGACY, @@ -90,9 +86,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up MQTT vacuum through configuration.yaml and dynamically through MQTT discovery.""" - # load and initialize platform config from configuration.yaml - await async_discover_yaml_entities(hass, vacuum.DOMAIN) - # setup for discovery setup = functools.partial( _async_setup_entity, hass, async_add_entities, config_entry=config_entry ) diff --git a/tests/components/mqtt/test_init.py b/tests/components/mqtt/test_init.py index 46649bf703f17..90df45b65a1c5 100644 --- a/tests/components/mqtt/test_init.py +++ b/tests/components/mqtt/test_init.py @@ -29,11 +29,13 @@ from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers import device_registry as dr, template from homeassistant.helpers.entity import Entity +from homeassistant.helpers.entity_platform import async_get_platforms from homeassistant.setup import async_setup_component from homeassistant.util.dt import utcnow from .test_common import ( help_test_entry_reload_with_new_config, + help_test_reload_with_config, help_test_setup_manual_entity_from_yaml, ) @@ -2986,3 +2988,68 @@ async def test_remove_unknown_conf_entry_options(hass, mqtt_client_mock, caplog) "MQTT config entry: {'protocol'}. Add them to configuration.yaml if they " "are needed" ) in caplog.text + + +@patch("homeassistant.components.mqtt.PLATFORMS", [Platform.LIGHT]) +async def test_link_config_entry(hass, tmp_path, caplog): + """Test manual and dynamically setup entities are linked to the config entry.""" + config_manual = { + "mqtt": { + "light": [ + { + "name": "test_manual", + "unique_id": "test_manual_unique_id123", + "command_topic": "test-topic_manual", + } + ] + } + } + config_discovery = { + "name": "test_discovery", + "unique_id": "test_discovery_unique456", + "command_topic": "test-topic_discovery", + } + + # set up manual item + await help_test_setup_manual_entity_from_yaml(hass, config_manual) + + # set up item through discovery + async_fire_mqtt_message( + hass, "homeassistant/light/bla/config", json.dumps(config_discovery) + ) + await hass.async_block_till_done() + + assert hass.states.get("light.test_manual") is not None + assert hass.states.get("light.test_discovery") is not None + entity_names = ["test_manual", "test_discovery"] + + # Check if both entities were linked to the MQTT config entry + mqtt_config_entry = hass.config_entries.async_entries(mqtt.DOMAIN)[0] + mqtt_platforms = async_get_platforms(hass, mqtt.DOMAIN) + + def _check_entities(): + entities = [] + for mqtt_platform in mqtt_platforms: + assert mqtt_platform.config_entry is mqtt_config_entry + entities += (entity for entity in mqtt_platform.entities.values()) + + for entity in entities: + assert entity.name in entity_names + return len(entities) + + assert _check_entities() == 2 + + # reload entry and assert again + await help_test_entry_reload_with_new_config(hass, tmp_path, config_manual) + # manual set up item should remain + assert _check_entities() == 1 + # set up item through discovery + async_fire_mqtt_message( + hass, "homeassistant/light/bla/config", json.dumps(config_discovery) + ) + await hass.async_block_till_done() + assert _check_entities() == 2 + + # reload manual configured items and assert again + await help_test_reload_with_config(hass, caplog, tmp_path, config_manual) + assert _check_entities() == 2 From 91398b6a75ac4791016797418ee676c88b329cff Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Sep 2022 16:36:50 -0500 Subject: [PATCH 08/23] Drop PARALLEL_UPDATES from switchbot (#78713) --- homeassistant/components/switchbot/binary_sensor.py | 2 +- homeassistant/components/switchbot/cover.py | 2 +- homeassistant/components/switchbot/light.py | 2 +- homeassistant/components/switchbot/manifest.json | 2 +- homeassistant/components/switchbot/sensor.py | 2 +- homeassistant/components/switchbot/switch.py | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/switchbot/binary_sensor.py b/homeassistant/components/switchbot/binary_sensor.py index bf071d64a2df0..a537802826438 100644 --- a/homeassistant/components/switchbot/binary_sensor.py +++ b/homeassistant/components/switchbot/binary_sensor.py @@ -15,7 +15,7 @@ from .coordinator import SwitchbotDataUpdateCoordinator from .entity import SwitchbotEntity -PARALLEL_UPDATES = 1 +PARALLEL_UPDATES = 0 BINARY_SENSOR_TYPES: dict[str, BinarySensorEntityDescription] = { "calibration": BinarySensorEntityDescription( diff --git a/homeassistant/components/switchbot/cover.py b/homeassistant/components/switchbot/cover.py index df716be6ff39e..696c9455f28bd 100644 --- a/homeassistant/components/switchbot/cover.py +++ b/homeassistant/components/switchbot/cover.py @@ -24,7 +24,7 @@ # Initialize the logger _LOGGER = logging.getLogger(__name__) -PARALLEL_UPDATES = 1 +PARALLEL_UPDATES = 0 async def async_setup_entry( diff --git a/homeassistant/components/switchbot/light.py b/homeassistant/components/switchbot/light.py index e55f5fff9b11a..0b4f748f1b256 100644 --- a/homeassistant/components/switchbot/light.py +++ b/homeassistant/components/switchbot/light.py @@ -29,7 +29,7 @@ SwitchBotColorMode.COLOR_TEMP: ColorMode.COLOR_TEMP, } -PARALLEL_UPDATES = 1 +PARALLEL_UPDATES = 0 async def async_setup_entry( diff --git a/homeassistant/components/switchbot/manifest.json b/homeassistant/components/switchbot/manifest.json index a321c964edcf2..bb670cc72d391 100644 --- a/homeassistant/components/switchbot/manifest.json +++ b/homeassistant/components/switchbot/manifest.json @@ -2,7 +2,7 @@ "domain": "switchbot", "name": "SwitchBot", "documentation": "https://www.home-assistant.io/integrations/switchbot", - "requirements": ["PySwitchbot==0.19.9"], + "requirements": ["PySwitchbot==0.19.10"], "config_flow": true, "dependencies": ["bluetooth"], "codeowners": [ diff --git a/homeassistant/components/switchbot/sensor.py b/homeassistant/components/switchbot/sensor.py index 9658c1ed9c8fc..e435e71efbd2a 100644 --- a/homeassistant/components/switchbot/sensor.py +++ b/homeassistant/components/switchbot/sensor.py @@ -21,7 +21,7 @@ from .coordinator import SwitchbotDataUpdateCoordinator from .entity import SwitchbotEntity -PARALLEL_UPDATES = 1 +PARALLEL_UPDATES = 0 SENSOR_TYPES: dict[str, SensorEntityDescription] = { "rssi": SensorEntityDescription( diff --git a/homeassistant/components/switchbot/switch.py b/homeassistant/components/switchbot/switch.py index d524a7100f027..c4bbc2af1e01f 100644 --- a/homeassistant/components/switchbot/switch.py +++ b/homeassistant/components/switchbot/switch.py @@ -19,7 +19,7 @@ # Initialize the logger _LOGGER = logging.getLogger(__name__) -PARALLEL_UPDATES = 1 +PARALLEL_UPDATES = 0 async def async_setup_entry( diff --git a/requirements_all.txt b/requirements_all.txt index 91a8c24ad1d78..15662fa01f49e 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -37,7 +37,7 @@ PyRMVtransport==0.3.3 PySocks==1.7.1 # homeassistant.components.switchbot -PySwitchbot==0.19.9 +PySwitchbot==0.19.10 # homeassistant.components.transport_nsw PyTransportNSW==0.1.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 8c0e003985151..b9dc80104b8d3 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -33,7 +33,7 @@ PyRMVtransport==0.3.3 PySocks==1.7.1 # homeassistant.components.switchbot -PySwitchbot==0.19.9 +PySwitchbot==0.19.10 # homeassistant.components.transport_nsw PyTransportNSW==0.1.1 From 8c9e0a8239bd86a46c1bb952ca664adc174e0912 Mon Sep 17 00:00:00 2001 From: Nico Date: Mon, 19 Sep 2022 12:59:09 +0200 Subject: [PATCH 09/23] Bump aioimaplib to 1.0.1 (#78738) --- homeassistant/components/imap/manifest.json | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/imap/manifest.json b/homeassistant/components/imap/manifest.json index f4bbadfa6acc1..3600411335157 100644 --- a/homeassistant/components/imap/manifest.json +++ b/homeassistant/components/imap/manifest.json @@ -2,7 +2,7 @@ "domain": "imap", "name": "IMAP", "documentation": "https://www.home-assistant.io/integrations/imap", - "requirements": ["aioimaplib==1.0.0"], + "requirements": ["aioimaplib==1.0.1"], "codeowners": [], "iot_class": "cloud_push", "loggers": ["aioimaplib"] diff --git a/requirements_all.txt b/requirements_all.txt index 15662fa01f49e..e34c34e3ada10 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -181,7 +181,7 @@ aiohttp_cors==0.7.0 aiohue==4.5.0 # homeassistant.components.imap -aioimaplib==1.0.0 +aioimaplib==1.0.1 # homeassistant.components.apache_kafka aiokafka==0.7.2 From a688b4c5818fb2bef6130af4e17cc31e2cc94746 Mon Sep 17 00:00:00 2001 From: Aaron Bach Date: Wed, 21 Sep 2022 11:34:04 -0600 Subject: [PATCH 10/23] Fix bug wherein RainMachine services use the wrong controller (#78780) --- .../components/rainmachine/__init__.py | 73 +++++++++++++------ 1 file changed, 50 insertions(+), 23 deletions(-) diff --git a/homeassistant/components/rainmachine/__init__.py b/homeassistant/components/rainmachine/__init__.py index 756dc9b958de6..4d19dbc7bfcfe 100644 --- a/homeassistant/components/rainmachine/__init__.py +++ b/homeassistant/components/rainmachine/__init__.py @@ -2,9 +2,10 @@ from __future__ import annotations import asyncio +from collections.abc import Awaitable, Callable from dataclasses import dataclass from datetime import timedelta -from functools import partial +from functools import partial, wraps from typing import Any from regenmaschine import Client @@ -22,7 +23,7 @@ Platform, ) from homeassistant.core import HomeAssistant, ServiceCall, callback -from homeassistant.exceptions import ConfigEntryNotReady +from homeassistant.exceptions import ConfigEntryNotReady, HomeAssistantError from homeassistant.helpers import ( aiohttp_client, config_validation as cv, @@ -152,9 +153,9 @@ class RainMachineData: @callback -def async_get_controller_for_service_call( +def async_get_entry_for_service_call( hass: HomeAssistant, call: ServiceCall -) -> Controller: +) -> ConfigEntry: """Get the controller related to a service call (by device ID).""" device_id = call.data[CONF_DEVICE_ID] device_registry = dr.async_get(hass) @@ -166,8 +167,7 @@ def async_get_controller_for_service_call( if (entry := hass.config_entries.async_get_entry(entry_id)) is None: continue if entry.domain == DOMAIN: - data: RainMachineData = hass.data[DOMAIN][entry_id] - return data.controller + return entry raise ValueError(f"No controller for device ID: {device_id}") @@ -288,15 +288,42 @@ async def async_init_coordinator( entry.async_on_unload(entry.add_update_listener(async_reload_entry)) - async def async_pause_watering(call: ServiceCall) -> None: + def call_with_controller(update_programs_and_zones: bool = True) -> Callable: + """Hydrate a service call with the appropriate controller.""" + + def decorator(func: Callable) -> Callable[..., Awaitable]: + """Define the decorator.""" + + @wraps(func) + async def wrapper(call: ServiceCall) -> None: + """Wrap the service function.""" + entry = async_get_entry_for_service_call(hass, call) + data: RainMachineData = hass.data[DOMAIN][entry.entry_id] + + try: + await func(call, data.controller) + except RainMachineError as err: + raise HomeAssistantError( + f"Error while executing {func.__name__}: {err}" + ) from err + + if update_programs_and_zones: + await async_update_programs_and_zones(hass, entry) + + return wrapper + + return decorator + + @call_with_controller() + async def async_pause_watering(call: ServiceCall, controller: Controller) -> None: """Pause watering for a set number of seconds.""" - controller = async_get_controller_for_service_call(hass, call) await controller.watering.pause_all(call.data[CONF_SECONDS]) - await async_update_programs_and_zones(hass, entry) - async def async_push_weather_data(call: ServiceCall) -> None: + @call_with_controller(update_programs_and_zones=False) + async def async_push_weather_data( + call: ServiceCall, controller: Controller + ) -> None: """Push weather data to the device.""" - controller = async_get_controller_for_service_call(hass, call) await controller.parsers.post_data( { CONF_WEATHER: [ @@ -309,9 +336,11 @@ async def async_push_weather_data(call: ServiceCall) -> None: } ) - async def async_restrict_watering(call: ServiceCall) -> None: + @call_with_controller() + async def async_restrict_watering( + call: ServiceCall, controller: Controller + ) -> None: """Restrict watering for a time period.""" - controller = async_get_controller_for_service_call(hass, call) duration = call.data[CONF_DURATION] await controller.restrictions.set_universal( { @@ -319,30 +348,28 @@ async def async_restrict_watering(call: ServiceCall) -> None: "rainDelayDuration": duration.total_seconds(), }, ) - await async_update_programs_and_zones(hass, entry) - async def async_stop_all(call: ServiceCall) -> None: + @call_with_controller() + async def async_stop_all(call: ServiceCall, controller: Controller) -> None: """Stop all watering.""" - controller = async_get_controller_for_service_call(hass, call) await controller.watering.stop_all() - await async_update_programs_and_zones(hass, entry) - async def async_unpause_watering(call: ServiceCall) -> None: + @call_with_controller() + async def async_unpause_watering(call: ServiceCall, controller: Controller) -> None: """Unpause watering.""" - controller = async_get_controller_for_service_call(hass, call) await controller.watering.unpause_all() - await async_update_programs_and_zones(hass, entry) - async def async_unrestrict_watering(call: ServiceCall) -> None: + @call_with_controller() + async def async_unrestrict_watering( + call: ServiceCall, controller: Controller + ) -> None: """Unrestrict watering.""" - controller = async_get_controller_for_service_call(hass, call) await controller.restrictions.set_universal( { "rainDelayStartTime": round(as_timestamp(utcnow())), "rainDelayDuration": 0, }, ) - await async_update_programs_and_zones(hass, entry) for service_name, schema, method in ( ( From fac2a46781b288148b7273d10524c0eb68c7fc49 Mon Sep 17 00:00:00 2001 From: Aaron Bach Date: Mon, 19 Sep 2022 13:15:32 -0600 Subject: [PATCH 11/23] Guard Guardian switches from redundant on/off calls (#78791) --- homeassistant/components/guardian/switch.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/guardian/switch.py b/homeassistant/components/guardian/switch.py index 4e100ce4fe4eb..870dd72184370 100644 --- a/homeassistant/components/guardian/switch.py +++ b/homeassistant/components/guardian/switch.py @@ -92,7 +92,10 @@ def _async_update_from_latest_data(self) -> None: ) async def async_turn_off(self, **kwargs: Any) -> None: - """Turn the valve off (closed).""" + """Turn the switch off.""" + if not self._attr_is_on: + return + try: async with self._client: await self._client.valve.close() @@ -103,7 +106,10 @@ async def async_turn_off(self, **kwargs: Any) -> None: self.async_write_ha_state() async def async_turn_on(self, **kwargs: Any) -> None: - """Turn the valve on (open).""" + """Turn the switch on.""" + if self._attr_is_on: + return + try: async with self._client: await self._client.valve.open() From 48c6fbf22ea6afae9a6eed71319d5e8ff2cf5f07 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 19 Sep 2022 19:59:07 -0500 Subject: [PATCH 12/23] Bump dbus-fast to 1.5.1 (#78802) --- homeassistant/components/bluetooth/manifest.json | 2 +- homeassistant/package_constraints.txt | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/bluetooth/manifest.json b/homeassistant/components/bluetooth/manifest.json index 1b1ec016e82a4..413ceb77e3945 100644 --- a/homeassistant/components/bluetooth/manifest.json +++ b/homeassistant/components/bluetooth/manifest.json @@ -9,7 +9,7 @@ "bleak-retry-connector==1.17.1", "bluetooth-adapters==0.4.1", "bluetooth-auto-recovery==0.3.3", - "dbus-fast==1.4.0" + "dbus-fast==1.5.1" ], "codeowners": ["@bdraco"], "config_flow": true, diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index 3ee61afca2383..8a0ee6c3205ff 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -17,7 +17,7 @@ bluetooth-auto-recovery==0.3.3 certifi>=2021.5.30 ciso8601==2.2.0 cryptography==37.0.4 -dbus-fast==1.4.0 +dbus-fast==1.5.1 fnvhash==0.1.0 hass-nabucasa==0.55.0 home-assistant-bluetooth==1.3.0 diff --git a/requirements_all.txt b/requirements_all.txt index e34c34e3ada10..24ef4d6c7ebc4 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -538,7 +538,7 @@ datadog==0.15.0 datapoint==0.9.8 # homeassistant.components.bluetooth -dbus-fast==1.4.0 +dbus-fast==1.5.1 # homeassistant.components.debugpy debugpy==1.6.3 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index b9dc80104b8d3..da0d14f522faa 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -415,7 +415,7 @@ datadog==0.15.0 datapoint==0.9.8 # homeassistant.components.bluetooth -dbus-fast==1.4.0 +dbus-fast==1.5.1 # homeassistant.components.debugpy debugpy==1.6.3 From 829777a2114238fbc48d1bce6ec62bc72b5d08dd Mon Sep 17 00:00:00 2001 From: Joakim Plate Date: Tue, 20 Sep 2022 13:57:54 +0200 Subject: [PATCH 13/23] If brightness is not available, don't set a value (#78827) --- homeassistant/components/google_assistant/trait.py | 2 -- tests/components/google_assistant/test_smart_home.py | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/homeassistant/components/google_assistant/trait.py b/homeassistant/components/google_assistant/trait.py index 4f2971c01fa6b..a05e8ebe4aa84 100644 --- a/homeassistant/components/google_assistant/trait.py +++ b/homeassistant/components/google_assistant/trait.py @@ -260,8 +260,6 @@ def query_attributes(self): brightness = self.state.attributes.get(light.ATTR_BRIGHTNESS) if brightness is not None: response["brightness"] = round(100 * (brightness / 255)) - else: - response["brightness"] = 0 return response diff --git a/tests/components/google_assistant/test_smart_home.py b/tests/components/google_assistant/test_smart_home.py index 684a6db264084..a7b061f2ec830 100644 --- a/tests/components/google_assistant/test_smart_home.py +++ b/tests/components/google_assistant/test_smart_home.py @@ -381,7 +381,7 @@ async def test_query_message(hass): "payload": { "devices": { "light.non_existing": {"online": False}, - "light.demo_light": {"on": False, "online": True, "brightness": 0}, + "light.demo_light": {"on": False, "online": True}, "light.another_light": { "on": True, "online": True, @@ -725,7 +725,6 @@ async def slow_turn_on(*args, **kwargs): "states": { "on": on, "online": True, - "brightness": brightness, }, }, { From 6704efd1ef3525b28400b4417c07b2209a548b8e Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Tue, 20 Sep 2022 20:24:39 +0200 Subject: [PATCH 14/23] Pin Python patch versions [ci] (#78830) --- .github/workflows/ci.yaml | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 80c6cbac34bd5..350ba9336a27f 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -23,7 +23,8 @@ env: CACHE_VERSION: 1 PIP_CACHE_VERSION: 1 HA_SHORT_VERSION: 2022.9 - DEFAULT_PYTHON: 3.9 + DEFAULT_PYTHON: 3.9.14 + ALL_PYTHON_VERSIONS: "['3.9.14', '3.10.7']" PRE_COMMIT_CACHE: ~/.cache/pre-commit PIP_CACHE: /tmp/pip-cache SQLALCHEMY_WARN_20: 1 @@ -46,6 +47,7 @@ jobs: pre-commit_cache_key: ${{ steps.generate_pre-commit_cache_key.outputs.key }} python_cache_key: ${{ steps.generate_python_cache_key.outputs.key }} requirements: ${{ steps.core.outputs.requirements }} + python_versions: ${{ steps.info.outputs.python_versions }} test_full_suite: ${{ steps.info.outputs.test_full_suite }} test_group_count: ${{ steps.info.outputs.test_group_count }} test_groups: ${{ steps.info.outputs.test_groups }} @@ -143,6 +145,8 @@ jobs: fi # Output & sent to GitHub Actions + echo "python_versions: ${ALL_PYTHON_VERSIONS}" + echo "::set-output name=python_versions::${ALL_PYTHON_VERSIONS}" echo "test_full_suite: ${test_full_suite}" echo "::set-output name=test_full_suite::${test_full_suite}" echo "integrations_glob: ${integrations_glob}" @@ -463,7 +467,7 @@ jobs: timeout-minutes: 60 strategy: matrix: - python-version: ["3.9", "3.10"] + python-version: ${{ fromJSON(needs.info.outputs.python_versions) }} steps: - name: Check out code from GitHub uses: actions/checkout@v3.0.2 @@ -483,7 +487,7 @@ jobs: with: path: venv key: >- - ${{ runner.os }}-${{ matrix.python-version }}-${{ + ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{ needs.info.outputs.python_cache_key }} - name: Restore pip wheel cache if: steps.cache-venv.outputs.cache-hit != 'true' @@ -491,10 +495,10 @@ jobs: with: path: ${{ env.PIP_CACHE }} key: >- - ${{ runner.os }}-${{ matrix.python-version }}-${{ + ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{ steps.generate-pip-key.outputs.key }} restore-keys: | - ${{ runner.os }}-${{ matrix.python-version }}-pip-${{ env.PIP_CACHE_VERSION }}-${{ env.HA_SHORT_VERSION }}- + ${{ runner.os }}-${{ steps.python.outputs.python-version }}-pip-${{ env.PIP_CACHE_VERSION }}-${{ env.HA_SHORT_VERSION }}- - name: Install additional OS dependencies if: steps.cache-venv.outputs.cache-hit != 'true' run: | @@ -541,7 +545,7 @@ jobs: with: path: venv key: >- - ${{ runner.os }}-${{ env.DEFAULT_PYTHON }}-${{ + ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{ needs.info.outputs.python_cache_key }} - name: Fail job if Python cache restore failed if: steps.cache-venv.outputs.cache-hit != 'true' @@ -573,7 +577,7 @@ jobs: with: path: venv key: >- - ${{ runner.os }}-${{ env.DEFAULT_PYTHON }}-${{ + ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{ needs.info.outputs.python_cache_key }} - name: Fail job if Python cache restore failed if: steps.cache-venv.outputs.cache-hit != 'true' @@ -606,7 +610,7 @@ jobs: with: path: venv key: >- - ${{ runner.os }}-${{ env.DEFAULT_PYTHON }}-${{ + ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{ needs.info.outputs.python_cache_key }} - name: Fail job if Python cache restore failed if: steps.cache-venv.outputs.cache-hit != 'true' @@ -650,7 +654,7 @@ jobs: with: path: venv key: >- - ${{ runner.os }}-${{ env.DEFAULT_PYTHON }}-${{ + ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{ needs.info.outputs.python_cache_key }} - name: Fail job if Python cache restore failed if: steps.cache-venv.outputs.cache-hit != 'true' @@ -682,7 +686,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.9", "3.10"] + python-version: ${{ fromJson(needs.info.outputs.python_versions) }} name: Run pip check ${{ matrix.python-version }} steps: - name: Check out code from GitHub @@ -698,7 +702,7 @@ jobs: with: path: venv key: >- - ${{ runner.os }}-${{ matrix.python-version }}-${{ + ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{ needs.info.outputs.python_cache_key }} - name: Fail job if Python cache restore failed if: steps.cache-venv.outputs.cache-hit != 'true' @@ -729,7 +733,7 @@ jobs: fail-fast: false matrix: group: ${{ fromJson(needs.info.outputs.test_groups) }} - python-version: ["3.9", "3.10"] + python-version: ${{ fromJson(needs.info.outputs.python_versions) }} name: >- Run tests Python ${{ matrix.python-version }} (${{ matrix.group }}) steps: @@ -751,7 +755,7 @@ jobs: uses: actions/cache@v3.0.8 with: path: venv - key: ${{ runner.os }}-${{ matrix.python-version }}-${{ + key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{ needs.info.outputs.python_cache_key }} - name: Fail job if Python cache restore failed if: steps.cache-venv.outputs.cache-hit != 'true' From 8f21e7775bacd9230662360acb9e4f79f698ca70 Mon Sep 17 00:00:00 2001 From: Jc2k Date: Wed, 21 Sep 2022 16:41:01 +0100 Subject: [PATCH 15/23] Fix parsing Eve Energy characteristic data (#78880) --- homeassistant/components/homekit_controller/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/homekit_controller/manifest.json b/homeassistant/components/homekit_controller/manifest.json index d9e5bfb854b43..7ecd54e0a79fd 100644 --- a/homeassistant/components/homekit_controller/manifest.json +++ b/homeassistant/components/homekit_controller/manifest.json @@ -3,7 +3,7 @@ "name": "HomeKit Controller", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/homekit_controller", - "requirements": ["aiohomekit==1.5.9"], + "requirements": ["aiohomekit==1.5.12"], "zeroconf": ["_hap._tcp.local.", "_hap._udp.local."], "bluetooth": [{ "manufacturer_id": 76, "manufacturer_data_start": [6] }], "dependencies": ["bluetooth", "zeroconf"], diff --git a/requirements_all.txt b/requirements_all.txt index 24ef4d6c7ebc4..9b6582cb50190 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -171,7 +171,7 @@ aioguardian==2022.07.0 aioharmony==0.2.9 # homeassistant.components.homekit_controller -aiohomekit==1.5.9 +aiohomekit==1.5.12 # homeassistant.components.emulated_hue # homeassistant.components.http diff --git a/requirements_test_all.txt b/requirements_test_all.txt index da0d14f522faa..5d4b6c7d22384 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -155,7 +155,7 @@ aioguardian==2022.07.0 aioharmony==0.2.9 # homeassistant.components.homekit_controller -aiohomekit==1.5.9 +aiohomekit==1.5.12 # homeassistant.components.emulated_hue # homeassistant.components.http From 72769130f97c042d820398319d34a3e733e68f94 Mon Sep 17 00:00:00 2001 From: Michael <35783820+mib1185@users.noreply.github.com> Date: Wed, 21 Sep 2022 17:27:05 +0200 Subject: [PATCH 16/23] Check Surveillance Station permissions during setup of Synology DSM integration (#78884) --- homeassistant/components/synology_dsm/common.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/homeassistant/components/synology_dsm/common.py b/homeassistant/components/synology_dsm/common.py index 82f2c214804fd..019108c32307c 100644 --- a/homeassistant/components/synology_dsm/common.py +++ b/homeassistant/components/synology_dsm/common.py @@ -91,6 +91,16 @@ def _setup(self) -> None: self._with_surveillance_station = bool( self.dsm.apis.get(SynoSurveillanceStation.CAMERA_API_KEY) ) + if self._with_surveillance_station: + try: + self.dsm.surveillance_station.update() + except SYNOLOGY_CONNECTION_EXCEPTIONS: + self._with_surveillance_station = False + self.dsm.reset(SynoSurveillanceStation.API_KEY) + LOGGER.info( + "Surveillance Station found, but disabled due to missing user permissions" + ) + LOGGER.debug( "State of Surveillance_station during setup of '%s': %s", self._entry.unique_id, From 5c294550e8c96d636ff22f4206c23de05b13bdb2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 21 Sep 2022 11:03:50 -1000 Subject: [PATCH 17/23] Handle default RSSI values from bleak in bluetooth (#78908) --- homeassistant/components/bluetooth/manager.py | 3 +- tests/components/bluetooth/test_manager.py | 56 +++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/bluetooth/manager.py b/homeassistant/components/bluetooth/manager.py index 014da818e1279..9f6b0bbe3edc6 100644 --- a/homeassistant/components/bluetooth/manager.py +++ b/homeassistant/components/bluetooth/manager.py @@ -60,6 +60,7 @@ APPLE_START_BYTES_WANTED: Final = {APPLE_DEVICE_ID_START_BYTE, APPLE_HOMEKIT_START_BYTE} RSSI_SWITCH_THRESHOLD = 6 +NO_RSSI_VALUE = -1000 _LOGGER = logging.getLogger(__name__) @@ -83,7 +84,7 @@ def _prefer_previous_adv( STALE_ADVERTISEMENT_SECONDS, ) return False - if new.device.rssi - RSSI_SWITCH_THRESHOLD > old.device.rssi: + if new.device.rssi - RSSI_SWITCH_THRESHOLD > (old.device.rssi or NO_RSSI_VALUE): # If new advertisement is RSSI_SWITCH_THRESHOLD more, the new one is preferred if new.source != old.source: _LOGGER.debug( diff --git a/tests/components/bluetooth/test_manager.py b/tests/components/bluetooth/test_manager.py index 9ce5985318beb..28f870e3a3505 100644 --- a/tests/components/bluetooth/test_manager.py +++ b/tests/components/bluetooth/test_manager.py @@ -116,6 +116,62 @@ async def test_switching_adapters_based_on_rssi(hass, enable_bluetooth): ) +async def test_switching_adapters_based_on_zero_rssi(hass, enable_bluetooth): + """Test switching adapters based on zero rssi.""" + + address = "44:44:33:11:23:45" + + switchbot_device_no_rssi = BLEDevice(address, "wohand_poor_signal", rssi=0) + switchbot_adv_no_rssi = AdvertisementData( + local_name="wohand_no_rssi", service_uuids=[] + ) + inject_advertisement_with_source( + hass, switchbot_device_no_rssi, switchbot_adv_no_rssi, "hci0" + ) + + assert ( + bluetooth.async_ble_device_from_address(hass, address) + is switchbot_device_no_rssi + ) + + switchbot_device_good_signal = BLEDevice(address, "wohand_good_signal", rssi=-60) + switchbot_adv_good_signal = AdvertisementData( + local_name="wohand_good_signal", service_uuids=[] + ) + inject_advertisement_with_source( + hass, switchbot_device_good_signal, switchbot_adv_good_signal, "hci1" + ) + + assert ( + bluetooth.async_ble_device_from_address(hass, address) + is switchbot_device_good_signal + ) + + inject_advertisement_with_source( + hass, switchbot_device_good_signal, switchbot_adv_no_rssi, "hci0" + ) + assert ( + bluetooth.async_ble_device_from_address(hass, address) + is switchbot_device_good_signal + ) + + # We should not switch adapters unless the signal hits the threshold + switchbot_device_similar_signal = BLEDevice( + address, "wohand_similar_signal", rssi=-62 + ) + switchbot_adv_similar_signal = AdvertisementData( + local_name="wohand_similar_signal", service_uuids=[] + ) + + inject_advertisement_with_source( + hass, switchbot_device_similar_signal, switchbot_adv_similar_signal, "hci0" + ) + assert ( + bluetooth.async_ble_device_from_address(hass, address) + is switchbot_device_good_signal + ) + + async def test_switching_adapters_based_on_stale(hass, enable_bluetooth): """Test switching adapters based on the previous advertisement being stale.""" From 68fa40c0fab9f3965de756460532f8f7f4e3a42b Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Wed, 21 Sep 2022 22:31:14 -0400 Subject: [PATCH 18/23] Disable force update Netatmo (#78913) --- homeassistant/components/netatmo/data_handler.py | 4 ++-- tests/components/netatmo/test_camera.py | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/netatmo/data_handler.py b/homeassistant/components/netatmo/data_handler.py index 3a1ea73e31167..50a3bed17ff4c 100644 --- a/homeassistant/components/netatmo/data_handler.py +++ b/homeassistant/components/netatmo/data_handler.py @@ -138,8 +138,8 @@ async def async_update(self, event_time: datetime) -> None: @callback def async_force_update(self, signal_name: str) -> None: """Prioritize data retrieval for given data class entry.""" - self.publisher[signal_name].next_scan = time() - self._queue.rotate(-(self._queue.index(self.publisher[signal_name]))) + # self.publisher[signal_name].next_scan = time() + # self._queue.rotate(-(self._queue.index(self.publisher[signal_name]))) async def handle_event(self, event: dict) -> None: """Handle webhook events.""" diff --git a/tests/components/netatmo/test_camera.py b/tests/components/netatmo/test_camera.py index 0e10ce922887a..5b01668925f68 100644 --- a/tests/components/netatmo/test_camera.py +++ b/tests/components/netatmo/test_camera.py @@ -328,6 +328,7 @@ async def test_service_set_camera_light(hass, config_entry, netatmo_auth): ) +@pytest.mark.skip async def test_camera_reconnect_webhook(hass, config_entry): """Test webhook event on camera reconnect.""" fake_post_hits = 0 From 103f4905194b8c84d272354504669d376501cdf6 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Wed, 21 Sep 2022 22:33:08 -0400 Subject: [PATCH 19/23] Bumped version to 2022.9.6 --- homeassistant/const.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index c11f9a9e05482..6c3d2a32ea303 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -7,7 +7,7 @@ MAJOR_VERSION: Final = 2022 MINOR_VERSION: Final = 9 -PATCH_VERSION: Final = "5" +PATCH_VERSION: Final = "6" __short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__: Final = f"{__short_version__}.{PATCH_VERSION}" REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 9, 0) diff --git a/pyproject.toml b/pyproject.toml index 2d1213ea19904..2f4d1e5315d63 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "homeassistant" -version = "2022.9.5" +version = "2022.9.6" license = {text = "Apache-2.0"} description = "Open-source home automation platform running on Python 3." readme = "README.rst" From f3451858ef4a6921691b1cec0de33ebb6ab37ade Mon Sep 17 00:00:00 2001 From: Jan Bouwhuis Date: Sat, 17 Sep 2022 17:27:22 +0200 Subject: [PATCH 20/23] Correct return typing for `catch_log_exception` (#78399) --- homeassistant/util/logging.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/homeassistant/util/logging.py b/homeassistant/util/logging.py index 76df4bb17b648..e493a3378fd11 100644 --- a/homeassistant/util/logging.py +++ b/homeassistant/util/logging.py @@ -120,27 +120,30 @@ def log_exception(format_err: Callable[..., Any], *args: Any) -> None: def catch_log_exception( func: Callable[..., Coroutine[Any, Any, Any]], format_err: Callable[..., Any] ) -> Callable[..., Coroutine[Any, Any, None]]: - """Overload for Callables that return a Coroutine.""" + """Overload for Coroutine that returns a Coroutine.""" @overload def catch_log_exception( func: Callable[..., Any], format_err: Callable[..., Any] -) -> Callable[..., None | Coroutine[Any, Any, None]]: - """Overload for Callables that return Any.""" +) -> Callable[..., None] | Callable[..., Coroutine[Any, Any, None]]: + """Overload for a callback that returns a callback.""" def catch_log_exception( func: Callable[..., Any], format_err: Callable[..., Any] -) -> Callable[..., None | Coroutine[Any, Any, None]]: - """Decorate a callback to catch and log exceptions.""" +) -> Callable[..., None] | Callable[..., Coroutine[Any, Any, None]]: + """Decorate a function func to catch and log exceptions. + If func is a coroutine function, a coroutine function will be returned. + If func is a callback, a callback will be returned. + """ # Check for partials to properly determine if coroutine function check_func = func while isinstance(check_func, partial): check_func = check_func.func - wrapper_func: Callable[..., None | Coroutine[Any, Any, None]] + wrapper_func: Callable[..., None] | Callable[..., Coroutine[Any, Any, None]] if asyncio.iscoroutinefunction(check_func): async_func = cast(Callable[..., Coroutine[Any, Any, None]], func) From b51dc0884eed61edf524557bcc02a8dfc6611ca3 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 21 Sep 2022 08:02:54 -1000 Subject: [PATCH 21/23] Fix samsungtv to abort when ATTR_UPNP_MANUFACTURER is missing (#78895) --- .../components/samsungtv/config_flow.py | 2 +- .../components/samsungtv/test_config_flow.py | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/samsungtv/config_flow.py b/homeassistant/components/samsungtv/config_flow.py index 099f0afbae8f2..d7ad62bdf7a9e 100644 --- a/homeassistant/components/samsungtv/config_flow.py +++ b/homeassistant/components/samsungtv/config_flow.py @@ -458,7 +458,7 @@ async def async_step_ssdp(self, discovery_info: ssdp.SsdpServiceInfo) -> FlowRes ) if hostname := urlparse(discovery_info.ssdp_location or "").hostname: self._host = hostname - self._manufacturer = discovery_info.upnp[ssdp.ATTR_UPNP_MANUFACTURER] + self._manufacturer = discovery_info.upnp.get(ssdp.ATTR_UPNP_MANUFACTURER) self._abort_if_manufacturer_is_not_samsung() # Set defaults, in case they cannot be extracted from device_info diff --git a/tests/components/samsungtv/test_config_flow.py b/tests/components/samsungtv/test_config_flow.py index 0b49a064a1990..30bb1052702aa 100644 --- a/tests/components/samsungtv/test_config_flow.py +++ b/tests/components/samsungtv/test_config_flow.py @@ -100,6 +100,15 @@ ATTR_UPNP_UDN: "uuid:0d1cef00-00dc-1000-9c80-4844f7b172de", }, ) +MOCK_SSDP_DATA_NO_MANUFACTURER = ssdp.SsdpServiceInfo( + ssdp_usn="mock_usn", + ssdp_st="mock_st", + ssdp_location="https://fake_host:12345/test", + upnp={ + ATTR_UPNP_FRIENDLY_NAME: "[TV] fake_name", + ATTR_UPNP_UDN: "uuid:0d1cef00-00dc-1000-9c80-4844f7b172de", + }, +) MOCK_SSDP_DATA_NOPREFIX = ssdp.SsdpServiceInfo( ssdp_usn="mock_usn", @@ -521,6 +530,18 @@ async def test_ssdp(hass: HomeAssistant) -> None: assert result["result"].unique_id == "0d1cef00-00dc-1000-9c80-4844f7b172de" +@pytest.mark.usefixtures("remote", "rest_api_failing") +async def test_ssdp_no_manufacturer(hass: HomeAssistant) -> None: + """Test starting a flow from discovery when the manufacturer data is missing.""" + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": config_entries.SOURCE_SSDP}, + data=MOCK_SSDP_DATA_NO_MANUFACTURER, + ) + assert result["type"] == "abort" + assert result["reason"] == "not_supported" + + @pytest.mark.parametrize( "data", [MOCK_SSDP_DATA_MAIN_TV_AGENT_ST, MOCK_SSDP_DATA_RENDERING_CONTROL_ST] ) From d44ff16f9d73e7bbe9f534bff95b604c47f28b3f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 21 Sep 2022 08:03:05 -1000 Subject: [PATCH 22/23] Handle timeout fetching bond token in config flow (#78896) --- homeassistant/components/bond/config_flow.py | 6 +++- tests/components/bond/test_config_flow.py | 38 ++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/bond/config_flow.py b/homeassistant/components/bond/config_flow.py index 09386c3587d1d..da8e6781bfaa9 100644 --- a/homeassistant/components/bond/config_flow.py +++ b/homeassistant/components/bond/config_flow.py @@ -1,6 +1,7 @@ """Config flow for Bond integration.""" from __future__ import annotations +import asyncio import contextlib from http import HTTPStatus import logging @@ -83,7 +84,10 @@ async def _async_try_automatic_configure(self) -> None: instead ask them to manually enter the token. """ host = self._discovered[CONF_HOST] - if not (token := await async_get_token(self.hass, host)): + try: + if not (token := await async_get_token(self.hass, host)): + return + except asyncio.TimeoutError: return self._discovered[CONF_ACCESS_TOKEN] = token diff --git a/tests/components/bond/test_config_flow.py b/tests/components/bond/test_config_flow.py index 15aa643abafd2..a54360283e6ad 100644 --- a/tests/components/bond/test_config_flow.py +++ b/tests/components/bond/test_config_flow.py @@ -1,6 +1,7 @@ """Test the Bond config flow.""" from __future__ import annotations +import asyncio from http import HTTPStatus from typing import Any from unittest.mock import MagicMock, Mock, patch @@ -268,6 +269,43 @@ async def test_zeroconf_form_token_unavailable(hass: core.HomeAssistant): assert len(mock_setup_entry.mock_calls) == 1 +async def test_zeroconf_form_token_times_out(hass: core.HomeAssistant): + """Test we get the discovery form and we handle the token request timeout.""" + + with patch_bond_version(), patch_bond_token(side_effect=asyncio.TimeoutError): + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": config_entries.SOURCE_ZEROCONF}, + data=zeroconf.ZeroconfServiceInfo( + host="test-host", + addresses=["test-host"], + hostname="mock_hostname", + name="ZXXX12345.some-other-tail-info", + port=None, + properties={}, + type="mock_type", + ), + ) + await hass.async_block_till_done() + assert result["type"] == "form" + assert result["errors"] == {} + + with patch_bond_version(), patch_bond_bridge(), patch_bond_device_ids(), _patch_async_setup_entry() as mock_setup_entry: + result2 = await hass.config_entries.flow.async_configure( + result["flow_id"], + {CONF_ACCESS_TOKEN: "test-token"}, + ) + await hass.async_block_till_done() + + assert result2["type"] == "create_entry" + assert result2["title"] == "bond-name" + assert result2["data"] == { + CONF_HOST: "test-host", + CONF_ACCESS_TOKEN: "test-token", + } + assert len(mock_setup_entry.mock_calls) == 1 + + async def test_zeroconf_form_with_token_available(hass: core.HomeAssistant): """Test we get the discovery form when we can get the token.""" From 7be5fde8d635d6cb6372fc771b2c2e3f15d001b9 Mon Sep 17 00:00:00 2001 From: rikroe <42204099+rikroe@users.noreply.github.com> Date: Thu, 22 Sep 2022 08:53:29 +0200 Subject: [PATCH 23/23] Bump bimmer_connected to 0.10.4 (#78910) Co-authored-by: rikroe --- homeassistant/components/bmw_connected_drive/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/bmw_connected_drive/manifest.json b/homeassistant/components/bmw_connected_drive/manifest.json index f540176a837fa..98b6861fd49f4 100644 --- a/homeassistant/components/bmw_connected_drive/manifest.json +++ b/homeassistant/components/bmw_connected_drive/manifest.json @@ -2,7 +2,7 @@ "domain": "bmw_connected_drive", "name": "BMW Connected Drive", "documentation": "https://www.home-assistant.io/integrations/bmw_connected_drive", - "requirements": ["bimmer_connected==0.10.2"], + "requirements": ["bimmer_connected==0.10.4"], "codeowners": ["@gerard33", "@rikroe"], "config_flow": true, "iot_class": "cloud_polling", diff --git a/requirements_all.txt b/requirements_all.txt index 9b6582cb50190..608c558b7efb0 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -402,7 +402,7 @@ beautifulsoup4==4.11.1 bellows==0.33.1 # homeassistant.components.bmw_connected_drive -bimmer_connected==0.10.2 +bimmer_connected==0.10.4 # homeassistant.components.bizkaibus bizkaibus==0.1.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 5d4b6c7d22384..ffca40fe7dadc 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -326,7 +326,7 @@ beautifulsoup4==4.11.1 bellows==0.33.1 # homeassistant.components.bmw_connected_drive -bimmer_connected==0.10.2 +bimmer_connected==0.10.4 # homeassistant.components.bluetooth bleak-retry-connector==1.17.1