mirror of
https://github.com/home-assistant/core.git
synced 2025-12-24 12:59:34 +00:00
Add common template test framework to vacuum platform (#157846)
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
"""template conftest."""
|
"""template conftest."""
|
||||||
|
|
||||||
|
from dataclasses import dataclass
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
@@ -8,6 +9,7 @@ from homeassistant.components import template
|
|||||||
from homeassistant.config_entries import SOURCE_USER
|
from homeassistant.config_entries import SOURCE_USER
|
||||||
from homeassistant.core import HomeAssistant, ServiceCall
|
from homeassistant.core import HomeAssistant, ServiceCall
|
||||||
from homeassistant.data_entry_flow import FlowResultType
|
from homeassistant.data_entry_flow import FlowResultType
|
||||||
|
from homeassistant.helpers import entity_registry as er
|
||||||
from homeassistant.helpers.typing import ConfigType
|
from homeassistant.helpers.typing import ConfigType
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
@@ -40,19 +42,37 @@ def make_test_trigger(*entities: str) -> dict:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def async_trigger(
|
||||||
|
hass: HomeAssistant, entity_id: str, state: str | None = None
|
||||||
|
) -> None:
|
||||||
|
"""Trigger a state change."""
|
||||||
|
hass.states.async_set(entity_id, state)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_legacy_platforms(
|
async def async_setup_legacy_platforms(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
domain: str,
|
domain: str,
|
||||||
slug: str,
|
slug: str | None,
|
||||||
count: int,
|
count: int,
|
||||||
config: ConfigType,
|
config: ConfigType | list[ConfigType],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Do setup of any legacy platform that supports a keyed dictionary of template entities."""
|
"""Do setup of any legacy platform that supports a keyed dictionary of template entities."""
|
||||||
|
if slug is None:
|
||||||
|
# Lock and Weather platforms do not use a slug
|
||||||
|
if isinstance(config, list):
|
||||||
|
config = {domain: [{"platform": "template", **item} for item in config]}
|
||||||
|
else:
|
||||||
|
config = {domain: {"platform": "template", **config}}
|
||||||
|
else:
|
||||||
|
assert isinstance(config, dict)
|
||||||
|
config = {domain: {"platform": "template", slug: config}}
|
||||||
|
|
||||||
with assert_setup_component(count, domain):
|
with assert_setup_component(count, domain):
|
||||||
assert await async_setup_component(
|
assert await async_setup_component(
|
||||||
hass,
|
hass,
|
||||||
domain,
|
domain,
|
||||||
{domain: {"platform": "template", slug: config}},
|
config,
|
||||||
)
|
)
|
||||||
|
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
@@ -64,16 +84,15 @@ async def async_setup_modern_state_format(
|
|||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
domain: str,
|
domain: str,
|
||||||
count: int,
|
count: int,
|
||||||
config: ConfigType,
|
config: ConfigType | list[ConfigType],
|
||||||
extra_config: ConfigType | None = None,
|
extra_section_config: ConfigType | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Do setup of template integration via modern format."""
|
"""Do setup of template integration via modern format."""
|
||||||
extra = extra_config or {}
|
|
||||||
with assert_setup_component(count, template.DOMAIN):
|
with assert_setup_component(count, template.DOMAIN):
|
||||||
assert await async_setup_component(
|
assert await async_setup_component(
|
||||||
hass,
|
hass,
|
||||||
template.DOMAIN,
|
template.DOMAIN,
|
||||||
{"template": {domain: config, **extra}},
|
{"template": {domain: config, **(extra_section_config or {})}},
|
||||||
)
|
)
|
||||||
|
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
@@ -86,12 +105,11 @@ async def async_setup_modern_trigger_format(
|
|||||||
domain: str,
|
domain: str,
|
||||||
trigger: dict,
|
trigger: dict,
|
||||||
count: int,
|
count: int,
|
||||||
config: ConfigType,
|
config: ConfigType | list[ConfigType],
|
||||||
extra_config: ConfigType | None = None,
|
extra_section_config: ConfigType | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Do setup of template integration via trigger format."""
|
"""Do setup of template integration via trigger format."""
|
||||||
extra = extra_config or {}
|
config = {"template": {domain: config, **trigger, **(extra_section_config or {})}}
|
||||||
config = {"template": {domain: config, **trigger, **extra}}
|
|
||||||
|
|
||||||
with assert_setup_component(count, template.DOMAIN):
|
with assert_setup_component(count, template.DOMAIN):
|
||||||
assert await async_setup_component(
|
assert await async_setup_component(
|
||||||
@@ -105,6 +123,164 @@ async def async_setup_modern_trigger_format(
|
|||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class TemplatePlatformSetup:
|
||||||
|
"""Template Platform Setup Information."""
|
||||||
|
|
||||||
|
domain: str
|
||||||
|
legacy_slug: str | None
|
||||||
|
object_id: str
|
||||||
|
trigger: ConfigType
|
||||||
|
|
||||||
|
@property
|
||||||
|
def entity_id(self) -> str:
|
||||||
|
"""Return test entity ID."""
|
||||||
|
return f"{self.domain}.{self.object_id}"
|
||||||
|
|
||||||
|
|
||||||
|
async def setup_entity(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
platform_setup: TemplatePlatformSetup,
|
||||||
|
style: ConfigurationStyle,
|
||||||
|
count: int,
|
||||||
|
config: ConfigType,
|
||||||
|
state_template: str | None = None,
|
||||||
|
extra_config: ConfigType | None = None,
|
||||||
|
attributes: ConfigType | None = None,
|
||||||
|
extra_section_config: ConfigType | None = None,
|
||||||
|
) -> None:
|
||||||
|
"""Do setup of a template entity based on the configuration style."""
|
||||||
|
if style == ConfigurationStyle.LEGACY:
|
||||||
|
await async_setup_legacy_platforms(
|
||||||
|
hass,
|
||||||
|
platform_setup.domain,
|
||||||
|
platform_setup.legacy_slug,
|
||||||
|
count,
|
||||||
|
{
|
||||||
|
platform_setup.object_id: {
|
||||||
|
**({"value_template": state_template} if state_template else {}),
|
||||||
|
**config,
|
||||||
|
**(extra_config or {}),
|
||||||
|
**({"attribute_templates": attributes} if attributes else {}),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
entity_config = {
|
||||||
|
"name": platform_setup.object_id,
|
||||||
|
**({"state": state_template} if state_template else {}),
|
||||||
|
**config,
|
||||||
|
**({"attributes": attributes} if attributes else {}),
|
||||||
|
**(extra_config or {}),
|
||||||
|
}
|
||||||
|
if style == ConfigurationStyle.MODERN:
|
||||||
|
await async_setup_modern_state_format(
|
||||||
|
hass, platform_setup.domain, count, entity_config, extra_section_config
|
||||||
|
)
|
||||||
|
elif style == ConfigurationStyle.TRIGGER:
|
||||||
|
await async_setup_modern_trigger_format(
|
||||||
|
hass,
|
||||||
|
platform_setup.domain,
|
||||||
|
platform_setup.trigger,
|
||||||
|
count,
|
||||||
|
entity_config,
|
||||||
|
extra_section_config,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def setup_and_test_unique_id(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
platform_setup: TemplatePlatformSetup,
|
||||||
|
style: ConfigurationStyle,
|
||||||
|
entity_config: ConfigType | None,
|
||||||
|
) -> None:
|
||||||
|
"""Setup 2 entities with the same unique_id and verify only 1 entity is created.
|
||||||
|
|
||||||
|
The entity_config not provide name or unique_id, those are added automatically.
|
||||||
|
"""
|
||||||
|
entity_config = {"unique_id": "not-so_-unique-anymore", **(entity_config or {})}
|
||||||
|
if style == ConfigurationStyle.LEGACY:
|
||||||
|
if platform_setup.legacy_slug is None:
|
||||||
|
config = [
|
||||||
|
{"name": "template_entity_1", **entity_config},
|
||||||
|
{"name": "template_entity_2", **entity_config},
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
config = {
|
||||||
|
"template_entity_1": entity_config,
|
||||||
|
"template_entity_2": entity_config,
|
||||||
|
}
|
||||||
|
await async_setup_legacy_platforms(
|
||||||
|
hass, platform_setup.domain, platform_setup.legacy_slug, 1, config
|
||||||
|
)
|
||||||
|
elif style == ConfigurationStyle.MODERN:
|
||||||
|
await async_setup_modern_state_format(
|
||||||
|
hass,
|
||||||
|
platform_setup.domain,
|
||||||
|
1,
|
||||||
|
[
|
||||||
|
{"name": "template_entity_1", **entity_config},
|
||||||
|
{"name": "template_entity_2", **entity_config},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
elif style == ConfigurationStyle.TRIGGER:
|
||||||
|
await async_setup_modern_trigger_format(
|
||||||
|
hass,
|
||||||
|
platform_setup.domain,
|
||||||
|
platform_setup.trigger,
|
||||||
|
1,
|
||||||
|
[
|
||||||
|
{"name": "template_entity_1", **entity_config},
|
||||||
|
{"name": "template_entity_2", **entity_config},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
assert len(hass.states.async_all(platform_setup.domain)) == 1
|
||||||
|
|
||||||
|
|
||||||
|
async def setup_and_test_nested_unique_id(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
platform_setup: TemplatePlatformSetup,
|
||||||
|
style: ConfigurationStyle,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
entity_config: ConfigType | None,
|
||||||
|
) -> None:
|
||||||
|
"""Setup 2 entities with unique unique_ids in a template section that contains a unique_id.
|
||||||
|
|
||||||
|
The test will verify that 2 entities are created where the unique_id appends the
|
||||||
|
section unique_id to each entity unique_id.
|
||||||
|
|
||||||
|
The entity_config should not provide name or unique_id, those are added automatically.
|
||||||
|
"""
|
||||||
|
entities = [
|
||||||
|
{"name": "test_a", "unique_id": "a", **(entity_config or {})},
|
||||||
|
{"name": "test_b", "unique_id": "b", **(entity_config or {})},
|
||||||
|
]
|
||||||
|
extra_section_config = {"unique_id": "x"}
|
||||||
|
if style == ConfigurationStyle.MODERN:
|
||||||
|
await async_setup_modern_state_format(
|
||||||
|
hass, platform_setup.domain, 1, entities, extra_section_config
|
||||||
|
)
|
||||||
|
elif style == ConfigurationStyle.TRIGGER:
|
||||||
|
await async_setup_modern_trigger_format(
|
||||||
|
hass,
|
||||||
|
platform_setup.domain,
|
||||||
|
platform_setup.trigger,
|
||||||
|
1,
|
||||||
|
entities,
|
||||||
|
extra_section_config,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert len(hass.states.async_all(platform_setup.domain)) == 2
|
||||||
|
|
||||||
|
entry = entity_registry.async_get(f"{platform_setup.domain}.test_a")
|
||||||
|
assert entry.unique_id == "x-a"
|
||||||
|
|
||||||
|
entry = entity_registry.async_get(f"{platform_setup.domain}.test_b")
|
||||||
|
assert entry.unique_id == "x-b"
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def calls(hass: HomeAssistant) -> list[ServiceCall]:
|
def calls(hass: HomeAssistant) -> list[ServiceCall]:
|
||||||
"""Track calls to a mock service."""
|
"""Track calls to a mock service."""
|
||||||
|
|||||||
@@ -17,37 +17,39 @@ from homeassistant.core import HomeAssistant, ServiceCall
|
|||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers import entity_registry as er, issue_registry as ir
|
from homeassistant.helpers import entity_registry as er, issue_registry as ir
|
||||||
from homeassistant.helpers.entity_component import async_update_entity
|
from homeassistant.helpers.entity_component import async_update_entity
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.helpers.typing import ConfigType
|
||||||
|
|
||||||
from .conftest import ConfigurationStyle, async_get_flow_preview_state
|
from .conftest import (
|
||||||
|
ConfigurationStyle,
|
||||||
|
TemplatePlatformSetup,
|
||||||
|
async_get_flow_preview_state,
|
||||||
|
async_trigger,
|
||||||
|
make_test_trigger,
|
||||||
|
setup_and_test_nested_unique_id,
|
||||||
|
setup_and_test_unique_id,
|
||||||
|
setup_entity,
|
||||||
|
)
|
||||||
|
|
||||||
from tests.common import MockConfigEntry, assert_setup_component
|
from tests.common import MockConfigEntry
|
||||||
from tests.components.vacuum import common
|
from tests.components.vacuum import common
|
||||||
from tests.typing import WebSocketGenerator
|
from tests.typing import WebSocketGenerator
|
||||||
|
|
||||||
TEST_OBJECT_ID = "test_vacuum"
|
|
||||||
TEST_ENTITY_ID = f"vacuum.{TEST_OBJECT_ID}"
|
|
||||||
|
|
||||||
TEST_STATE_SENSOR = "sensor.test_state"
|
TEST_STATE_SENSOR = "sensor.test_state"
|
||||||
TEST_SPEED_SENSOR = "sensor.test_fan_speed"
|
TEST_SPEED_SENSOR = "sensor.test_fan_speed"
|
||||||
TEST_BATTERY_LEVEL_SENSOR = "sensor.test_battery_level"
|
TEST_BATTERY_LEVEL_SENSOR = "sensor.test_battery_level"
|
||||||
TEST_AVAILABILITY_ENTITY = "availability_state.state"
|
TEST_AVAILABILITY_ENTITY = "availability_state.state"
|
||||||
|
|
||||||
TEST_STATE_TRIGGER = {
|
TEST_VACUUM = TemplatePlatformSetup(
|
||||||
"trigger": {
|
vacuum.DOMAIN,
|
||||||
"trigger": "state",
|
"vacuums",
|
||||||
"entity_id": [
|
"test_vacuum",
|
||||||
|
make_test_trigger(
|
||||||
TEST_STATE_SENSOR,
|
TEST_STATE_SENSOR,
|
||||||
TEST_SPEED_SENSOR,
|
TEST_SPEED_SENSOR,
|
||||||
TEST_BATTERY_LEVEL_SENSOR,
|
TEST_BATTERY_LEVEL_SENSOR,
|
||||||
TEST_AVAILABILITY_ENTITY,
|
TEST_AVAILABILITY_ENTITY,
|
||||||
],
|
),
|
||||||
},
|
)
|
||||||
"variables": {"triggering_entity": "{{ trigger.entity_id }}"},
|
|
||||||
"action": [
|
|
||||||
{"event": "action_event", "event_data": {"what": "{{ triggering_entity }}"}}
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
||||||
START_ACTION = {
|
START_ACTION = {
|
||||||
"start": {
|
"start": {
|
||||||
@@ -114,70 +116,16 @@ def _verify(
|
|||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
expected_state: str,
|
expected_state: str,
|
||||||
expected_battery_level: int | None = None,
|
expected_battery_level: int | None = None,
|
||||||
expected_fan_speed: int | None = None,
|
expected_fan_speed: str | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Verify vacuum's state and speed."""
|
"""Verify vacuum's state and speed."""
|
||||||
state = hass.states.get(TEST_ENTITY_ID)
|
state = hass.states.get(TEST_VACUUM.entity_id)
|
||||||
attributes = state.attributes
|
attributes = state.attributes
|
||||||
assert state.state == expected_state
|
assert state.state == expected_state
|
||||||
assert attributes.get(ATTR_BATTERY_LEVEL) == expected_battery_level
|
assert attributes.get(ATTR_BATTERY_LEVEL) == expected_battery_level
|
||||||
assert attributes.get(ATTR_FAN_SPEED) == expected_fan_speed
|
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()
|
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_trigger_format(
|
|
||||||
hass: HomeAssistant, count: int, vacuum_config: dict[str, Any]
|
|
||||||
) -> None:
|
|
||||||
"""Do setup of vacuum integration via trigger format."""
|
|
||||||
config = {"template": {"vacuum": vacuum_config, **TEST_STATE_TRIGGER}}
|
|
||||||
|
|
||||||
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
|
@pytest.fixture
|
||||||
async def setup_vacuum(
|
async def setup_vacuum(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
@@ -186,12 +134,7 @@ async def setup_vacuum(
|
|||||||
vacuum_config: dict[str, Any],
|
vacuum_config: dict[str, Any],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Do setup of number integration."""
|
"""Do setup of number integration."""
|
||||||
if style == ConfigurationStyle.LEGACY:
|
await setup_entity(hass, TEST_VACUUM, style, count, vacuum_config)
|
||||||
await async_setup_legacy_format(hass, count, vacuum_config)
|
|
||||||
elif style == ConfigurationStyle.MODERN:
|
|
||||||
await async_setup_modern_format(hass, count, vacuum_config)
|
|
||||||
elif style == ConfigurationStyle.TRIGGER:
|
|
||||||
await async_setup_trigger_format(hass, count, vacuum_config)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
@@ -203,17 +146,8 @@ async def setup_test_vacuum_with_extra_config(
|
|||||||
extra_config: dict[str, Any],
|
extra_config: dict[str, Any],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Do setup of number integration."""
|
"""Do setup of number integration."""
|
||||||
if style == ConfigurationStyle.LEGACY:
|
await setup_entity(
|
||||||
await async_setup_legacy_format(
|
hass, TEST_VACUUM, style, count, vacuum_config, extra_config=extra_config
|
||||||
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}
|
|
||||||
)
|
|
||||||
elif style == ConfigurationStyle.TRIGGER:
|
|
||||||
await async_setup_trigger_format(
|
|
||||||
hass, count, {"name": TEST_OBJECT_ID, **vacuum_config, **extra_config}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -225,36 +159,8 @@ async def setup_state_vacuum(
|
|||||||
state_template: str,
|
state_template: str,
|
||||||
):
|
):
|
||||||
"""Do setup of vacuum integration using a state template."""
|
"""Do setup of vacuum integration using a state template."""
|
||||||
if style == ConfigurationStyle.LEGACY:
|
await setup_entity(
|
||||||
await async_setup_legacy_format(
|
hass, TEST_VACUUM, style, count, TEMPLATE_VACUUM_ACTIONS, state_template
|
||||||
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,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
elif style == ConfigurationStyle.TRIGGER:
|
|
||||||
await async_setup_trigger_format(
|
|
||||||
hass,
|
|
||||||
count,
|
|
||||||
{
|
|
||||||
"name": TEST_OBJECT_ID,
|
|
||||||
"state": state_template,
|
|
||||||
**TEMPLATE_VACUUM_ACTIONS,
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -267,40 +173,7 @@ async def setup_base_vacuum(
|
|||||||
extra_config: dict,
|
extra_config: dict,
|
||||||
):
|
):
|
||||||
"""Do setup of vacuum integration using a state template."""
|
"""Do setup of vacuum integration using a state template."""
|
||||||
if style == ConfigurationStyle.LEGACY:
|
await setup_entity(hass, TEST_VACUUM, style, count, extra_config, state_template)
|
||||||
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,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
elif style == ConfigurationStyle.TRIGGER:
|
|
||||||
state_config = {"state": state_template} if state_template else {}
|
|
||||||
await async_setup_trigger_format(
|
|
||||||
hass,
|
|
||||||
count,
|
|
||||||
{
|
|
||||||
"name": TEST_OBJECT_ID,
|
|
||||||
**state_config,
|
|
||||||
**extra_config,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
@@ -314,46 +187,15 @@ async def setup_single_attribute_state_vacuum(
|
|||||||
extra_config: dict,
|
extra_config: dict,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Do setup of vacuum integration testing a single attribute."""
|
"""Do setup of vacuum integration testing a single attribute."""
|
||||||
extra = {attribute: attribute_template} if attribute and attribute_template else {}
|
config = {attribute: attribute_template} if attribute and attribute_template else {}
|
||||||
if style == ConfigurationStyle.LEGACY:
|
await setup_entity(
|
||||||
state_config = {"value_template": state_template} if state_template else {}
|
|
||||||
await async_setup_legacy_format(
|
|
||||||
hass,
|
hass,
|
||||||
|
TEST_VACUUM,
|
||||||
|
style,
|
||||||
count,
|
count,
|
||||||
{
|
{**config, **TEMPLATE_VACUUM_ACTIONS},
|
||||||
TEST_OBJECT_ID: {
|
state_template,
|
||||||
**state_config,
|
extra_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,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
elif style == ConfigurationStyle.TRIGGER:
|
|
||||||
state_config = {"state": state_template} if state_template else {}
|
|
||||||
await async_setup_trigger_format(
|
|
||||||
hass,
|
|
||||||
count,
|
|
||||||
{
|
|
||||||
"name": TEST_OBJECT_ID,
|
|
||||||
**state_config,
|
|
||||||
**TEMPLATE_VACUUM_ACTIONS,
|
|
||||||
**extra,
|
|
||||||
**extra_config,
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -366,42 +208,14 @@ async def setup_attributes_state_vacuum(
|
|||||||
attributes: dict,
|
attributes: dict,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Do setup of vacuum integration testing a single attribute."""
|
"""Do setup of vacuum integration testing a single attribute."""
|
||||||
if style == ConfigurationStyle.LEGACY:
|
await setup_entity(
|
||||||
state_config = {"value_template": state_template} if state_template else {}
|
|
||||||
await async_setup_legacy_format(
|
|
||||||
hass,
|
hass,
|
||||||
|
TEST_VACUUM,
|
||||||
|
style,
|
||||||
count,
|
count,
|
||||||
{
|
TEMPLATE_VACUUM_ACTIONS,
|
||||||
TEST_OBJECT_ID: {
|
state_template,
|
||||||
"attribute_templates": attributes,
|
attributes=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,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
elif style == ConfigurationStyle.TRIGGER:
|
|
||||||
state_config = {"state": state_template} if state_template else {}
|
|
||||||
await async_setup_trigger_format(
|
|
||||||
hass,
|
|
||||||
count,
|
|
||||||
{
|
|
||||||
"name": TEST_OBJECT_ID,
|
|
||||||
"attributes": attributes,
|
|
||||||
**state_config,
|
|
||||||
**TEMPLATE_VACUUM_ACTIONS,
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -582,10 +396,7 @@ async def test_battery_level_template(
|
|||||||
hass: HomeAssistant, expected: int | None
|
hass: HomeAssistant, expected: int | None
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test templates with values from other entities."""
|
"""Test templates with values from other entities."""
|
||||||
# Ensure trigger entity templates are rendered
|
await async_trigger(hass, TEST_STATE_SENSOR)
|
||||||
hass.states.async_set(TEST_STATE_SENSOR, None)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
|
|
||||||
_verify(hass, STATE_UNKNOWN, expected)
|
_verify(hass, STATE_UNKNOWN, expected)
|
||||||
|
|
||||||
|
|
||||||
@@ -609,18 +420,16 @@ async def test_battery_level_template_repair(
|
|||||||
caplog: pytest.LogCaptureFixture,
|
caplog: pytest.LogCaptureFixture,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test battery_level template raises issue."""
|
"""Test battery_level template raises issue."""
|
||||||
# Ensure trigger entity templates are rendered
|
await async_trigger(hass, TEST_STATE_SENSOR, VacuumActivity.DOCKED)
|
||||||
hass.states.async_set(TEST_STATE_SENSOR, VacuumActivity.DOCKED)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
|
|
||||||
assert len(issue_registry.issues) == issue_count
|
assert len(issue_registry.issues) == issue_count
|
||||||
issue = issue_registry.async_get_issue(
|
issue = issue_registry.async_get_issue(
|
||||||
"template", f"deprecated_battery_level_{TEST_ENTITY_ID}"
|
"template", f"deprecated_battery_level_{TEST_VACUUM.entity_id}"
|
||||||
)
|
)
|
||||||
assert issue.domain == "template"
|
assert issue.domain == "template"
|
||||||
assert issue.severity == ir.IssueSeverity.WARNING
|
assert issue.severity == ir.IssueSeverity.WARNING
|
||||||
assert issue.translation_placeholders["entity_name"] == TEST_OBJECT_ID
|
assert issue.translation_placeholders["entity_name"] == TEST_VACUUM.object_id
|
||||||
assert issue.translation_placeholders["entity_id"] == TEST_ENTITY_ID
|
assert issue.translation_placeholders["entity_id"] == TEST_VACUUM.entity_id
|
||||||
assert "Detected that integration 'template' is setting the" not in caplog.text
|
assert "Detected that integration 'template' is setting the" not in caplog.text
|
||||||
|
|
||||||
|
|
||||||
@@ -656,10 +465,7 @@ async def test_battery_level_template_repair(
|
|||||||
@pytest.mark.usefixtures("setup_single_attribute_state_vacuum")
|
@pytest.mark.usefixtures("setup_single_attribute_state_vacuum")
|
||||||
async def test_fan_speed_template(hass: HomeAssistant, expected: str | None) -> None:
|
async def test_fan_speed_template(hass: HomeAssistant, expected: str | None) -> None:
|
||||||
"""Test templates with values from other entities."""
|
"""Test templates with values from other entities."""
|
||||||
# Ensure trigger entity templates are rendered
|
await async_trigger(hass, TEST_STATE_SENSOR)
|
||||||
hass.states.async_set(TEST_STATE_SENSOR, None)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
|
|
||||||
_verify(hass, STATE_UNKNOWN, None, expected)
|
_verify(hass, STATE_UNKNOWN, None, expected)
|
||||||
|
|
||||||
|
|
||||||
@@ -685,13 +491,13 @@ async def test_fan_speed_template(hass: HomeAssistant, expected: str | None) ->
|
|||||||
@pytest.mark.usefixtures("setup_single_attribute_state_vacuum")
|
@pytest.mark.usefixtures("setup_single_attribute_state_vacuum")
|
||||||
async def test_icon_template(hass: HomeAssistant, expected: int) -> None:
|
async def test_icon_template(hass: HomeAssistant, expected: int) -> None:
|
||||||
"""Test icon template."""
|
"""Test icon template."""
|
||||||
state = hass.states.get(TEST_ENTITY_ID)
|
state = hass.states.get(TEST_VACUUM.entity_id)
|
||||||
assert state.attributes.get("icon") == expected
|
assert state.attributes.get("icon") == expected
|
||||||
|
|
||||||
hass.states.async_set(TEST_STATE_SENSOR, STATE_ON)
|
hass.states.async_set(TEST_STATE_SENSOR, STATE_ON)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
state = hass.states.get(TEST_ENTITY_ID)
|
state = hass.states.get(TEST_VACUUM.entity_id)
|
||||||
assert state.attributes["icon"] == "mdi:check"
|
assert state.attributes["icon"] == "mdi:check"
|
||||||
|
|
||||||
|
|
||||||
@@ -717,13 +523,13 @@ async def test_icon_template(hass: HomeAssistant, expected: int) -> None:
|
|||||||
@pytest.mark.usefixtures("setup_single_attribute_state_vacuum")
|
@pytest.mark.usefixtures("setup_single_attribute_state_vacuum")
|
||||||
async def test_picture_template(hass: HomeAssistant, expected: int) -> None:
|
async def test_picture_template(hass: HomeAssistant, expected: int) -> None:
|
||||||
"""Test picture template."""
|
"""Test picture template."""
|
||||||
state = hass.states.get(TEST_ENTITY_ID)
|
state = hass.states.get(TEST_VACUUM.entity_id)
|
||||||
assert state.attributes.get("entity_picture") == expected
|
assert state.attributes.get("entity_picture") == expected
|
||||||
|
|
||||||
hass.states.async_set(TEST_STATE_SENSOR, STATE_ON)
|
hass.states.async_set(TEST_STATE_SENSOR, STATE_ON)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
state = hass.states.get(TEST_ENTITY_ID)
|
state = hass.states.get(TEST_VACUUM.entity_id)
|
||||||
assert state.attributes["entity_picture"] == "local/vacuum.png"
|
assert state.attributes["entity_picture"] == "local/vacuum.png"
|
||||||
|
|
||||||
|
|
||||||
@@ -755,14 +561,14 @@ async def test_available_template_with_entities(hass: HomeAssistant) -> None:
|
|||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
# Device State should not be unavailable
|
# Device State should not be unavailable
|
||||||
assert hass.states.get(TEST_ENTITY_ID).state != STATE_UNAVAILABLE
|
assert hass.states.get(TEST_VACUUM.entity_id).state != STATE_UNAVAILABLE
|
||||||
|
|
||||||
# When Availability template returns false
|
# When Availability template returns false
|
||||||
hass.states.async_set(TEST_AVAILABILITY_ENTITY, STATE_OFF)
|
hass.states.async_set(TEST_AVAILABILITY_ENTITY, STATE_OFF)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
# device state should be unavailable
|
# device state should be unavailable
|
||||||
assert hass.states.get(TEST_ENTITY_ID).state == STATE_UNAVAILABLE
|
assert hass.states.get(TEST_VACUUM.entity_id).state == STATE_UNAVAILABLE
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("extra_config", [{}])
|
@pytest.mark.parametrize("extra_config", [{}])
|
||||||
@@ -789,12 +595,8 @@ async def test_invalid_availability_template_keeps_component_available(
|
|||||||
hass: HomeAssistant, caplog_setup_text, caplog: pytest.LogCaptureFixture
|
hass: HomeAssistant, caplog_setup_text, caplog: pytest.LogCaptureFixture
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test that an invalid availability keeps the device available."""
|
"""Test that an invalid availability keeps the device available."""
|
||||||
|
await async_trigger(hass, TEST_STATE_SENSOR)
|
||||||
# Ensure state change triggers trigger entity.
|
assert hass.states.get(TEST_VACUUM.entity_id) != STATE_UNAVAILABLE
|
||||||
hass.states.async_set(TEST_STATE_SENSOR, None)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
|
|
||||||
assert hass.states.get(TEST_ENTITY_ID) != STATE_UNAVAILABLE
|
|
||||||
err = "'x' is undefined"
|
err = "'x' is undefined"
|
||||||
assert err in caplog_setup_text or err in caplog.text
|
assert err in caplog_setup_text or err in caplog.text
|
||||||
|
|
||||||
@@ -815,13 +617,13 @@ async def test_invalid_availability_template_keeps_component_available(
|
|||||||
@pytest.mark.usefixtures("setup_attributes_state_vacuum")
|
@pytest.mark.usefixtures("setup_attributes_state_vacuum")
|
||||||
async def test_attribute_templates(hass: HomeAssistant) -> None:
|
async def test_attribute_templates(hass: HomeAssistant) -> None:
|
||||||
"""Test attribute_templates template."""
|
"""Test attribute_templates template."""
|
||||||
state = hass.states.get(TEST_ENTITY_ID)
|
state = hass.states.get(TEST_VACUUM.entity_id)
|
||||||
assert state.attributes["test_attribute"] == "It ."
|
assert state.attributes["test_attribute"] == "It ."
|
||||||
|
|
||||||
hass.states.async_set(TEST_STATE_SENSOR, "Works")
|
hass.states.async_set(TEST_STATE_SENSOR, "Works")
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
await async_update_entity(hass, TEST_ENTITY_ID)
|
await async_update_entity(hass, TEST_VACUUM.entity_id)
|
||||||
state = hass.states.get(TEST_ENTITY_ID)
|
state = hass.states.get(TEST_VACUUM.entity_id)
|
||||||
assert state.attributes["test_attribute"] == "It Works."
|
assert state.attributes["test_attribute"] == "It Works."
|
||||||
|
|
||||||
|
|
||||||
@@ -853,59 +655,32 @@ async def test_invalid_attribute_template(
|
|||||||
assert err in caplog_setup_text or err in caplog.text
|
assert err in caplog_setup_text or err in caplog.text
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("count", [1])
|
@pytest.mark.parametrize("config", [TEMPLATE_VACUUM_ACTIONS])
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("style", "vacuum_config"),
|
"style",
|
||||||
[
|
[ConfigurationStyle.LEGACY, ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER],
|
||||||
(
|
|
||||||
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,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
),
|
|
||||||
(
|
|
||||||
ConfigurationStyle.TRIGGER,
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"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(
|
||||||
async def test_unique_id(hass: HomeAssistant) -> None:
|
hass: HomeAssistant, style: ConfigurationStyle, config: ConfigType
|
||||||
|
) -> None:
|
||||||
"""Test unique_id option only creates one vacuum per id."""
|
"""Test unique_id option only creates one vacuum per id."""
|
||||||
assert len(hass.states.async_all("vacuum")) == 1
|
await setup_and_test_unique_id(hass, TEST_VACUUM, style, config)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("config", [TEMPLATE_VACUUM_ACTIONS])
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"style", [ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER]
|
||||||
|
)
|
||||||
|
async def test_nested_unique_id(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
style: ConfigurationStyle,
|
||||||
|
config: ConfigType,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
) -> None:
|
||||||
|
"""Test a template unique_id propagates to vacuum unique_ids."""
|
||||||
|
await setup_and_test_nested_unique_id(
|
||||||
|
hass, TEST_VACUUM, style, entity_registry, config
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
@@ -920,32 +695,32 @@ async def test_unused_services(hass: HomeAssistant) -> None:
|
|||||||
"""Test calling unused services raises."""
|
"""Test calling unused services raises."""
|
||||||
# Pause vacuum
|
# Pause vacuum
|
||||||
with pytest.raises(HomeAssistantError):
|
with pytest.raises(HomeAssistantError):
|
||||||
await common.async_pause(hass, TEST_ENTITY_ID)
|
await common.async_pause(hass, TEST_VACUUM.entity_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
# Stop vacuum
|
# Stop vacuum
|
||||||
with pytest.raises(HomeAssistantError):
|
with pytest.raises(HomeAssistantError):
|
||||||
await common.async_stop(hass, TEST_ENTITY_ID)
|
await common.async_stop(hass, TEST_VACUUM.entity_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
# Return vacuum to base
|
# Return vacuum to base
|
||||||
with pytest.raises(HomeAssistantError):
|
with pytest.raises(HomeAssistantError):
|
||||||
await common.async_return_to_base(hass, TEST_ENTITY_ID)
|
await common.async_return_to_base(hass, TEST_VACUUM.entity_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
# Spot cleaning
|
# Spot cleaning
|
||||||
with pytest.raises(HomeAssistantError):
|
with pytest.raises(HomeAssistantError):
|
||||||
await common.async_clean_spot(hass, TEST_ENTITY_ID)
|
await common.async_clean_spot(hass, TEST_VACUUM.entity_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
# Locate vacuum
|
# Locate vacuum
|
||||||
with pytest.raises(HomeAssistantError):
|
with pytest.raises(HomeAssistantError):
|
||||||
await common.async_locate(hass, TEST_ENTITY_ID)
|
await common.async_locate(hass, TEST_VACUUM.entity_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
# Set fan's speed
|
# Set fan's speed
|
||||||
with pytest.raises(HomeAssistantError):
|
with pytest.raises(HomeAssistantError):
|
||||||
await common.async_set_fan_speed(hass, "medium", TEST_ENTITY_ID)
|
await common.async_set_fan_speed(hass, "medium", TEST_VACUUM.entity_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
_verify(hass, STATE_UNKNOWN, None)
|
_verify(hass, STATE_UNKNOWN, None)
|
||||||
@@ -979,7 +754,7 @@ async def test_state_services(
|
|||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
"vacuum",
|
"vacuum",
|
||||||
action,
|
action,
|
||||||
{"entity_id": TEST_ENTITY_ID},
|
{"entity_id": TEST_VACUUM.entity_id},
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
@@ -987,7 +762,7 @@ async def test_state_services(
|
|||||||
# verify
|
# verify
|
||||||
assert len(calls) == 1
|
assert len(calls) == 1
|
||||||
assert calls[-1].data["action"] == action
|
assert calls[-1].data["action"] == action
|
||||||
assert calls[-1].data["caller"] == TEST_ENTITY_ID
|
assert calls[-1].data["caller"] == TEST_VACUUM.entity_id
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
@@ -1016,23 +791,23 @@ async def test_set_fan_speed(hass: HomeAssistant, calls: list[ServiceCall]) -> N
|
|||||||
"""Test set valid fan speed."""
|
"""Test set valid fan speed."""
|
||||||
|
|
||||||
# Set vacuum's fan speed to high
|
# Set vacuum's fan speed to high
|
||||||
await common.async_set_fan_speed(hass, "high", TEST_ENTITY_ID)
|
await common.async_set_fan_speed(hass, "high", TEST_VACUUM.entity_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
# verify
|
# verify
|
||||||
assert len(calls) == 1
|
assert len(calls) == 1
|
||||||
assert calls[-1].data["action"] == "set_fan_speed"
|
assert calls[-1].data["action"] == "set_fan_speed"
|
||||||
assert calls[-1].data["caller"] == TEST_ENTITY_ID
|
assert calls[-1].data["caller"] == TEST_VACUUM.entity_id
|
||||||
assert calls[-1].data["fan_speed"] == "high"
|
assert calls[-1].data["fan_speed"] == "high"
|
||||||
|
|
||||||
# Set fan's speed to medium
|
# Set fan's speed to medium
|
||||||
await common.async_set_fan_speed(hass, "medium", TEST_ENTITY_ID)
|
await common.async_set_fan_speed(hass, "medium", TEST_VACUUM.entity_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
# verify
|
# verify
|
||||||
assert len(calls) == 2
|
assert len(calls) == 2
|
||||||
assert calls[-1].data["action"] == "set_fan_speed"
|
assert calls[-1].data["action"] == "set_fan_speed"
|
||||||
assert calls[-1].data["caller"] == TEST_ENTITY_ID
|
assert calls[-1].data["caller"] == TEST_VACUUM.entity_id
|
||||||
assert calls[-1].data["fan_speed"] == "medium"
|
assert calls[-1].data["fan_speed"] == "medium"
|
||||||
|
|
||||||
|
|
||||||
@@ -1069,68 +844,26 @@ async def test_set_invalid_fan_speed(
|
|||||||
"""Test set invalid fan speed when fan has valid speed."""
|
"""Test set invalid fan speed when fan has valid speed."""
|
||||||
|
|
||||||
# Set vacuum's fan speed to high
|
# Set vacuum's fan speed to high
|
||||||
await common.async_set_fan_speed(hass, "high", TEST_ENTITY_ID)
|
await common.async_set_fan_speed(hass, "high", TEST_VACUUM.entity_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
# verify
|
# verify
|
||||||
assert len(calls) == 1
|
assert len(calls) == 1
|
||||||
assert calls[-1].data["action"] == "set_fan_speed"
|
assert calls[-1].data["action"] == "set_fan_speed"
|
||||||
assert calls[-1].data["caller"] == TEST_ENTITY_ID
|
assert calls[-1].data["caller"] == TEST_VACUUM.entity_id
|
||||||
assert calls[-1].data["fan_speed"] == "high"
|
assert calls[-1].data["fan_speed"] == "high"
|
||||||
|
|
||||||
# Set vacuum's fan speed to 'invalid'
|
# Set vacuum's fan speed to 'invalid'
|
||||||
await common.async_set_fan_speed(hass, "invalid", TEST_ENTITY_ID)
|
await common.async_set_fan_speed(hass, "invalid", TEST_VACUUM.entity_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
# verify fan speed is unchanged
|
# verify fan speed is unchanged
|
||||||
assert len(calls) == 1
|
assert len(calls) == 1
|
||||||
assert calls[-1].data["action"] == "set_fan_speed"
|
assert calls[-1].data["action"] == "set_fan_speed"
|
||||||
assert calls[-1].data["caller"] == TEST_ENTITY_ID
|
assert calls[-1].data["caller"] == TEST_VACUUM.entity_id
|
||||||
assert calls[-1].data["fan_speed"] == "high"
|
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(("count", "vacuum_config"), [(1, {"start": []})])
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"style",
|
"style",
|
||||||
@@ -1177,16 +910,16 @@ async def test_nested_unique_id(
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@pytest.mark.usefixtures("setup_test_vacuum_with_extra_config")
|
||||||
async def test_empty_action_config(
|
async def test_empty_action_config(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
supported_features: VacuumEntityFeature,
|
supported_features: VacuumEntityFeature,
|
||||||
setup_test_vacuum_with_extra_config,
|
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test configuration with empty script."""
|
"""Test configuration with empty script."""
|
||||||
await common.async_start(hass, TEST_ENTITY_ID)
|
await common.async_start(hass, TEST_VACUUM.entity_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
state = hass.states.get(TEST_ENTITY_ID)
|
state = hass.states.get(TEST_VACUUM.entity_id)
|
||||||
assert state.attributes["supported_features"] == (
|
assert state.attributes["supported_features"] == (
|
||||||
VacuumEntityFeature.STATE | VacuumEntityFeature.START | supported_features
|
VacuumEntityFeature.STATE | VacuumEntityFeature.START | supported_features
|
||||||
)
|
)
|
||||||
@@ -1197,7 +930,7 @@ async def test_empty_action_config(
|
|||||||
[
|
[
|
||||||
(
|
(
|
||||||
1,
|
1,
|
||||||
{"name": TEST_OBJECT_ID, "start": [], **TEMPLATE_VACUUM_ACTIONS},
|
{"name": TEST_VACUUM.object_id, "start": [], **TEMPLATE_VACUUM_ACTIONS},
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@@ -1227,12 +960,12 @@ async def test_assumed_optimistic(
|
|||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
vacuum.DOMAIN,
|
vacuum.DOMAIN,
|
||||||
service,
|
service,
|
||||||
{"entity_id": TEST_ENTITY_ID},
|
{"entity_id": TEST_VACUUM.entity_id},
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
state = hass.states.get(TEST_ENTITY_ID)
|
state = hass.states.get(TEST_VACUUM.entity_id)
|
||||||
assert state.state == expected
|
assert state.state == expected
|
||||||
|
|
||||||
|
|
||||||
@@ -1242,7 +975,7 @@ async def test_assumed_optimistic(
|
|||||||
(
|
(
|
||||||
1,
|
1,
|
||||||
{
|
{
|
||||||
"name": TEST_OBJECT_ID,
|
"name": TEST_VACUUM.object_id,
|
||||||
"state": "{{ states('sensor.test_state') }}",
|
"state": "{{ states('sensor.test_state') }}",
|
||||||
"start": [],
|
"start": [],
|
||||||
**TEMPLATE_VACUUM_ACTIONS,
|
**TEMPLATE_VACUUM_ACTIONS,
|
||||||
@@ -1276,18 +1009,18 @@ async def test_optimistic_option(
|
|||||||
hass.states.async_set(TEST_STATE_SENSOR, VacuumActivity.DOCKED)
|
hass.states.async_set(TEST_STATE_SENSOR, VacuumActivity.DOCKED)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
state = hass.states.get(TEST_ENTITY_ID)
|
state = hass.states.get(TEST_VACUUM.entity_id)
|
||||||
assert state.state == VacuumActivity.DOCKED
|
assert state.state == VacuumActivity.DOCKED
|
||||||
|
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
vacuum.DOMAIN,
|
vacuum.DOMAIN,
|
||||||
service,
|
service,
|
||||||
{"entity_id": TEST_ENTITY_ID},
|
{"entity_id": TEST_VACUUM.entity_id},
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
state = hass.states.get(TEST_ENTITY_ID)
|
state = hass.states.get(TEST_VACUUM.entity_id)
|
||||||
assert state.state == expected
|
assert state.state == expected
|
||||||
|
|
||||||
hass.states.async_set(TEST_STATE_SENSOR, VacuumActivity.RETURNING)
|
hass.states.async_set(TEST_STATE_SENSOR, VacuumActivity.RETURNING)
|
||||||
@@ -1296,7 +1029,7 @@ async def test_optimistic_option(
|
|||||||
hass.states.async_set(TEST_STATE_SENSOR, VacuumActivity.DOCKED)
|
hass.states.async_set(TEST_STATE_SENSOR, VacuumActivity.DOCKED)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
state = hass.states.get(TEST_ENTITY_ID)
|
state = hass.states.get(TEST_VACUUM.entity_id)
|
||||||
assert state.state == VacuumActivity.DOCKED
|
assert state.state == VacuumActivity.DOCKED
|
||||||
|
|
||||||
|
|
||||||
@@ -1306,7 +1039,7 @@ async def test_optimistic_option(
|
|||||||
(
|
(
|
||||||
1,
|
1,
|
||||||
{
|
{
|
||||||
"name": TEST_OBJECT_ID,
|
"name": TEST_VACUUM.object_id,
|
||||||
"state": "{{ states('sensor.test_state') }}",
|
"state": "{{ states('sensor.test_state') }}",
|
||||||
"start": [],
|
"start": [],
|
||||||
**TEMPLATE_VACUUM_ACTIONS,
|
**TEMPLATE_VACUUM_ACTIONS,
|
||||||
@@ -1339,12 +1072,12 @@ async def test_not_optimistic(
|
|||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
vacuum.DOMAIN,
|
vacuum.DOMAIN,
|
||||||
service,
|
service,
|
||||||
{"entity_id": TEST_ENTITY_ID},
|
{"entity_id": TEST_VACUUM.entity_id},
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
state = hass.states.get(TEST_ENTITY_ID)
|
state = hass.states.get(TEST_VACUUM.entity_id)
|
||||||
assert state.state == STATE_UNKNOWN
|
assert state.state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user