core/tests/components/template/test_vacuum.py

977 lines
28 KiB
Python

"""The tests for the Template vacuum platform."""
from typing import Any
import pytest
from homeassistant.components import template, vacuum
from homeassistant.components.vacuum import (
ATTR_BATTERY_LEVEL,
ATTR_FAN_SPEED,
VacuumActivity,
VacuumEntityFeature,
)
from homeassistant.const import STATE_OFF, STATE_ON, STATE_UNAVAILABLE, STATE_UNKNOWN
from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.entity_component import async_update_entity
from homeassistant.setup import async_setup_component
from .conftest import ConfigurationStyle
from tests.common import assert_setup_component
from tests.components.vacuum import common
TEST_OBJECT_ID = "test_vacuum"
TEST_ENTITY_ID = f"vacuum.{TEST_OBJECT_ID}"
STATE_INPUT_SELECT = "input_select.state"
BATTERY_LEVEL_INPUT_NUMBER = "input_number.battery_level"
START_ACTION = {
"start": {
"service": "test.automation",
"data": {
"caller": "{{ this.entity_id }}",
"action": "start",
},
},
}
TEMPLATE_VACUUM_ACTIONS = {
**START_ACTION,
"pause": {
"service": "test.automation",
"data": {
"caller": "{{ this.entity_id }}",
"action": "pause",
},
},
"stop": {
"service": "test.automation",
"data": {
"caller": "{{ this.entity_id }}",
"action": "stop",
},
},
"return_to_base": {
"service": "test.automation",
"data": {
"caller": "{{ this.entity_id }}",
"action": "return_to_base",
},
},
"clean_spot": {
"service": "test.automation",
"data": {
"caller": "{{ this.entity_id }}",
"action": "clean_spot",
},
},
"locate": {
"service": "test.automation",
"data": {
"caller": "{{ this.entity_id }}",
"action": "locate",
},
},
"set_fan_speed": {
"service": "test.automation",
"data": {
"caller": "{{ this.entity_id }}",
"action": "set_fan_speed",
"fan_speed": "{{ fan_speed }}",
},
},
}
UNIQUE_ID_CONFIG = {"unique_id": "not-so-unique-anymore", **TEMPLATE_VACUUM_ACTIONS}
def _verify(
hass: HomeAssistant,
expected_state: str,
expected_battery_level: int | None = None,
expected_fan_speed: int | None = None,
) -> None:
"""Verify vacuum's state and speed."""
state = hass.states.get(TEST_ENTITY_ID)
attributes = state.attributes
assert state.state == expected_state
assert attributes.get(ATTR_BATTERY_LEVEL) == expected_battery_level
assert attributes.get(ATTR_FAN_SPEED) == expected_fan_speed
async def async_setup_legacy_format(
hass: HomeAssistant, count: int, vacuum_config: dict[str, Any]
) -> None:
"""Do setup of vacuum integration via new format."""
config = {"vacuum": {"platform": "template", "vacuums": vacuum_config}}
with assert_setup_component(count, vacuum.DOMAIN):
assert await async_setup_component(
hass,
vacuum.DOMAIN,
config,
)
await hass.async_block_till_done()
await hass.async_start()
await hass.async_block_till_done()
async def async_setup_modern_format(
hass: HomeAssistant, count: int, vacuum_config: dict[str, Any]
) -> None:
"""Do setup of vacuum integration via modern format."""
config = {"template": {"vacuum": vacuum_config}}
with assert_setup_component(count, template.DOMAIN):
assert await async_setup_component(
hass,
template.DOMAIN,
config,
)
await hass.async_block_till_done()
await hass.async_start()
await hass.async_block_till_done()
@pytest.fixture
async def setup_vacuum(
hass: HomeAssistant,
count: int,
style: ConfigurationStyle,
vacuum_config: dict[str, Any],
) -> None:
"""Do setup of number integration."""
if style == ConfigurationStyle.LEGACY:
await async_setup_legacy_format(hass, count, vacuum_config)
elif style == ConfigurationStyle.MODERN:
await async_setup_modern_format(hass, count, vacuum_config)
@pytest.fixture
async def setup_test_vacuum_with_extra_config(
hass: HomeAssistant,
count: int,
style: ConfigurationStyle,
vacuum_config: dict[str, Any],
extra_config: dict[str, Any],
) -> None:
"""Do setup of number integration."""
if style == ConfigurationStyle.LEGACY:
await async_setup_legacy_format(
hass, count, {TEST_OBJECT_ID: {**vacuum_config, **extra_config}}
)
elif style == ConfigurationStyle.MODERN:
await async_setup_modern_format(
hass, count, {"name": TEST_OBJECT_ID, **vacuum_config, **extra_config}
)
@pytest.fixture
async def setup_state_vacuum(
hass: HomeAssistant,
count: int,
style: ConfigurationStyle,
state_template: str,
):
"""Do setup of vacuum integration using a state template."""
if style == ConfigurationStyle.LEGACY:
await async_setup_legacy_format(
hass,
count,
{
TEST_OBJECT_ID: {
"value_template": state_template,
**TEMPLATE_VACUUM_ACTIONS,
}
},
)
elif style == ConfigurationStyle.MODERN:
await async_setup_modern_format(
hass,
count,
{
"name": TEST_OBJECT_ID,
"state": state_template,
**TEMPLATE_VACUUM_ACTIONS,
},
)
@pytest.fixture
async def setup_base_vacuum(
hass: HomeAssistant,
count: int,
style: ConfigurationStyle,
state_template: str | None,
extra_config: dict,
):
"""Do setup of vacuum integration using a state template."""
if style == ConfigurationStyle.LEGACY:
state_config = {"value_template": state_template} if state_template else {}
await async_setup_legacy_format(
hass,
count,
{
TEST_OBJECT_ID: {
**state_config,
**extra_config,
}
},
)
elif style == ConfigurationStyle.MODERN:
state_config = {"state": state_template} if state_template else {}
await async_setup_modern_format(
hass,
count,
{
"name": TEST_OBJECT_ID,
**state_config,
**extra_config,
},
)
@pytest.fixture
async def setup_single_attribute_state_vacuum(
hass: HomeAssistant,
count: int,
style: ConfigurationStyle,
state_template: str | None,
attribute: str,
attribute_template: str,
extra_config: dict,
) -> None:
"""Do setup of vacuum integration testing a single attribute."""
extra = {attribute: attribute_template} if attribute and attribute_template else {}
if style == ConfigurationStyle.LEGACY:
state_config = {"value_template": state_template} if state_template else {}
await async_setup_legacy_format(
hass,
count,
{
TEST_OBJECT_ID: {
**state_config,
**TEMPLATE_VACUUM_ACTIONS,
**extra,
**extra_config,
}
},
)
elif style == ConfigurationStyle.MODERN:
state_config = {"state": state_template} if state_template else {}
await async_setup_modern_format(
hass,
count,
{
"name": TEST_OBJECT_ID,
**state_config,
**TEMPLATE_VACUUM_ACTIONS,
**extra,
**extra_config,
},
)
@pytest.fixture
async def setup_attributes_state_vacuum(
hass: HomeAssistant,
count: int,
style: ConfigurationStyle,
state_template: str | None,
attributes: dict,
) -> None:
"""Do setup of vacuum integration testing a single attribute."""
if style == ConfigurationStyle.LEGACY:
state_config = {"value_template": state_template} if state_template else {}
await async_setup_legacy_format(
hass,
count,
{
TEST_OBJECT_ID: {
"attribute_templates": attributes,
**state_config,
**TEMPLATE_VACUUM_ACTIONS,
}
},
)
elif style == ConfigurationStyle.MODERN:
state_config = {"state": state_template} if state_template else {}
await async_setup_modern_format(
hass,
count,
{
"name": TEST_OBJECT_ID,
"attributes": attributes,
**state_config,
**TEMPLATE_VACUUM_ACTIONS,
},
)
@pytest.mark.parametrize("count", [1])
@pytest.mark.parametrize(
("style", "state_template", "extra_config", "parm1", "parm2"),
[
(
ConfigurationStyle.LEGACY,
None,
{"start": {"service": "script.vacuum_start"}},
STATE_UNKNOWN,
None,
),
(
ConfigurationStyle.MODERN,
None,
{"start": {"service": "script.vacuum_start"}},
STATE_UNKNOWN,
None,
),
(
ConfigurationStyle.LEGACY,
"{{ 'cleaning' }}",
{
"battery_level_template": "{{ 100 }}",
"start": {"service": "script.vacuum_start"},
},
VacuumActivity.CLEANING,
100,
),
(
ConfigurationStyle.MODERN,
"{{ 'cleaning' }}",
{
"battery_level": "{{ 100 }}",
"start": {"service": "script.vacuum_start"},
},
VacuumActivity.CLEANING,
100,
),
(
ConfigurationStyle.LEGACY,
"{{ 'abc' }}",
{
"battery_level_template": "{{ 101 }}",
"start": {"service": "script.vacuum_start"},
},
STATE_UNKNOWN,
None,
),
(
ConfigurationStyle.MODERN,
"{{ 'abc' }}",
{
"battery_level": "{{ 101 }}",
"start": {"service": "script.vacuum_start"},
},
STATE_UNKNOWN,
None,
),
(
ConfigurationStyle.LEGACY,
"{{ this_function_does_not_exist() }}",
{
"battery_level_template": "{{ this_function_does_not_exist() }}",
"fan_speed_template": "{{ this_function_does_not_exist() }}",
"start": {"service": "script.vacuum_start"},
},
STATE_UNKNOWN,
None,
),
(
ConfigurationStyle.MODERN,
"{{ this_function_does_not_exist() }}",
{
"battery_level": "{{ this_function_does_not_exist() }}",
"fan_speed": "{{ this_function_does_not_exist() }}",
"start": {"service": "script.vacuum_start"},
},
STATE_UNKNOWN,
None,
),
],
)
@pytest.mark.usefixtures("setup_base_vacuum")
async def test_valid_legacy_configs(hass: HomeAssistant, count, parm1, parm2) -> None:
"""Test: configs."""
assert len(hass.states.async_all("vacuum")) == count
_verify(hass, parm1, parm2)
@pytest.mark.parametrize("count", [0])
@pytest.mark.parametrize(
"style", [ConfigurationStyle.LEGACY, ConfigurationStyle.MODERN]
)
@pytest.mark.parametrize(
("state_template", "extra_config"),
[
("{{ 'on' }}", {}),
(None, {"nothingburger": {"service": "script.vacuum_start"}}),
],
)
@pytest.mark.usefixtures("setup_base_vacuum")
async def test_invalid_configs(hass: HomeAssistant, count) -> None:
"""Test: configs."""
assert len(hass.states.async_all("vacuum")) == count
@pytest.mark.parametrize(
("count", "state_template", "extra_config"),
[(1, "{{ states('input_select.state') }}", {})],
)
@pytest.mark.parametrize(
("style", "attribute"),
[
(ConfigurationStyle.LEGACY, "battery_level_template"),
(ConfigurationStyle.MODERN, "battery_level"),
],
)
@pytest.mark.parametrize(
("attribute_template", "expected"),
[
("{{ '0' }}", 0),
("{{ 100 }}", 100),
("{{ 101 }}", None),
("{{ -1 }}", None),
("{{ 'foo' }}", None),
],
)
@pytest.mark.usefixtures("setup_single_attribute_state_vacuum")
async def test_battery_level_template(
hass: HomeAssistant, expected: int | None
) -> None:
"""Test templates with values from other entities."""
_verify(hass, STATE_UNKNOWN, expected)
@pytest.mark.parametrize(
("count", "state_template", "extra_config"),
[
(
1,
"{{ states('input_select.state') }}",
{
"fan_speeds": ["low", "medium", "high"],
},
)
],
)
@pytest.mark.parametrize(
("style", "attribute"),
[
(ConfigurationStyle.LEGACY, "fan_speed_template"),
(ConfigurationStyle.MODERN, "fan_speed"),
],
)
@pytest.mark.parametrize(
("attribute_template", "expected"),
[
("{{ 'low' }}", "low"),
("{{ 'medium' }}", "medium"),
("{{ 'high' }}", "high"),
("{{ 'invalid' }}", None),
],
)
@pytest.mark.usefixtures("setup_single_attribute_state_vacuum")
async def test_fan_speed_template(hass: HomeAssistant, expected: str | None) -> None:
"""Test templates with values from other entities."""
_verify(hass, STATE_UNKNOWN, None, expected)
@pytest.mark.parametrize(
("count", "state_template", "attribute_template", "extra_config"),
[
(
1,
"{{ 'on' }}",
"{% if states.switch.test_state.state %}mdi:check{% endif %}",
{},
)
],
)
@pytest.mark.parametrize(
("style", "attribute"),
[
(ConfigurationStyle.MODERN, "icon"),
],
)
@pytest.mark.usefixtures("setup_single_attribute_state_vacuum")
async def test_icon_template(hass: HomeAssistant) -> None:
"""Test icon template."""
state = hass.states.get(TEST_ENTITY_ID)
assert state.attributes.get("icon") in ("", None)
hass.states.async_set("switch.test_state", STATE_ON)
await hass.async_block_till_done()
state = hass.states.get(TEST_ENTITY_ID)
assert state.attributes["icon"] == "mdi:check"
@pytest.mark.parametrize(
("count", "state_template", "attribute_template", "extra_config"),
[
(
1,
"{{ 'on' }}",
"{% if states.switch.test_state.state %}local/vacuum.png{% endif %}",
{},
)
],
)
@pytest.mark.parametrize(
("style", "attribute"),
[
(ConfigurationStyle.MODERN, "picture"),
],
)
@pytest.mark.usefixtures("setup_single_attribute_state_vacuum")
async def test_picture_template(hass: HomeAssistant) -> None:
"""Test picture template."""
state = hass.states.get(TEST_ENTITY_ID)
assert state.attributes.get("entity_picture") in ("", None)
hass.states.async_set("switch.test_state", STATE_ON)
await hass.async_block_till_done()
state = hass.states.get(TEST_ENTITY_ID)
assert state.attributes["entity_picture"] == "local/vacuum.png"
@pytest.mark.parametrize("extra_config", [{}])
@pytest.mark.parametrize(
("count", "state_template", "attribute_template"),
[
(
1,
None,
"{{ is_state('availability_state.state', 'on') }}",
)
],
)
@pytest.mark.parametrize(
("style", "attribute"),
[
(ConfigurationStyle.LEGACY, "availability_template"),
(ConfigurationStyle.MODERN, "availability"),
],
)
@pytest.mark.usefixtures("setup_single_attribute_state_vacuum")
async def test_available_template_with_entities(hass: HomeAssistant) -> None:
"""Test availability templates with values from other entities."""
# When template returns true..
hass.states.async_set("availability_state.state", STATE_ON)
await hass.async_block_till_done()
# Device State should not be unavailable
assert hass.states.get(TEST_ENTITY_ID).state != STATE_UNAVAILABLE
# When Availability template returns false
hass.states.async_set("availability_state.state", STATE_OFF)
await hass.async_block_till_done()
# device state should be unavailable
assert hass.states.get(TEST_ENTITY_ID).state == STATE_UNAVAILABLE
@pytest.mark.parametrize("extra_config", [{}])
@pytest.mark.parametrize(
("count", "state_template", "attribute_template"),
[
(
1,
None,
"{{ x - 12 }}",
)
],
)
@pytest.mark.parametrize(
("style", "attribute"),
[
(ConfigurationStyle.LEGACY, "availability_template"),
(ConfigurationStyle.MODERN, "availability"),
],
)
@pytest.mark.usefixtures("setup_single_attribute_state_vacuum")
async def test_invalid_availability_template_keeps_component_available(
hass: HomeAssistant, caplog_setup_text
) -> None:
"""Test that an invalid availability keeps the device available."""
assert hass.states.get(TEST_ENTITY_ID) != STATE_UNAVAILABLE
assert "UndefinedError: 'x' is undefined" in caplog_setup_text
@pytest.mark.parametrize(
"style", [ConfigurationStyle.LEGACY, ConfigurationStyle.MODERN]
)
@pytest.mark.parametrize(
("count", "state_template", "attributes"),
[
(
1,
"{{ 'cleaning' }}",
{"test_attribute": "It {{ states.sensor.test_state.state }}."},
)
],
)
@pytest.mark.usefixtures("setup_attributes_state_vacuum")
async def test_attribute_templates(hass: HomeAssistant) -> None:
"""Test attribute_templates template."""
state = hass.states.get(TEST_ENTITY_ID)
assert state.attributes["test_attribute"] == "It ."
hass.states.async_set("sensor.test_state", "Works")
await hass.async_block_till_done()
await async_update_entity(hass, TEST_ENTITY_ID)
state = hass.states.get(TEST_ENTITY_ID)
assert state.attributes["test_attribute"] == "It Works."
@pytest.mark.parametrize(
"style", [ConfigurationStyle.LEGACY, ConfigurationStyle.MODERN]
)
@pytest.mark.parametrize(
("count", "state_template", "attributes"),
[
(
1,
"{{ states('input_select.state') }}",
{"test_attribute": "{{ this_function_does_not_exist() }}"},
)
],
)
@pytest.mark.usefixtures("setup_attributes_state_vacuum")
async def test_invalid_attribute_template(
hass: HomeAssistant, caplog_setup_text
) -> None:
"""Test that errors are logged if rendering template fails."""
assert len(hass.states.async_all("vacuum")) == 1
assert "test_attribute" in caplog_setup_text
assert "TemplateError" in caplog_setup_text
@pytest.mark.parametrize("count", [1])
@pytest.mark.parametrize(
("style", "vacuum_config"),
[
(
ConfigurationStyle.LEGACY,
{
"test_template_vacuum_01": {
"value_template": "{{ true }}",
**UNIQUE_ID_CONFIG,
},
"test_template_vacuum_02": {
"value_template": "{{ false }}",
**UNIQUE_ID_CONFIG,
},
},
),
(
ConfigurationStyle.MODERN,
[
{
"name": "test_template_vacuum_01",
"state": "{{ true }}",
**UNIQUE_ID_CONFIG,
},
{
"name": "test_template_vacuum_02",
"state": "{{ false }}",
**UNIQUE_ID_CONFIG,
},
],
),
],
)
@pytest.mark.usefixtures("setup_vacuum")
async def test_unique_id(hass: HomeAssistant) -> None:
"""Test unique_id option only creates one vacuum per id."""
assert len(hass.states.async_all("vacuum")) == 1
@pytest.mark.parametrize(
("count", "state_template", "extra_config"), [(1, None, START_ACTION)]
)
@pytest.mark.parametrize(
"style", [ConfigurationStyle.LEGACY, ConfigurationStyle.MODERN]
)
@pytest.mark.usefixtures("setup_base_vacuum")
async def test_unused_services(hass: HomeAssistant) -> None:
"""Test calling unused services raises."""
# Pause vacuum
with pytest.raises(HomeAssistantError):
await common.async_pause(hass, TEST_ENTITY_ID)
await hass.async_block_till_done()
# Stop vacuum
with pytest.raises(HomeAssistantError):
await common.async_stop(hass, TEST_ENTITY_ID)
await hass.async_block_till_done()
# Return vacuum to base
with pytest.raises(HomeAssistantError):
await common.async_return_to_base(hass, TEST_ENTITY_ID)
await hass.async_block_till_done()
# Spot cleaning
with pytest.raises(HomeAssistantError):
await common.async_clean_spot(hass, TEST_ENTITY_ID)
await hass.async_block_till_done()
# Locate vacuum
with pytest.raises(HomeAssistantError):
await common.async_locate(hass, TEST_ENTITY_ID)
await hass.async_block_till_done()
# Set fan's speed
with pytest.raises(HomeAssistantError):
await common.async_set_fan_speed(hass, "medium", TEST_ENTITY_ID)
await hass.async_block_till_done()
_verify(hass, STATE_UNKNOWN, None)
@pytest.mark.parametrize(
("count", "state_template"),
[(1, "{{ states('input_select.state') }}")],
)
@pytest.mark.parametrize(
"style", [ConfigurationStyle.LEGACY, ConfigurationStyle.MODERN]
)
@pytest.mark.parametrize(
"action",
[
"start",
"pause",
"stop",
"clean_spot",
"return_to_base",
"locate",
],
)
@pytest.mark.usefixtures("setup_state_vacuum")
async def test_state_services(
hass: HomeAssistant, action: str, calls: list[ServiceCall]
) -> None:
"""Test locate service."""
await hass.services.async_call(
"vacuum",
action,
{"entity_id": TEST_ENTITY_ID},
blocking=True,
)
await hass.async_block_till_done()
# verify
assert len(calls) == 1
assert calls[-1].data["action"] == action
assert calls[-1].data["caller"] == TEST_ENTITY_ID
@pytest.mark.parametrize(
("count", "state_template", "attribute_template", "extra_config"),
[
(
1,
"{{ states('input_select.state') }}",
"{{ states('input_select.fan_speed') }}",
{
"fan_speeds": ["low", "medium", "high"],
},
)
],
)
@pytest.mark.parametrize(
("style", "attribute"),
[
(ConfigurationStyle.LEGACY, "fan_speed_template"),
(ConfigurationStyle.MODERN, "fan_speed"),
],
)
@pytest.mark.usefixtures("setup_single_attribute_state_vacuum")
async def test_set_fan_speed(hass: HomeAssistant, calls: list[ServiceCall]) -> None:
"""Test set valid fan speed."""
# Set vacuum's fan speed to high
await common.async_set_fan_speed(hass, "high", TEST_ENTITY_ID)
await hass.async_block_till_done()
# verify
assert len(calls) == 1
assert calls[-1].data["action"] == "set_fan_speed"
assert calls[-1].data["caller"] == TEST_ENTITY_ID
assert calls[-1].data["fan_speed"] == "high"
# Set fan's speed to medium
await common.async_set_fan_speed(hass, "medium", TEST_ENTITY_ID)
await hass.async_block_till_done()
# verify
assert len(calls) == 2
assert calls[-1].data["action"] == "set_fan_speed"
assert calls[-1].data["caller"] == TEST_ENTITY_ID
assert calls[-1].data["fan_speed"] == "medium"
@pytest.mark.parametrize(
"extra_config",
[
{
"fan_speeds": ["low", "medium", "high"],
}
],
)
@pytest.mark.parametrize(
("count", "state_template", "attribute_template"),
[
(
1,
"{{ states('input_select.state') }}",
"{{ states('input_select.fan_speed') }}",
)
],
)
@pytest.mark.parametrize(
("style", "attribute"),
[
(ConfigurationStyle.LEGACY, "fan_speed_template"),
(ConfigurationStyle.MODERN, "fan_speed"),
],
)
@pytest.mark.usefixtures("setup_single_attribute_state_vacuum")
async def test_set_invalid_fan_speed(
hass: HomeAssistant, calls: list[ServiceCall]
) -> None:
"""Test set invalid fan speed when fan has valid speed."""
# Set vacuum's fan speed to high
await common.async_set_fan_speed(hass, "high", TEST_ENTITY_ID)
await hass.async_block_till_done()
# verify
assert len(calls) == 1
assert calls[-1].data["action"] == "set_fan_speed"
assert calls[-1].data["caller"] == TEST_ENTITY_ID
assert calls[-1].data["fan_speed"] == "high"
# Set vacuum's fan speed to 'invalid'
await common.async_set_fan_speed(hass, "invalid", TEST_ENTITY_ID)
await hass.async_block_till_done()
# verify fan speed is unchanged
assert len(calls) == 1
assert calls[-1].data["action"] == "set_fan_speed"
assert calls[-1].data["caller"] == TEST_ENTITY_ID
assert calls[-1].data["fan_speed"] == "high"
async def test_nested_unique_id(
hass: HomeAssistant, entity_registry: er.EntityRegistry
) -> None:
"""Test a template unique_id propagates to switch unique_ids."""
with assert_setup_component(1, template.DOMAIN):
assert await async_setup_component(
hass,
template.DOMAIN,
{
"template": {
"unique_id": "x",
"vacuum": [
{
**TEMPLATE_VACUUM_ACTIONS,
"name": "test_a",
"unique_id": "a",
},
{
**TEMPLATE_VACUUM_ACTIONS,
"name": "test_b",
"unique_id": "b",
},
],
},
},
)
await hass.async_block_till_done()
await hass.async_start()
await hass.async_block_till_done()
assert len(hass.states.async_all("vacuum")) == 2
entry = entity_registry.async_get("vacuum.test_a")
assert entry
assert entry.unique_id == "x-a"
entry = entity_registry.async_get("vacuum.test_b")
assert entry
assert entry.unique_id == "x-b"
@pytest.mark.parametrize(("count", "vacuum_config"), [(1, {"start": []})])
@pytest.mark.parametrize(
"style", [ConfigurationStyle.LEGACY, ConfigurationStyle.MODERN]
)
@pytest.mark.parametrize(
("extra_config", "supported_features"),
[
(
{
"pause": [],
},
VacuumEntityFeature.PAUSE,
),
(
{
"stop": [],
},
VacuumEntityFeature.STOP,
),
(
{
"return_to_base": [],
},
VacuumEntityFeature.RETURN_HOME,
),
(
{
"clean_spot": [],
},
VacuumEntityFeature.CLEAN_SPOT,
),
(
{
"locate": [],
},
VacuumEntityFeature.LOCATE,
),
(
{
"set_fan_speed": [],
},
VacuumEntityFeature.FAN_SPEED,
),
],
)
async def test_empty_action_config(
hass: HomeAssistant,
supported_features: VacuumEntityFeature,
setup_test_vacuum_with_extra_config,
) -> None:
"""Test configuration with empty script."""
await common.async_start(hass, TEST_ENTITY_ID)
await hass.async_block_till_done()
state = hass.states.get(TEST_ENTITY_ID)
assert state.attributes["supported_features"] == (
VacuumEntityFeature.STATE | VacuumEntityFeature.START | supported_features
)