Prepare MQTT platform tests part4 (#90107)

* Tests humidifier

* Tests legacy_vacuum
This commit is contained in:
Jan Bouwhuis 2023-03-23 19:14:44 +01:00 committed by GitHub
parent 44add1dc11
commit 2c1b59be0e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 398 additions and 414 deletions

View File

@ -14,7 +14,6 @@ from homeassistant.components.humidifier import (
SERVICE_SET_HUMIDITY, SERVICE_SET_HUMIDITY,
SERVICE_SET_MODE, SERVICE_SET_MODE,
) )
from homeassistant.components.mqtt import CONFIG_SCHEMA
from homeassistant.components.mqtt.humidifier import ( from homeassistant.components.mqtt.humidifier import (
CONF_MODE_COMMAND_TOPIC, CONF_MODE_COMMAND_TOPIC,
CONF_MODE_STATE_TOPIC, CONF_MODE_STATE_TOPIC,
@ -34,7 +33,6 @@ from homeassistant.const import (
Platform, Platform,
) )
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
from .test_common import ( from .test_common import (
help_test_availability_when_connection_lost, help_test_availability_when_connection_lost,
@ -130,30 +128,26 @@ async def async_set_humidity(
await hass.services.async_call(DOMAIN, SERVICE_SET_HUMIDITY, data, blocking=True) await hass.services.async_call(DOMAIN, SERVICE_SET_HUMIDITY, data, blocking=True)
@pytest.mark.parametrize(
"hass_config", [{mqtt.DOMAIN: {humidifier.DOMAIN: {"name": "test"}}}]
)
async def test_fail_setup_if_no_command_topic( async def test_fail_setup_if_no_command_topic(
hass: HomeAssistant, caplog: pytest.LogCaptureFixture hass: HomeAssistant,
mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
caplog: pytest.LogCaptureFixture,
) -> None: ) -> None:
"""Test if command fails with command topic.""" """Test if command fails with command topic."""
assert not await async_setup_component( with pytest.raises(AssertionError):
hass, await mqtt_mock_entry_no_yaml_config()
mqtt.DOMAIN,
{mqtt.DOMAIN: {humidifier.DOMAIN: {"name": "test"}}},
)
assert ( assert (
"Invalid config for [mqtt]: required key not provided @ data['mqtt']['humidifier'][0]['command_topic']. Got None" "Invalid config for [mqtt]: required key not provided @ data['mqtt']['humidifier'][0]['command_topic']. Got None"
in caplog.text in caplog.text
) )
async def test_controlling_state_via_topic( @pytest.mark.parametrize(
hass: HomeAssistant, "hass_config",
mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator, [
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test the controlling state via topic."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
{ {
mqtt.DOMAIN: { mqtt.DOMAIN: {
humidifier.DOMAIN: { humidifier.DOMAIN: {
@ -178,10 +172,16 @@ async def test_controlling_state_via_topic(
"payload_reset_mode": "rEset_mode", "payload_reset_mode": "rEset_mode",
} }
} }
}, }
) ],
await hass.async_block_till_done() )
await mqtt_mock_entry_with_yaml_config() async def test_controlling_state_via_topic(
hass: HomeAssistant,
mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test the controlling state via topic."""
await mqtt_mock_entry_no_yaml_config()
state = hass.states.get("humidifier.test") state = hass.states.get("humidifier.test")
assert state.state == STATE_UNKNOWN assert state.state == STATE_UNKNOWN
@ -252,15 +252,9 @@ async def test_controlling_state_via_topic(
assert state.state == STATE_UNKNOWN assert state.state == STATE_UNKNOWN
async def test_controlling_state_via_topic_and_json_message( @pytest.mark.parametrize(
hass: HomeAssistant, "hass_config",
mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator, [
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test the controlling state via topic and JSON message."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
{ {
mqtt.DOMAIN: { mqtt.DOMAIN: {
humidifier.DOMAIN: { humidifier.DOMAIN: {
@ -281,10 +275,17 @@ async def test_controlling_state_via_topic_and_json_message(
"mode_state_template": "{{ value_json.val }}", "mode_state_template": "{{ value_json.val }}",
} }
} }
}, }
) ],
)
async def test_controlling_state_via_topic_and_json_message(
hass: HomeAssistant,
mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test the controlling state via topic and JSON message."""
await hass.async_block_till_done() await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config() await mqtt_mock_entry_no_yaml_config()
state = hass.states.get("humidifier.test") state = hass.states.get("humidifier.test")
assert state.state == STATE_UNKNOWN assert state.state == STATE_UNKNOWN
@ -343,15 +344,9 @@ async def test_controlling_state_via_topic_and_json_message(
assert state.state == STATE_UNKNOWN assert state.state == STATE_UNKNOWN
async def test_controlling_state_via_topic_and_json_message_shared_topic( @pytest.mark.parametrize(
hass: HomeAssistant, "hass_config",
mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator, [
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test the controlling state via topic and JSON message using a shared topic."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
{ {
mqtt.DOMAIN: { mqtt.DOMAIN: {
humidifier.DOMAIN: { humidifier.DOMAIN: {
@ -372,10 +367,16 @@ async def test_controlling_state_via_topic_and_json_message_shared_topic(
"mode_state_template": "{{ value_json.mode }}", "mode_state_template": "{{ value_json.mode }}",
} }
} }
}, }
) ],
await hass.async_block_till_done() )
await mqtt_mock_entry_with_yaml_config() async def test_controlling_state_via_topic_and_json_message_shared_topic(
hass: HomeAssistant,
mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test the controlling state via topic and JSON message using a shared topic."""
await mqtt_mock_entry_no_yaml_config()
state = hass.states.get("humidifier.test") state = hass.states.get("humidifier.test")
assert state.state == STATE_UNKNOWN assert state.state == STATE_UNKNOWN
@ -422,15 +423,9 @@ async def test_controlling_state_via_topic_and_json_message_shared_topic(
caplog.clear() caplog.clear()
async def test_sending_mqtt_commands_and_optimistic( @pytest.mark.parametrize(
hass: HomeAssistant, "hass_config",
mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator, [
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test optimistic mode without state topic."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
{ {
mqtt.DOMAIN: { mqtt.DOMAIN: {
humidifier.DOMAIN: { humidifier.DOMAIN: {
@ -447,10 +442,16 @@ async def test_sending_mqtt_commands_and_optimistic(
], ],
} }
} }
}, }
) ],
await hass.async_block_till_done() )
mqtt_mock = await mqtt_mock_entry_with_yaml_config() async def test_sending_mqtt_commands_and_optimistic(
hass: HomeAssistant,
mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test optimistic mode without state topic."""
mqtt_mock = await mqtt_mock_entry_no_yaml_config()
state = hass.states.get("humidifier.test") state = hass.states.get("humidifier.test")
assert state.state == STATE_UNKNOWN assert state.state == STATE_UNKNOWN
@ -521,15 +522,9 @@ async def test_sending_mqtt_commands_and_optimistic(
assert state.attributes.get(ATTR_ASSUMED_STATE) assert state.attributes.get(ATTR_ASSUMED_STATE)
async def test_sending_mqtt_command_templates_( @pytest.mark.parametrize(
hass: HomeAssistant, "hass_config",
mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator, [
caplog: pytest.LogCaptureFixture,
) -> None:
"""Testing command templates with optimistic mode without state topic."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
{ {
mqtt.DOMAIN: { mqtt.DOMAIN: {
humidifier.DOMAIN: { humidifier.DOMAIN: {
@ -547,10 +542,16 @@ async def test_sending_mqtt_command_templates_(
], ],
} }
} }
}, }
) ],
await hass.async_block_till_done() )
mqtt_mock = await mqtt_mock_entry_with_yaml_config() async def test_sending_mqtt_command_templates_(
hass: HomeAssistant,
mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Testing command templates with optimistic mode without state topic."""
mqtt_mock = await mqtt_mock_entry_no_yaml_config()
state = hass.states.get("humidifier.test") state = hass.states.get("humidifier.test")
assert state.state == STATE_UNKNOWN assert state.state == STATE_UNKNOWN
@ -621,15 +622,9 @@ async def test_sending_mqtt_command_templates_(
assert state.attributes.get(ATTR_ASSUMED_STATE) assert state.attributes.get(ATTR_ASSUMED_STATE)
async def test_sending_mqtt_commands_and_explicit_optimistic( @pytest.mark.parametrize(
hass: HomeAssistant, "hass_config",
mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator, [
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test optimistic mode with state topic and turn on attributes."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
{ {
mqtt.DOMAIN: { mqtt.DOMAIN: {
humidifier.DOMAIN: { humidifier.DOMAIN: {
@ -648,10 +643,16 @@ async def test_sending_mqtt_commands_and_explicit_optimistic(
"optimistic": True, "optimistic": True,
} }
} }
}, }
) ],
await hass.async_block_till_done() )
mqtt_mock = await mqtt_mock_entry_with_yaml_config() async def test_sending_mqtt_commands_and_explicit_optimistic(
hass: HomeAssistant,
mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test optimistic mode with state topic and turn on attributes."""
mqtt_mock = await mqtt_mock_entry_no_yaml_config()
state = hass.states.get("humidifier.test") state = hass.states.get("humidifier.test")
assert state.state == STATE_UNKNOWN assert state.state == STATE_UNKNOWN
@ -774,15 +775,9 @@ async def test_encoding_subscribable_topics(
) )
async def test_attributes( @pytest.mark.parametrize(
hass: HomeAssistant, "hass_config",
mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator, [
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test attributes."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
{ {
mqtt.DOMAIN: { mqtt.DOMAIN: {
humidifier.DOMAIN: { humidifier.DOMAIN: {
@ -796,10 +791,16 @@ async def test_attributes(
], ],
} }
} }
}, }
) ],
await hass.async_block_till_done() )
await mqtt_mock_entry_with_yaml_config() async def test_attributes(
hass: HomeAssistant,
mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test attributes."""
await mqtt_mock_entry_no_yaml_config()
state = hass.states.get("humidifier.test") state = hass.states.get("humidifier.test")
assert state.state == STATE_UNKNOWN assert state.state == STATE_UNKNOWN
@ -826,105 +827,142 @@ async def test_attributes(
@pytest.mark.parametrize( @pytest.mark.parametrize(
("config", "valid"), ("hass_config", "valid"),
[ [
( (
{ {
"name": "test_valid_1", mqtt.DOMAIN: {
"command_topic": "command-topic", humidifier.DOMAIN: {
"target_humidity_command_topic": "humidity-command-topic", "name": "test_valid_1",
"command_topic": "command-topic",
"target_humidity_command_topic": "humidity-command-topic",
}
}
}, },
True, True,
), ),
( (
{ {
"name": "test_valid_2", mqtt.DOMAIN: {
"command_topic": "command-topic", humidifier.DOMAIN: {
"target_humidity_command_topic": "humidity-command-topic", "name": "test_valid_2",
"device_class": "humidifier", "command_topic": "command-topic",
"target_humidity_command_topic": "humidity-command-topic",
"device_class": "humidifier",
}
}
}, },
True, True,
), ),
( (
{ {
"name": "test_valid_3", mqtt.DOMAIN: {
"command_topic": "command-topic", humidifier.DOMAIN: {
"target_humidity_command_topic": "humidity-command-topic", "name": "test_valid_3",
"device_class": "dehumidifier", "command_topic": "command-topic",
"target_humidity_command_topic": "humidity-command-topic",
"device_class": "dehumidifier",
}
}
}, },
True, True,
), ),
( (
{ {
"name": "test_invalid_device_class", mqtt.DOMAIN: {
"command_topic": "command-topic", humidifier.DOMAIN: {
"target_humidity_command_topic": "humidity-command-topic", "name": "test_invalid_device_class",
"device_class": "notsupporedSpeci@l", "command_topic": "command-topic",
"target_humidity_command_topic": "humidity-command-topic",
"device_class": "notsupporedSpeci@l",
}
}
}, },
False, False,
), ),
( (
{ {
"name": "test_mode_command_without_modes", mqtt.DOMAIN: {
"command_topic": "command-topic", humidifier.DOMAIN: {
"target_humidity_command_topic": "humidity-command-topic", "name": "test_mode_command_without_modes",
"mode_command_topic": "mode-command-topic", "command_topic": "command-topic",
"target_humidity_command_topic": "humidity-command-topic",
"mode_command_topic": "mode-command-topic",
}
}
}, },
False, False,
), ),
( (
{ {
"name": "test_invalid_humidity_min_max_1", mqtt.DOMAIN: {
"command_topic": "command-topic", humidifier.DOMAIN: {
"target_humidity_command_topic": "humidity-command-topic", "name": "test_invalid_humidity_min_max_1",
"min_humidity": 0, "command_topic": "command-topic",
"max_humidity": 101, "target_humidity_command_topic": "humidity-command-topic",
"min_humidity": 0,
"max_humidity": 101,
}
}
}, },
False, False,
), ),
( (
{ {
"name": "test_invalid_humidity_min_max_2", mqtt.DOMAIN: {
"command_topic": "command-topic", humidifier.DOMAIN: {
"target_humidity_command_topic": "humidity-command-topic", "name": "test_invalid_humidity_min_max_2",
"max_humidity": 20, "command_topic": "command-topic",
"min_humidity": 40, "target_humidity_command_topic": "humidity-command-topic",
"max_humidity": 20,
"min_humidity": 40,
}
}
}, },
False, False,
), ),
( (
{ {
"name": "test_invalid_mode_is_reset", mqtt.DOMAIN: {
"command_topic": "command-topic", humidifier.DOMAIN: {
"target_humidity_command_topic": "humidity-command-topic", "name": "test_invalid_mode_is_reset",
"mode_command_topic": "mode-command-topic", "command_topic": "command-topic",
"modes": ["eco", "None"], "target_humidity_command_topic": "humidity-command-topic",
"mode_command_topic": "mode-command-topic",
"modes": ["eco", "None"],
}
}
}, },
False, False,
), ),
], ],
) )
async def test_validity_configurations(hass: HomeAssistant, config, valid) -> None: async def test_validity_configurations(
hass: HomeAssistant,
mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
valid: bool,
) -> None:
"""Test validity of configurations.""" """Test validity of configurations."""
assert ( if valid:
await async_setup_component( await mqtt_mock_entry_no_yaml_config()
hass, return
mqtt.DOMAIN, with pytest.raises(AssertionError):
{mqtt.DOMAIN: {humidifier.DOMAIN: config}}, await mqtt_mock_entry_no_yaml_config()
)
is valid
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
("name", "config", "success", "features"), ("name", "hass_config", "success", "features"),
[ [
( (
"test1", "test1",
{ {
"name": "test1", mqtt.DOMAIN: {
"command_topic": "command-topic", humidifier.DOMAIN: {
"target_humidity_command_topic": "humidity-command-topic", "name": "test1",
"command_topic": "command-topic",
"target_humidity_command_topic": "humidity-command-topic",
}
}
}, },
True, True,
0, 0,
@ -932,21 +970,29 @@ async def test_validity_configurations(hass: HomeAssistant, config, valid) -> No
( (
"test2", "test2",
{ {
"name": "test2", mqtt.DOMAIN: {
"command_topic": "command-topic", humidifier.DOMAIN: {
"target_humidity_command_topic": "humidity-command-topic", "name": "test2",
"mode_command_topic": "mode-command-topic", "command_topic": "command-topic",
"modes": ["eco", "auto"], "target_humidity_command_topic": "humidity-command-topic",
"mode_command_topic": "mode-command-topic",
"modes": ["eco", "auto"],
}
}
}, },
True, True,
humidifier.SUPPORT_MODES, humidifier.HumidifierEntityFeature.MODES,
), ),
( (
"test3", "test3",
{ {
"name": "test3", mqtt.DOMAIN: {
"command_topic": "command-topic", humidifier.DOMAIN: {
"target_humidity_command_topic": "humidity-command-topic", "name": "test3",
"command_topic": "command-topic",
"target_humidity_command_topic": "humidity-command-topic",
}
}
}, },
True, True,
0, 0,
@ -954,20 +1000,28 @@ async def test_validity_configurations(hass: HomeAssistant, config, valid) -> No
( (
"test4", "test4",
{ {
"name": "test4", mqtt.DOMAIN: {
"command_topic": "command-topic", humidifier.DOMAIN: {
"target_humidity_command_topic": "humidity-command-topic", "name": "test4",
"mode_command_topic": "mode-command-topic", "command_topic": "command-topic",
"modes": ["eco", "auto"], "target_humidity_command_topic": "humidity-command-topic",
"mode_command_topic": "mode-command-topic",
"modes": ["eco", "auto"],
}
}
}, },
True, True,
humidifier.SUPPORT_MODES, humidifier.HumidifierEntityFeature.MODES,
), ),
( (
"test5", "test5",
{ {
"name": "test5", mqtt.DOMAIN: {
"command_topic": "command-topic", humidifier.DOMAIN: {
"name": "test5",
"command_topic": "command-topic",
}
}
}, },
False, False,
None, None,
@ -975,8 +1029,12 @@ async def test_validity_configurations(hass: HomeAssistant, config, valid) -> No
( (
"test6", "test6",
{ {
"name": "test6", mqtt.DOMAIN: {
"target_humidity_command_topic": "humidity-command-topic", humidifier.DOMAIN: {
"name": "test6",
"target_humidity_command_topic": "humidity-command-topic",
}
}
}, },
False, False,
None, None,
@ -985,27 +1043,20 @@ async def test_validity_configurations(hass: HomeAssistant, config, valid) -> No
) )
async def test_supported_features( async def test_supported_features(
hass: HomeAssistant, hass: HomeAssistant,
mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
name, name: str,
config, success: bool,
success, features: humidifier.HumidifierEntityFeature | None,
features,
) -> None: ) -> None:
"""Test supported features.""" """Test supported features."""
assert (
await async_setup_component(
hass,
mqtt.DOMAIN,
{mqtt.DOMAIN: {humidifier.DOMAIN: config}},
)
is success
)
if success: if success:
await hass.async_block_till_done() await mqtt_mock_entry_no_yaml_config()
await mqtt_mock_entry_with_yaml_config()
state = hass.states.get(f"humidifier.{name}") state = hass.states.get(f"humidifier.{name}")
assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == features assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == features
return
with pytest.raises(AssertionError):
await mqtt_mock_entry_no_yaml_config()
@pytest.mark.parametrize("hass_config", [DEFAULT_CONFIG]) @pytest.mark.parametrize("hass_config", [DEFAULT_CONFIG])
@ -1388,17 +1439,6 @@ async def test_setup_manual_entity_from_yaml(
assert hass.states.get(f"{platform}.test") assert hass.states.get(f"{platform}.test")
async def test_config_schema_validation(hass: HomeAssistant) -> None:
"""Test invalid platform options in the config schema do not pass the config validation."""
platform = humidifier.DOMAIN
config = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][platform])
config["name"] = "test"
CONFIG_SCHEMA({mqtt.DOMAIN: {platform: config}})
CONFIG_SCHEMA({mqtt.DOMAIN: {platform: [config]}})
with pytest.raises(MultipleInvalid):
CONFIG_SCHEMA({mqtt.DOMAIN: {platform: [{"bla": "bla"}]}})
async def test_unload_config_entry( async def test_unload_config_entry(
hass: HomeAssistant, hass: HomeAssistant,
mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,

View File

@ -32,9 +32,10 @@ from homeassistant.components.vacuum import (
) )
from homeassistant.const import CONF_NAME, STATE_OFF, STATE_ON, Platform from homeassistant.const import CONF_NAME, STATE_OFF, STATE_ON, Platform
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component from homeassistant.helpers.typing import ConfigType
from .test_common import ( from .test_common import (
help_custom_config,
help_test_availability_when_connection_lost, help_test_availability_when_connection_lost,
help_test_availability_without_topic, help_test_availability_without_topic,
help_test_custom_availability_payload, help_test_custom_availability_payload,
@ -92,6 +93,28 @@ DEFAULT_CONFIG = {
DEFAULT_CONFIG_2 = {mqtt.DOMAIN: {vacuum.DOMAIN: {"name": "test"}}} DEFAULT_CONFIG_2 = {mqtt.DOMAIN: {vacuum.DOMAIN: {"name": "test"}}}
DEFAULT_CONFIG_ALL_SERVICES = help_custom_config(
vacuum.DOMAIN,
DEFAULT_CONFIG,
(
{
mqttvacuum.CONF_SUPPORTED_FEATURES: services_to_strings(
ALL_SERVICES, SERVICE_TO_STRING
)
},
),
)
def filter_options(default_config: ConfigType, options: set[str]) -> ConfigType:
"""Generate a config from a default config with omitted options."""
options_base: ConfigType = default_config[mqtt.DOMAIN][vacuum.DOMAIN]
config = deepcopy(default_config)
config[mqtt.DOMAIN][vacuum.DOMAIN] = {
key: value for key, value in options_base.items() if key not in options
}
return config
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def vacuum_platform_only(): def vacuum_platform_only():
@ -100,13 +123,12 @@ def vacuum_platform_only():
yield yield
@pytest.mark.parametrize("hass_config", [DEFAULT_CONFIG])
async def test_default_supported_features( async def test_default_supported_features(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None: ) -> None:
"""Test that the correct supported features.""" """Test that the correct supported features."""
assert await async_setup_component(hass, mqtt.DOMAIN, DEFAULT_CONFIG) await mqtt_mock_entry_no_yaml_config()
await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config()
entity = hass.states.get("vacuum.mqtttest") entity = hass.states.get("vacuum.mqtttest")
entity_features = entity.attributes.get(mqttvacuum.CONF_SUPPORTED_FEATURES, 0) entity_features = entity.attributes.get(mqttvacuum.CONF_SUPPORTED_FEATURES, 0)
assert sorted(services_to_strings(entity_features, SERVICE_TO_STRING)) == sorted( assert sorted(services_to_strings(entity_features, SERVICE_TO_STRING)) == sorted(
@ -122,20 +144,15 @@ async def test_default_supported_features(
) )
@pytest.mark.parametrize(
"hass_config",
[DEFAULT_CONFIG_ALL_SERVICES],
)
async def test_all_commands( async def test_all_commands(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None: ) -> None:
"""Test simple commands to the vacuum.""" """Test simple commands to the vacuum."""
config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) mqtt_mock = await mqtt_mock_entry_no_yaml_config()
config[mqttvacuum.CONF_SUPPORTED_FEATURES] = services_to_strings(
ALL_SERVICES, SERVICE_TO_STRING
)
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()
await common.async_turn_on(hass, "vacuum.mqtttest") await common.async_turn_on(hass, "vacuum.mqtttest")
mqtt_mock.async_publish.assert_called_once_with( mqtt_mock.async_publish.assert_called_once_with(
@ -206,21 +223,27 @@ async def test_all_commands(
} }
@pytest.mark.parametrize(
"hass_config",
[
help_custom_config(
vacuum.DOMAIN,
DEFAULT_CONFIG,
(
{
mqttvacuum.CONF_SUPPORTED_FEATURES: services_to_strings(
mqttvacuum.STRING_TO_SERVICE["status"], SERVICE_TO_STRING
)
},
),
)
],
)
async def test_commands_without_supported_features( async def test_commands_without_supported_features(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None: ) -> None:
"""Test commands which are not supported by the vacuum.""" """Test commands which are not supported by the vacuum."""
config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) mqtt_mock = await mqtt_mock_entry_no_yaml_config()
services = mqttvacuum.STRING_TO_SERVICE["status"]
config[mqttvacuum.CONF_SUPPORTED_FEATURES] = services_to_strings(
services, SERVICE_TO_STRING
)
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()
await common.async_turn_on(hass, "vacuum.mqtttest") await common.async_turn_on(hass, "vacuum.mqtttest")
mqtt_mock.async_publish.assert_not_called() mqtt_mock.async_publish.assert_not_called()
@ -259,21 +282,27 @@ async def test_commands_without_supported_features(
mqtt_mock.async_publish.reset_mock() mqtt_mock.async_publish.reset_mock()
@pytest.mark.parametrize(
"hass_config",
[
help_custom_config(
vacuum.DOMAIN,
DEFAULT_CONFIG,
(
{
mqttvacuum.CONF_SUPPORTED_FEATURES: services_to_strings(
mqttvacuum.STRING_TO_SERVICE["turn_on"], SERVICE_TO_STRING
)
},
),
)
],
)
async def test_attributes_without_supported_features( async def test_attributes_without_supported_features(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None: ) -> None:
"""Test attributes which are not supported by the vacuum.""" """Test attributes which are not supported by the vacuum."""
config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) await mqtt_mock_entry_no_yaml_config()
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, mqtt.DOMAIN, {mqtt.DOMAIN: {vacuum.DOMAIN: config}}
)
await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config()
message = """{ message = """{
"battery_level": 54, "battery_level": 54,
@ -291,20 +320,15 @@ async def test_attributes_without_supported_features(
assert state.attributes.get(ATTR_FAN_SPEED_LIST) is None assert state.attributes.get(ATTR_FAN_SPEED_LIST) is None
@pytest.mark.parametrize(
"hass_config",
[DEFAULT_CONFIG_ALL_SERVICES],
)
async def test_status( async def test_status(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None: ) -> None:
"""Test status updates from the vacuum.""" """Test status updates from the vacuum."""
config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) await mqtt_mock_entry_no_yaml_config()
config[mqttvacuum.CONF_SUPPORTED_FEATURES] = services_to_strings(
ALL_SERVICES, SERVICE_TO_STRING
)
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()
message = """{ message = """{
"battery_level": 54, "battery_level": 54,
@ -336,20 +360,15 @@ async def test_status(
assert state.attributes.get(ATTR_FAN_SPEED) == "min" assert state.attributes.get(ATTR_FAN_SPEED) == "min"
@pytest.mark.parametrize(
"hass_config",
[DEFAULT_CONFIG_ALL_SERVICES],
)
async def test_status_battery( async def test_status_battery(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None: ) -> None:
"""Test status updates from the vacuum.""" """Test status updates from the vacuum."""
config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) await mqtt_mock_entry_no_yaml_config()
config[mqttvacuum.CONF_SUPPORTED_FEATURES] = services_to_strings(
ALL_SERVICES, SERVICE_TO_STRING
)
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()
message = """{ message = """{
"battery_level": 54 "battery_level": 54
@ -359,20 +378,16 @@ async def test_status_battery(
assert state.attributes.get(ATTR_BATTERY_ICON) == "mdi:battery-50" assert state.attributes.get(ATTR_BATTERY_ICON) == "mdi:battery-50"
@pytest.mark.parametrize(
"hass_config",
[DEFAULT_CONFIG_ALL_SERVICES],
)
async def test_status_cleaning( async def test_status_cleaning(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None: ) -> None:
"""Test status updates from the vacuum.""" """Test status updates from the vacuum."""
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, mqtt.DOMAIN, {mqtt.DOMAIN: {vacuum.DOMAIN: config}}
)
await hass.async_block_till_done() await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config() await mqtt_mock_entry_no_yaml_config()
message = """{ message = """{
"cleaning": true "cleaning": true
@ -382,20 +397,15 @@ async def test_status_cleaning(
assert state.state == STATE_ON assert state.state == STATE_ON
@pytest.mark.parametrize(
"hass_config",
[DEFAULT_CONFIG_ALL_SERVICES],
)
async def test_status_docked( async def test_status_docked(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None: ) -> None:
"""Test status updates from the vacuum.""" """Test status updates from the vacuum."""
config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) await mqtt_mock_entry_no_yaml_config()
config[mqttvacuum.CONF_SUPPORTED_FEATURES] = services_to_strings(
ALL_SERVICES, SERVICE_TO_STRING
)
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()
message = """{ message = """{
"docked": true "docked": true
@ -405,20 +415,15 @@ async def test_status_docked(
assert state.state == STATE_OFF assert state.state == STATE_OFF
@pytest.mark.parametrize(
"hass_config",
[DEFAULT_CONFIG_ALL_SERVICES],
)
async def test_status_charging( async def test_status_charging(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None: ) -> None:
"""Test status updates from the vacuum.""" """Test status updates from the vacuum."""
config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) await mqtt_mock_entry_no_yaml_config()
config[mqttvacuum.CONF_SUPPORTED_FEATURES] = services_to_strings(
ALL_SERVICES, SERVICE_TO_STRING
)
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()
message = """{ message = """{
"charging": true "charging": true
@ -428,20 +433,12 @@ async def test_status_charging(
assert state.attributes.get(ATTR_BATTERY_ICON) == "mdi:battery-outline" assert state.attributes.get(ATTR_BATTERY_ICON) == "mdi:battery-outline"
@pytest.mark.parametrize("hass_config", [DEFAULT_CONFIG_ALL_SERVICES])
async def test_status_fan_speed( async def test_status_fan_speed(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None: ) -> None:
"""Test status updates from the vacuum.""" """Test status updates from the vacuum."""
config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) await mqtt_mock_entry_no_yaml_config()
config[mqttvacuum.CONF_SUPPORTED_FEATURES] = services_to_strings(
ALL_SERVICES, SERVICE_TO_STRING
)
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()
message = """{ message = """{
"fan_speed": "max" "fan_speed": "max"
@ -451,62 +448,52 @@ async def test_status_fan_speed(
assert state.attributes.get(ATTR_FAN_SPEED) == "max" assert state.attributes.get(ATTR_FAN_SPEED) == "max"
@pytest.mark.parametrize("hass_config", [DEFAULT_CONFIG_ALL_SERVICES])
async def test_status_fan_speed_list( async def test_status_fan_speed_list(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None: ) -> None:
"""Test status updates from the vacuum.""" """Test status updates from the vacuum."""
config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) await mqtt_mock_entry_no_yaml_config()
config[mqttvacuum.CONF_SUPPORTED_FEATURES] = services_to_strings(
ALL_SERVICES, SERVICE_TO_STRING
)
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") state = hass.states.get("vacuum.mqtttest")
assert state.attributes.get(ATTR_FAN_SPEED_LIST) == ["min", "medium", "high", "max"] assert state.attributes.get(ATTR_FAN_SPEED_LIST) == ["min", "medium", "high", "max"]
@pytest.mark.parametrize(
"hass_config",
[
help_custom_config(
vacuum.DOMAIN,
DEFAULT_CONFIG,
(
{
mqttvacuum.CONF_SUPPORTED_FEATURES: services_to_strings(
ALL_SERVICES - VacuumEntityFeature.FAN_SPEED, SERVICE_TO_STRING
)
},
),
)
],
)
async def test_status_no_fan_speed_list( async def test_status_no_fan_speed_list(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None: ) -> None:
"""Test status updates from the vacuum. """Test status updates from the vacuum.
If the vacuum doesn't support fan speed, fan speed list should be None. If the vacuum doesn't support fan speed, fan speed list should be None.
""" """
config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) await mqtt_mock_entry_no_yaml_config()
services = ALL_SERVICES - VacuumEntityFeature.FAN_SPEED
config[mqttvacuum.CONF_SUPPORTED_FEATURES] = services_to_strings(
services, SERVICE_TO_STRING
)
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") state = hass.states.get("vacuum.mqtttest")
assert state.attributes.get(ATTR_FAN_SPEED_LIST) is None assert state.attributes.get(ATTR_FAN_SPEED_LIST) is None
@pytest.mark.parametrize("hass_config", [DEFAULT_CONFIG_ALL_SERVICES])
async def test_status_error( async def test_status_error(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None: ) -> None:
"""Test status updates from the vacuum.""" """Test status updates from the vacuum."""
config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) await mqtt_mock_entry_no_yaml_config()
config[mqttvacuum.CONF_SUPPORTED_FEATURES] = services_to_strings(
ALL_SERVICES, SERVICE_TO_STRING
)
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()
message = """{ message = """{
"error": "Error1" "error": "Error1"
@ -523,26 +510,26 @@ async def test_status_error(
assert state.attributes.get(ATTR_STATUS) == "Stopped" assert state.attributes.get(ATTR_STATUS) == "Stopped"
@pytest.mark.parametrize(
"hass_config",
[
help_custom_config(
vacuum.DOMAIN,
DEFAULT_CONFIG,
(
{
mqttvacuum.CONF_BATTERY_LEVEL_TOPIC: "retroroomba/battery_level",
mqttvacuum.CONF_BATTERY_LEVEL_TEMPLATE: "{{ value }}",
},
),
)
],
)
async def test_battery_template( async def test_battery_template(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None: ) -> None:
"""Test that you can use non-default templates for battery_level.""" """Test that you can use non-default templates for battery_level."""
config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) await mqtt_mock_entry_no_yaml_config()
config.update(
{
mqttvacuum.CONF_SUPPORTED_FEATURES: services_to_strings(
ALL_SERVICES, SERVICE_TO_STRING
),
mqttvacuum.CONF_BATTERY_LEVEL_TOPIC: "retroroomba/battery_level",
mqttvacuum.CONF_BATTERY_LEVEL_TEMPLATE: "{{ value }}",
}
)
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()
async_fire_mqtt_message(hass, "retroroomba/battery_level", "54") async_fire_mqtt_message(hass, "retroroomba/battery_level", "54")
state = hass.states.get("vacuum.mqtttest") state = hass.states.get("vacuum.mqtttest")
@ -550,20 +537,12 @@ async def test_battery_template(
assert state.attributes.get(ATTR_BATTERY_ICON) == "mdi:battery-50" assert state.attributes.get(ATTR_BATTERY_ICON) == "mdi:battery-50"
@pytest.mark.parametrize("hass_config", [DEFAULT_CONFIG_ALL_SERVICES])
async def test_status_invalid_json( async def test_status_invalid_json(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None: ) -> None:
"""Test to make sure nothing breaks if the vacuum sends bad JSON.""" """Test to make sure nothing breaks if the vacuum sends bad JSON."""
config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) await mqtt_mock_entry_no_yaml_config()
config[mqttvacuum.CONF_SUPPORTED_FEATURES] = services_to_strings(
ALL_SERVICES, SERVICE_TO_STRING
)
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()
async_fire_mqtt_message(hass, "vacuum/state", '{"asdfasas false}') async_fire_mqtt_message(hass, "vacuum/state", '{"asdfasas false}')
state = hass.states.get("vacuum.mqtttest") state = hass.states.get("vacuum.mqtttest")
@ -571,63 +550,28 @@ async def test_status_invalid_json(
assert state.attributes.get(ATTR_STATUS) == "Stopped" assert state.attributes.get(ATTR_STATUS) == "Stopped"
async def test_missing_battery_template(hass: HomeAssistant) -> None: @pytest.mark.parametrize(
"hass_config",
[
filter_options(DEFAULT_CONFIG, {mqttvacuum.CONF_BATTERY_LEVEL_TEMPLATE}),
filter_options(DEFAULT_CONFIG, {mqttvacuum.CONF_CHARGING_TEMPLATE}),
filter_options(DEFAULT_CONFIG, {mqttvacuum.CONF_CLEANING_TEMPLATE}),
filter_options(DEFAULT_CONFIG, {mqttvacuum.CONF_DOCKED_TEMPLATE}),
filter_options(DEFAULT_CONFIG, {mqttvacuum.CONF_ERROR_TEMPLATE}),
filter_options(DEFAULT_CONFIG, {mqttvacuum.CONF_FAN_SPEED_TEMPLATE}),
],
)
async def test_missing_templates(
hass: HomeAssistant,
mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test to make sure missing template is not allowed.""" """Test to make sure missing template is not allowed."""
config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN]) with pytest.raises(AssertionError):
config.pop(mqttvacuum.CONF_BATTERY_LEVEL_TEMPLATE) await mqtt_mock_entry_no_yaml_config()
assert (
assert not await async_setup_component( "Invalid config for [mqtt]: some but not all values in the same group of inclusion"
hass, mqtt.DOMAIN, {mqtt.DOMAIN: {vacuum.DOMAIN: config}} in caplog.text
)
async def test_missing_charging_template(hass: HomeAssistant) -> None:
"""Test to make sure missing template is not allowed."""
config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN])
config.pop(mqttvacuum.CONF_CHARGING_TEMPLATE)
assert not await async_setup_component(
hass, mqtt.DOMAIN, {mqtt.DOMAIN: {vacuum.DOMAIN: config}}
)
async def test_missing_cleaning_template(hass: HomeAssistant) -> None:
"""Test to make sure missing template is not allowed."""
config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN])
config.pop(mqttvacuum.CONF_CLEANING_TEMPLATE)
assert not await async_setup_component(
hass, mqtt.DOMAIN, {mqtt.DOMAIN: {vacuum.DOMAIN: config}}
)
async def test_missing_docked_template(hass: HomeAssistant) -> None:
"""Test to make sure missing template is not allowed."""
config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN])
config.pop(mqttvacuum.CONF_DOCKED_TEMPLATE)
assert not await async_setup_component(
hass, mqtt.DOMAIN, {mqtt.DOMAIN: {vacuum.DOMAIN: config}}
)
async def test_missing_error_template(hass: HomeAssistant) -> None:
"""Test to make sure missing template is not allowed."""
config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN])
config.pop(mqttvacuum.CONF_ERROR_TEMPLATE)
assert not await async_setup_component(
hass, mqtt.DOMAIN, {mqtt.DOMAIN: {vacuum.DOMAIN: config}}
)
async def test_missing_fan_speed_template(hass: HomeAssistant) -> None:
"""Test to make sure missing template is not allowed."""
config = deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][vacuum.DOMAIN])
config.pop(mqttvacuum.CONF_FAN_SPEED_TEMPLATE)
assert not await async_setup_component(
hass, mqtt.DOMAIN, {mqtt.DOMAIN: {vacuum.DOMAIN: config}}
) )