Skip to content

Commit f786ec1

Browse files
authored
Add common template test framework to vacuum platform (home-assistant#157846)
1 parent ef0add1 commit f786ec1

File tree

2 files changed

+310
-401
lines changed

2 files changed

+310
-401
lines changed

tests/components/template/conftest.py

Lines changed: 187 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""template conftest."""
22

3+
from dataclasses import dataclass
34
from enum import Enum
45

56
import pytest
@@ -8,6 +9,7 @@
89
from homeassistant.config_entries import SOURCE_USER
910
from homeassistant.core import HomeAssistant, ServiceCall
1011
from homeassistant.data_entry_flow import FlowResultType
12+
from homeassistant.helpers import entity_registry as er
1113
from homeassistant.helpers.typing import ConfigType
1214
from homeassistant.setup import async_setup_component
1315

@@ -40,19 +42,37 @@ def make_test_trigger(*entities: str) -> dict:
4042
}
4143

4244

45+
async def async_trigger(
46+
hass: HomeAssistant, entity_id: str, state: str | None = None
47+
) -> None:
48+
"""Trigger a state change."""
49+
hass.states.async_set(entity_id, state)
50+
await hass.async_block_till_done()
51+
52+
4353
async def async_setup_legacy_platforms(
4454
hass: HomeAssistant,
4555
domain: str,
46-
slug: str,
56+
slug: str | None,
4757
count: int,
48-
config: ConfigType,
58+
config: ConfigType | list[ConfigType],
4959
) -> None:
5060
"""Do setup of any legacy platform that supports a keyed dictionary of template entities."""
61+
if slug is None:
62+
# Lock and Weather platforms do not use a slug
63+
if isinstance(config, list):
64+
config = {domain: [{"platform": "template", **item} for item in config]}
65+
else:
66+
config = {domain: {"platform": "template", **config}}
67+
else:
68+
assert isinstance(config, dict)
69+
config = {domain: {"platform": "template", slug: config}}
70+
5171
with assert_setup_component(count, domain):
5272
assert await async_setup_component(
5373
hass,
5474
domain,
55-
{domain: {"platform": "template", slug: config}},
75+
config,
5676
)
5777

5878
await hass.async_block_till_done()
@@ -64,16 +84,15 @@ async def async_setup_modern_state_format(
6484
hass: HomeAssistant,
6585
domain: str,
6686
count: int,
67-
config: ConfigType,
68-
extra_config: ConfigType | None = None,
87+
config: ConfigType | list[ConfigType],
88+
extra_section_config: ConfigType | None = None,
6989
) -> None:
7090
"""Do setup of template integration via modern format."""
71-
extra = extra_config or {}
7291
with assert_setup_component(count, template.DOMAIN):
7392
assert await async_setup_component(
7493
hass,
7594
template.DOMAIN,
76-
{"template": {domain: config, **extra}},
95+
{"template": {domain: config, **(extra_section_config or {})}},
7796
)
7897

7998
await hass.async_block_till_done()
@@ -86,12 +105,11 @@ async def async_setup_modern_trigger_format(
86105
domain: str,
87106
trigger: dict,
88107
count: int,
89-
config: ConfigType,
90-
extra_config: ConfigType | None = None,
108+
config: ConfigType | list[ConfigType],
109+
extra_section_config: ConfigType | None = None,
91110
) -> None:
92111
"""Do setup of template integration via trigger format."""
93-
extra = extra_config or {}
94-
config = {"template": {domain: config, **trigger, **extra}}
112+
config = {"template": {domain: config, **trigger, **(extra_section_config or {})}}
95113

96114
with assert_setup_component(count, template.DOMAIN):
97115
assert await async_setup_component(
@@ -105,6 +123,164 @@ async def async_setup_modern_trigger_format(
105123
await hass.async_block_till_done()
106124

107125

126+
@dataclass(frozen=True)
127+
class TemplatePlatformSetup:
128+
"""Template Platform Setup Information."""
129+
130+
domain: str
131+
legacy_slug: str | None
132+
object_id: str
133+
trigger: ConfigType
134+
135+
@property
136+
def entity_id(self) -> str:
137+
"""Return test entity ID."""
138+
return f"{self.domain}.{self.object_id}"
139+
140+
141+
async def setup_entity(
142+
hass: HomeAssistant,
143+
platform_setup: TemplatePlatformSetup,
144+
style: ConfigurationStyle,
145+
count: int,
146+
config: ConfigType,
147+
state_template: str | None = None,
148+
extra_config: ConfigType | None = None,
149+
attributes: ConfigType | None = None,
150+
extra_section_config: ConfigType | None = None,
151+
) -> None:
152+
"""Do setup of a template entity based on the configuration style."""
153+
if style == ConfigurationStyle.LEGACY:
154+
await async_setup_legacy_platforms(
155+
hass,
156+
platform_setup.domain,
157+
platform_setup.legacy_slug,
158+
count,
159+
{
160+
platform_setup.object_id: {
161+
**({"value_template": state_template} if state_template else {}),
162+
**config,
163+
**(extra_config or {}),
164+
**({"attribute_templates": attributes} if attributes else {}),
165+
}
166+
},
167+
)
168+
return
169+
170+
entity_config = {
171+
"name": platform_setup.object_id,
172+
**({"state": state_template} if state_template else {}),
173+
**config,
174+
**({"attributes": attributes} if attributes else {}),
175+
**(extra_config or {}),
176+
}
177+
if style == ConfigurationStyle.MODERN:
178+
await async_setup_modern_state_format(
179+
hass, platform_setup.domain, count, entity_config, extra_section_config
180+
)
181+
elif style == ConfigurationStyle.TRIGGER:
182+
await async_setup_modern_trigger_format(
183+
hass,
184+
platform_setup.domain,
185+
platform_setup.trigger,
186+
count,
187+
entity_config,
188+
extra_section_config,
189+
)
190+
191+
192+
async def setup_and_test_unique_id(
193+
hass: HomeAssistant,
194+
platform_setup: TemplatePlatformSetup,
195+
style: ConfigurationStyle,
196+
entity_config: ConfigType | None,
197+
) -> None:
198+
"""Setup 2 entities with the same unique_id and verify only 1 entity is created.
199+
200+
The entity_config not provide name or unique_id, those are added automatically.
201+
"""
202+
entity_config = {"unique_id": "not-so_-unique-anymore", **(entity_config or {})}
203+
if style == ConfigurationStyle.LEGACY:
204+
if platform_setup.legacy_slug is None:
205+
config = [
206+
{"name": "template_entity_1", **entity_config},
207+
{"name": "template_entity_2", **entity_config},
208+
]
209+
else:
210+
config = {
211+
"template_entity_1": entity_config,
212+
"template_entity_2": entity_config,
213+
}
214+
await async_setup_legacy_platforms(
215+
hass, platform_setup.domain, platform_setup.legacy_slug, 1, config
216+
)
217+
elif style == ConfigurationStyle.MODERN:
218+
await async_setup_modern_state_format(
219+
hass,
220+
platform_setup.domain,
221+
1,
222+
[
223+
{"name": "template_entity_1", **entity_config},
224+
{"name": "template_entity_2", **entity_config},
225+
],
226+
)
227+
elif style == ConfigurationStyle.TRIGGER:
228+
await async_setup_modern_trigger_format(
229+
hass,
230+
platform_setup.domain,
231+
platform_setup.trigger,
232+
1,
233+
[
234+
{"name": "template_entity_1", **entity_config},
235+
{"name": "template_entity_2", **entity_config},
236+
],
237+
)
238+
239+
assert len(hass.states.async_all(platform_setup.domain)) == 1
240+
241+
242+
async def setup_and_test_nested_unique_id(
243+
hass: HomeAssistant,
244+
platform_setup: TemplatePlatformSetup,
245+
style: ConfigurationStyle,
246+
entity_registry: er.EntityRegistry,
247+
entity_config: ConfigType | None,
248+
) -> None:
249+
"""Setup 2 entities with unique unique_ids in a template section that contains a unique_id.
250+
251+
The test will verify that 2 entities are created where the unique_id appends the
252+
section unique_id to each entity unique_id.
253+
254+
The entity_config should not provide name or unique_id, those are added automatically.
255+
"""
256+
entities = [
257+
{"name": "test_a", "unique_id": "a", **(entity_config or {})},
258+
{"name": "test_b", "unique_id": "b", **(entity_config or {})},
259+
]
260+
extra_section_config = {"unique_id": "x"}
261+
if style == ConfigurationStyle.MODERN:
262+
await async_setup_modern_state_format(
263+
hass, platform_setup.domain, 1, entities, extra_section_config
264+
)
265+
elif style == ConfigurationStyle.TRIGGER:
266+
await async_setup_modern_trigger_format(
267+
hass,
268+
platform_setup.domain,
269+
platform_setup.trigger,
270+
1,
271+
entities,
272+
extra_section_config,
273+
)
274+
275+
assert len(hass.states.async_all(platform_setup.domain)) == 2
276+
277+
entry = entity_registry.async_get(f"{platform_setup.domain}.test_a")
278+
assert entry.unique_id == "x-a"
279+
280+
entry = entity_registry.async_get(f"{platform_setup.domain}.test_b")
281+
assert entry.unique_id == "x-b"
282+
283+
108284
@pytest.fixture
109285
def calls(hass: HomeAssistant) -> list[ServiceCall]:
110286
"""Track calls to a mock service."""

0 commit comments

Comments
 (0)