Add default config if not there (#43321)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
This commit is contained in:
parent
0cf3736162
commit
b3be708db6
75 changed files with 432 additions and 21 deletions
|
@ -166,7 +166,8 @@ async def async_setup(hass, config):
|
||||||
# To register the automation blueprints
|
# To register the automation blueprints
|
||||||
async_get_blueprints(hass)
|
async_get_blueprints(hass)
|
||||||
|
|
||||||
await _async_process_config(hass, config, component)
|
if not await _async_process_config(hass, config, component):
|
||||||
|
await async_get_blueprints(hass).async_populate()
|
||||||
|
|
||||||
async def trigger_service_handler(entity, service_call):
|
async def trigger_service_handler(entity, service_call):
|
||||||
"""Handle automation triggers."""
|
"""Handle automation triggers."""
|
||||||
|
@ -487,12 +488,13 @@ async def _async_process_config(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
config: Dict[str, Any],
|
config: Dict[str, Any],
|
||||||
component: EntityComponent,
|
component: EntityComponent,
|
||||||
) -> None:
|
) -> bool:
|
||||||
"""Process config and add automations.
|
"""Process config and add automations.
|
||||||
|
|
||||||
This method is a coroutine.
|
Returns if blueprints were used.
|
||||||
"""
|
"""
|
||||||
entities = []
|
entities = []
|
||||||
|
blueprints_used = False
|
||||||
|
|
||||||
for config_key in extract_domain_configs(config, DOMAIN):
|
for config_key in extract_domain_configs(config, DOMAIN):
|
||||||
conf: List[Union[Dict[str, Any], blueprint.BlueprintInputs]] = config[ # type: ignore
|
conf: List[Union[Dict[str, Any], blueprint.BlueprintInputs]] = config[ # type: ignore
|
||||||
|
@ -501,6 +503,7 @@ async def _async_process_config(
|
||||||
|
|
||||||
for list_no, config_block in enumerate(conf):
|
for list_no, config_block in enumerate(conf):
|
||||||
if isinstance(config_block, blueprint.BlueprintInputs): # type: ignore
|
if isinstance(config_block, blueprint.BlueprintInputs): # type: ignore
|
||||||
|
blueprints_used = True
|
||||||
blueprint_inputs = config_block
|
blueprint_inputs = config_block
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -562,6 +565,8 @@ async def _async_process_config(
|
||||||
if entities:
|
if entities:
|
||||||
await component.async_add_entities(entities)
|
await component.async_add_entities(entities)
|
||||||
|
|
||||||
|
return blueprints_used
|
||||||
|
|
||||||
|
|
||||||
async def _async_process_if(hass, config, p_config):
|
async def _async_process_if(hass, config, p_config):
|
||||||
"""Process if checks."""
|
"""Process if checks."""
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
blueprint:
|
||||||
|
name: Motion-activated Light
|
||||||
|
domain: automation
|
||||||
|
source_url: https://github.com/home-assistant/core/blob/dev/homeassistant/components/automation/blueprints/motion_light.yaml
|
||||||
|
input:
|
||||||
|
motion_entity:
|
||||||
|
name: Motion Sensor
|
||||||
|
selector:
|
||||||
|
entity:
|
||||||
|
domain: binary_sensor
|
||||||
|
device_class: motion
|
||||||
|
light_entity:
|
||||||
|
name: Light
|
||||||
|
selector:
|
||||||
|
entity:
|
||||||
|
domain: light
|
||||||
|
|
||||||
|
# If motion is detected within the 120s delay,
|
||||||
|
# we restart the script.
|
||||||
|
mode: restart
|
||||||
|
max_exceeded: silent
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
platform: state
|
||||||
|
entity_id: !placeholder motion_entity
|
||||||
|
from: "off"
|
||||||
|
to: "on"
|
||||||
|
|
||||||
|
action:
|
||||||
|
- service: homeassistant.turn_on
|
||||||
|
entity_id: !placeholder light_entity
|
||||||
|
- wait_for_trigger:
|
||||||
|
platform: state
|
||||||
|
entity_id: !placeholder motion_entity
|
||||||
|
from: "on"
|
||||||
|
to: "off"
|
||||||
|
- delay: 120
|
||||||
|
- service: homeassistant.turn_off
|
||||||
|
entity_id: !placeholder light_entity
|
|
@ -0,0 +1,34 @@
|
||||||
|
blueprint:
|
||||||
|
name: Send notification when a person leaves a zone
|
||||||
|
domain: automation
|
||||||
|
source_url: https://github.com/home-assistant/core/blob/dev/homeassistant/components/automation/blueprints/notify_leaving_zone.yaml
|
||||||
|
input:
|
||||||
|
person_entity:
|
||||||
|
name: Person
|
||||||
|
selector:
|
||||||
|
entity:
|
||||||
|
domain: person
|
||||||
|
zone_entity:
|
||||||
|
name: Zone
|
||||||
|
selector:
|
||||||
|
entity:
|
||||||
|
domain: zone
|
||||||
|
notify_service:
|
||||||
|
name: The notify service to use
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
platform: state
|
||||||
|
entity_id: !placeholder person_entity
|
||||||
|
|
||||||
|
variables:
|
||||||
|
zone_entity: !placeholder zone_entity
|
||||||
|
zone_state: "{{ states[zone_entity].name }}"
|
||||||
|
|
||||||
|
condition:
|
||||||
|
condition: template
|
||||||
|
value_template: "{{ trigger.from_state.state == zone_state and trigger.to_state.state != zone_state }}"
|
||||||
|
|
||||||
|
action:
|
||||||
|
- service: !placeholder notify_service
|
||||||
|
data:
|
||||||
|
message: "{{ trigger.to_state.name }} has left {{ zone_state }}"
|
|
@ -2,14 +2,16 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
import pathlib
|
import pathlib
|
||||||
|
import shutil
|
||||||
from typing import Any, Dict, List, Optional, Union
|
from typing import Any, Dict, List, Optional, Union
|
||||||
|
|
||||||
from pkg_resources import parse_version
|
from pkg_resources import parse_version
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
from voluptuous.humanize import humanize_error
|
from voluptuous.humanize import humanize_error
|
||||||
|
|
||||||
|
from homeassistant import loader
|
||||||
from homeassistant.const import CONF_DOMAIN, CONF_NAME, CONF_PATH, __version__
|
from homeassistant.const import CONF_DOMAIN, CONF_NAME, CONF_PATH, __version__
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import DOMAIN as HA_DOMAIN, HomeAssistant, callback
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers import placeholder
|
from homeassistant.helpers import placeholder
|
||||||
from homeassistant.util import yaml
|
from homeassistant.util import yaml
|
||||||
|
@ -169,6 +171,11 @@ class DomainBlueprints:
|
||||||
|
|
||||||
hass.data.setdefault(DOMAIN, {})[domain] = self
|
hass.data.setdefault(DOMAIN, {})[domain] = self
|
||||||
|
|
||||||
|
@property
|
||||||
|
def blueprint_folder(self) -> pathlib.Path:
|
||||||
|
"""Return the blueprint folder."""
|
||||||
|
return pathlib.Path(self.hass.config.path(BLUEPRINT_FOLDER, self.domain))
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_reset_cache(self) -> None:
|
def async_reset_cache(self) -> None:
|
||||||
"""Reset the blueprint cache."""
|
"""Reset the blueprint cache."""
|
||||||
|
@ -177,9 +184,7 @@ class DomainBlueprints:
|
||||||
def _load_blueprint(self, blueprint_path) -> Blueprint:
|
def _load_blueprint(self, blueprint_path) -> Blueprint:
|
||||||
"""Load a blueprint."""
|
"""Load a blueprint."""
|
||||||
try:
|
try:
|
||||||
blueprint_data = yaml.load_yaml(
|
blueprint_data = yaml.load_yaml(self.blueprint_folder / blueprint_path)
|
||||||
self.hass.config.path(BLUEPRINT_FOLDER, self.domain, blueprint_path)
|
|
||||||
)
|
|
||||||
except (HomeAssistantError, FileNotFoundError) as err:
|
except (HomeAssistantError, FileNotFoundError) as err:
|
||||||
raise FailedToLoad(self.domain, blueprint_path, err) from err
|
raise FailedToLoad(self.domain, blueprint_path, err) from err
|
||||||
|
|
||||||
|
@ -257,10 +262,7 @@ class DomainBlueprints:
|
||||||
|
|
||||||
async def async_remove_blueprint(self, blueprint_path: str) -> None:
|
async def async_remove_blueprint(self, blueprint_path: str) -> None:
|
||||||
"""Remove a blueprint file."""
|
"""Remove a blueprint file."""
|
||||||
path = pathlib.Path(
|
path = self.blueprint_folder / blueprint_path
|
||||||
self.hass.config.path(BLUEPRINT_FOLDER, self.domain, blueprint_path)
|
|
||||||
)
|
|
||||||
|
|
||||||
await self.hass.async_add_executor_job(path.unlink)
|
await self.hass.async_add_executor_job(path.unlink)
|
||||||
self._blueprints[blueprint_path] = None
|
self._blueprints[blueprint_path] = None
|
||||||
|
|
||||||
|
@ -288,3 +290,18 @@ class DomainBlueprints:
|
||||||
)
|
)
|
||||||
|
|
||||||
self._blueprints[blueprint_path] = blueprint
|
self._blueprints[blueprint_path] = blueprint
|
||||||
|
|
||||||
|
async def async_populate(self) -> None:
|
||||||
|
"""Create folder if it doesn't exist and populate with examples."""
|
||||||
|
integration = await loader.async_get_integration(self.hass, self.domain)
|
||||||
|
|
||||||
|
def populate():
|
||||||
|
if self.blueprint_folder.exists():
|
||||||
|
return
|
||||||
|
|
||||||
|
shutil.copytree(
|
||||||
|
integration.file_path / BLUEPRINT_FOLDER,
|
||||||
|
self.blueprint_folder / HA_DOMAIN,
|
||||||
|
)
|
||||||
|
|
||||||
|
await self.hass.async_add_executor_job(populate)
|
||||||
|
|
|
@ -63,6 +63,7 @@ BLUEPRINT_SCHEMA = vol.Schema(
|
||||||
vol.Required(CONF_BLUEPRINT): vol.Schema(
|
vol.Required(CONF_BLUEPRINT): vol.Schema(
|
||||||
{
|
{
|
||||||
vol.Required(CONF_NAME): str,
|
vol.Required(CONF_NAME): str,
|
||||||
|
vol.Optional(CONF_DESCRIPTION): str,
|
||||||
vol.Required(CONF_DOMAIN): str,
|
vol.Required(CONF_DOMAIN): str,
|
||||||
vol.Optional(CONF_SOURCE_URL): cv.url,
|
vol.Optional(CONF_SOURCE_URL): cv.url,
|
||||||
vol.Optional(CONF_HOMEASSISTANT): {
|
vol.Optional(CONF_HOMEASSISTANT): {
|
||||||
|
|
|
@ -453,18 +453,12 @@ def async_template(
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""Test if template condition matches."""
|
"""Test if template condition matches."""
|
||||||
try:
|
try:
|
||||||
value = value_template.async_render(variables)
|
value: str = value_template.async_render(variables, parse_result=False)
|
||||||
except TemplateError as ex:
|
except TemplateError as ex:
|
||||||
_LOGGER.error("Error during template condition: %s", ex)
|
_LOGGER.error("Error during template condition: %s", ex)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if isinstance(value, bool):
|
return value.lower() == "true"
|
||||||
return value
|
|
||||||
|
|
||||||
if isinstance(value, str):
|
|
||||||
return value.lower() == "true"
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def async_template_from_config(
|
def async_template_from_config(
|
||||||
|
|
|
@ -23,6 +23,10 @@ def validate_selector(config: Any) -> Dict:
|
||||||
if selector_class is None:
|
if selector_class is None:
|
||||||
raise vol.Invalid(f"Unknown selector type {selector_type} found")
|
raise vol.Invalid(f"Unknown selector type {selector_type} found")
|
||||||
|
|
||||||
|
# Seletors can be empty
|
||||||
|
if config[selector_type] is None:
|
||||||
|
return {selector_type: {}}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
selector_type: cast(Dict, selector_class.CONFIG_SCHEMA(config[selector_type]))
|
selector_type: cast(Dict, selector_class.CONFIG_SCHEMA(config[selector_type]))
|
||||||
}
|
}
|
||||||
|
@ -44,6 +48,8 @@ class EntitySelector(Selector):
|
||||||
vol.Optional("integration"): str,
|
vol.Optional("integration"): str,
|
||||||
# Domain the entity belongs to
|
# Domain the entity belongs to
|
||||||
vol.Optional("domain"): str,
|
vol.Optional("domain"): str,
|
||||||
|
# Device class of the entity
|
||||||
|
vol.Optional("device_class"): str,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ from io import StringIO
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import pathlib
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
import uuid
|
import uuid
|
||||||
|
@ -704,6 +705,9 @@ def patch_yaml_files(files_dict, endswith=True):
|
||||||
def mock_open_f(fname, **_):
|
def mock_open_f(fname, **_):
|
||||||
"""Mock open() in the yaml module, used by load_yaml."""
|
"""Mock open() in the yaml module, used by load_yaml."""
|
||||||
# Return the mocked file on full match
|
# Return the mocked file on full match
|
||||||
|
if isinstance(fname, pathlib.Path):
|
||||||
|
fname = str(fname)
|
||||||
|
|
||||||
if fname in files_dict:
|
if fname in files_dict:
|
||||||
_LOGGER.debug("patch_yaml_files match %s", fname)
|
_LOGGER.debug("patch_yaml_files match %s", fname)
|
||||||
res = StringIO(files_dict[fname])
|
res = StringIO(files_dict[fname])
|
||||||
|
|
|
@ -23,6 +23,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -22,6 +22,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -22,6 +22,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -13,6 +13,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
3
tests/components/automation/conftest.py
Normal file
3
tests/components/automation/conftest.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
"""Conftest for automation tests."""
|
||||||
|
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
185
tests/components/automation/test_blueprint.py
Normal file
185
tests/components/automation/test_blueprint.py
Normal file
|
@ -0,0 +1,185 @@
|
||||||
|
"""Test built-in blueprints."""
|
||||||
|
import asyncio
|
||||||
|
import contextlib
|
||||||
|
from datetime import timedelta
|
||||||
|
import pathlib
|
||||||
|
|
||||||
|
from homeassistant.components import automation
|
||||||
|
from homeassistant.components.blueprint import models
|
||||||
|
from homeassistant.core import callback
|
||||||
|
from homeassistant.setup import async_setup_component
|
||||||
|
from homeassistant.util import dt as dt_util, yaml
|
||||||
|
|
||||||
|
from tests.async_mock import patch
|
||||||
|
from tests.common import async_fire_time_changed, async_mock_service
|
||||||
|
|
||||||
|
BUILTIN_BLUEPRINT_FOLDER = pathlib.Path(automation.__file__).parent / "blueprints"
|
||||||
|
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def patch_blueprint(blueprint_path: str, data_path):
|
||||||
|
"""Patch blueprint loading from a different source."""
|
||||||
|
orig_load = models.DomainBlueprints._load_blueprint
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def mock_load_blueprint(self, path):
|
||||||
|
if path != blueprint_path:
|
||||||
|
assert False, f"Unexpected blueprint {path}"
|
||||||
|
return orig_load(self, path)
|
||||||
|
|
||||||
|
return models.Blueprint(
|
||||||
|
yaml.load_yaml(data_path), expected_domain=self.domain, path=path
|
||||||
|
)
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.blueprint.models.DomainBlueprints._load_blueprint",
|
||||||
|
mock_load_blueprint,
|
||||||
|
):
|
||||||
|
yield
|
||||||
|
|
||||||
|
|
||||||
|
async def test_notify_leaving_zone(hass):
|
||||||
|
"""Test notifying leaving a zone blueprint."""
|
||||||
|
|
||||||
|
def set_person_state(state, extra={}):
|
||||||
|
hass.states.async_set(
|
||||||
|
"person.test_person", state, {"friendly_name": "Paulus", **extra}
|
||||||
|
)
|
||||||
|
|
||||||
|
set_person_state("School")
|
||||||
|
|
||||||
|
assert await async_setup_component(
|
||||||
|
hass, "zone", {"zone": {"name": "School", "latitude": 1, "longitude": 2}}
|
||||||
|
)
|
||||||
|
|
||||||
|
with patch_blueprint(
|
||||||
|
"notify_leaving_zone.yaml",
|
||||||
|
BUILTIN_BLUEPRINT_FOLDER / "notify_leaving_zone.yaml",
|
||||||
|
):
|
||||||
|
assert await async_setup_component(
|
||||||
|
hass,
|
||||||
|
"automation",
|
||||||
|
{
|
||||||
|
"automation": {
|
||||||
|
"use_blueprint": {
|
||||||
|
"path": "notify_leaving_zone.yaml",
|
||||||
|
"input": {
|
||||||
|
"person_entity": "person.test_person",
|
||||||
|
"zone_entity": "zone.school",
|
||||||
|
"notify_service": "notify.test_service",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
calls = async_mock_service(hass, "notify", "test_service")
|
||||||
|
|
||||||
|
# Leaving zone to no zone
|
||||||
|
set_person_state("not_home")
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert len(calls) == 1
|
||||||
|
assert calls[0].data["message"] == "Paulus has left School"
|
||||||
|
|
||||||
|
# Should not increase when we go to another zone
|
||||||
|
set_person_state("bla")
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert len(calls) == 1
|
||||||
|
|
||||||
|
# Should not increase when we go into the zone
|
||||||
|
set_person_state("School")
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert len(calls) == 1
|
||||||
|
|
||||||
|
# Should not increase when we move in the zone
|
||||||
|
set_person_state("School", {"extra_key": "triggers change with same state"})
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert len(calls) == 1
|
||||||
|
|
||||||
|
# Should increase when leaving zone for another zone
|
||||||
|
set_person_state("Just Outside School")
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert len(calls) == 2
|
||||||
|
|
||||||
|
|
||||||
|
async def test_motion_light(hass):
|
||||||
|
"""Test motion light blueprint."""
|
||||||
|
hass.states.async_set("binary_sensor.kitchen", "off")
|
||||||
|
|
||||||
|
with patch_blueprint(
|
||||||
|
"motion_light.yaml",
|
||||||
|
BUILTIN_BLUEPRINT_FOLDER / "motion_light.yaml",
|
||||||
|
):
|
||||||
|
assert await async_setup_component(
|
||||||
|
hass,
|
||||||
|
"automation",
|
||||||
|
{
|
||||||
|
"automation": {
|
||||||
|
"use_blueprint": {
|
||||||
|
"path": "motion_light.yaml",
|
||||||
|
"input": {
|
||||||
|
"light_entity": "light.kitchen",
|
||||||
|
"motion_entity": "binary_sensor.kitchen",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
turn_on_calls = async_mock_service(hass, "homeassistant", "turn_on")
|
||||||
|
turn_off_calls = async_mock_service(hass, "homeassistant", "turn_off")
|
||||||
|
|
||||||
|
# Turn on motion
|
||||||
|
hass.states.async_set("binary_sensor.kitchen", "on")
|
||||||
|
# Can't block till done because delay is active
|
||||||
|
# So wait 5 event loop iterations to process script
|
||||||
|
for _ in range(5):
|
||||||
|
await asyncio.sleep(0)
|
||||||
|
|
||||||
|
assert len(turn_on_calls) == 1
|
||||||
|
|
||||||
|
# Test light doesn't turn off if motion stays
|
||||||
|
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=200))
|
||||||
|
|
||||||
|
for _ in range(5):
|
||||||
|
await asyncio.sleep(0)
|
||||||
|
|
||||||
|
assert len(turn_off_calls) == 0
|
||||||
|
|
||||||
|
# Test light turns off off 120s after last motion
|
||||||
|
hass.states.async_set("binary_sensor.kitchen", "off")
|
||||||
|
|
||||||
|
for _ in range(5):
|
||||||
|
await asyncio.sleep(0)
|
||||||
|
|
||||||
|
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=120))
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert len(turn_off_calls) == 1
|
||||||
|
|
||||||
|
# Test restarting the script
|
||||||
|
hass.states.async_set("binary_sensor.kitchen", "on")
|
||||||
|
|
||||||
|
for _ in range(5):
|
||||||
|
await asyncio.sleep(0)
|
||||||
|
|
||||||
|
assert len(turn_on_calls) == 2
|
||||||
|
assert len(turn_off_calls) == 1
|
||||||
|
|
||||||
|
hass.states.async_set("binary_sensor.kitchen", "off")
|
||||||
|
|
||||||
|
for _ in range(5):
|
||||||
|
await asyncio.sleep(0)
|
||||||
|
|
||||||
|
hass.states.async_set("binary_sensor.kitchen", "on")
|
||||||
|
|
||||||
|
for _ in range(15):
|
||||||
|
await asyncio.sleep(0)
|
||||||
|
|
||||||
|
assert len(turn_on_calls) == 3
|
||||||
|
assert len(turn_off_calls) == 1
|
|
@ -20,6 +20,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -20,6 +20,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
14
tests/components/blueprint/conftest.py
Normal file
14
tests/components/blueprint/conftest.py
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
"""Blueprints conftest."""
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from tests.async_mock import patch
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
def stub_blueprint_populate():
|
||||||
|
"""Stub copying the blueprint automations to the config folder."""
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.blueprint.models.DomainBlueprints.async_populate"
|
||||||
|
):
|
||||||
|
yield
|
28
tests/components/blueprint/test_default_blueprints.py
Normal file
28
tests/components/blueprint/test_default_blueprints.py
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
"""Test default blueprints."""
|
||||||
|
import importlib
|
||||||
|
import logging
|
||||||
|
import pathlib
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from homeassistant.components.blueprint import models
|
||||||
|
from homeassistant.components.blueprint.const import BLUEPRINT_FOLDER
|
||||||
|
from homeassistant.util import yaml
|
||||||
|
|
||||||
|
DOMAINS = ["automation"]
|
||||||
|
LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("domain", DOMAINS)
|
||||||
|
def test_default_blueprints(domain: str):
|
||||||
|
"""Validate a folder of blueprints."""
|
||||||
|
integration = importlib.import_module(f"homeassistant.components.{domain}")
|
||||||
|
blueprint_folder = pathlib.Path(integration.__file__).parent / BLUEPRINT_FOLDER
|
||||||
|
items = list(blueprint_folder.glob("*"))
|
||||||
|
assert len(items) > 0, "Folder cannot be empty"
|
||||||
|
|
||||||
|
for fil in items:
|
||||||
|
LOGGER.info("Processing %s", fil)
|
||||||
|
assert fil.name.endswith(".yaml")
|
||||||
|
data = yaml.load_yaml(fil)
|
||||||
|
models.Blueprint(data, expected_domain=domain)
|
|
@ -15,6 +15,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -15,6 +15,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -16,6 +16,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -5,6 +5,7 @@ from homeassistant.bootstrap import async_setup_component
|
||||||
from homeassistant.components import config
|
from homeassistant.components import config
|
||||||
|
|
||||||
from tests.async_mock import patch
|
from tests.async_mock import patch
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
async def test_get_device_config(hass, hass_client):
|
async def test_get_device_config(hass, hass_client):
|
||||||
|
|
|
@ -4,6 +4,7 @@ import pytest
|
||||||
from homeassistant.components.config import device_registry
|
from homeassistant.components.config import device_registry
|
||||||
|
|
||||||
from tests.common import mock_device_registry
|
from tests.common import mock_device_registry
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -16,6 +16,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -22,6 +22,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -22,6 +22,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -19,6 +19,7 @@ from homeassistant.const import (
|
||||||
from .test_gateway import DECONZ_WEB_REQUEST, setup_deconz_integration
|
from .test_gateway import DECONZ_WEB_REQUEST, setup_deconz_integration
|
||||||
|
|
||||||
from tests.common import assert_lists_same, async_get_device_automations
|
from tests.common import assert_lists_same, async_get_device_automations
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
SENSORS = {
|
SENSORS = {
|
||||||
"1": {
|
"1": {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import pytest
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
from tests.async_mock import patch
|
from tests.async_mock import patch
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
|
|
|
@ -13,6 +13,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -15,6 +15,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -16,6 +16,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
AWAY_LATITUDE = 32.881011
|
AWAY_LATITUDE = 32.881011
|
||||||
AWAY_LONGITUDE = -117.234758
|
AWAY_LONGITUDE = -117.234758
|
||||||
|
|
|
@ -14,6 +14,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -15,6 +15,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -15,6 +15,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -7,6 +7,7 @@ from homeassistant.core import Context
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
from tests.common import async_mock_service, mock_component
|
from tests.common import async_mock_service, mock_component
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
3
tests/components/homeassistant/triggers/conftest.py
Normal file
3
tests/components/homeassistant/triggers/conftest.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
"""Conftest for HA triggers."""
|
||||||
|
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
|
@ -12,6 +12,7 @@ from tests.common import (
|
||||||
async_get_device_automations,
|
async_get_device_automations,
|
||||||
async_mock_service,
|
async_mock_service,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
from tests.components.homekit_controller.common import setup_test_component
|
from tests.components.homekit_controller.common import setup_test_component
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ from tests.common import (
|
||||||
async_mock_service,
|
async_mock_service,
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
REMOTES_RESPONSE = {"7": HUE_TAP_REMOTE_1, "8": HUE_DIMMER_REMOTE_1}
|
REMOTES_RESPONSE = {"7": HUE_TAP_REMOTE_1, "8": HUE_DIMMER_REMOTE_1}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -17,6 +17,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -20,6 +20,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -16,6 +16,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -21,6 +21,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -19,6 +19,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -19,6 +19,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -11,6 +11,7 @@ import homeassistant.components.automation as automation
|
||||||
import homeassistant.util.dt as dt_util
|
import homeassistant.util.dt as dt_util
|
||||||
|
|
||||||
from tests.common import async_fire_time_changed, async_mock_service
|
from tests.common import async_fire_time_changed, async_mock_service
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -15,6 +15,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -15,6 +15,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -21,6 +21,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -16,6 +16,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -7,6 +7,7 @@ from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
from tests.async_mock import ANY
|
from tests.async_mock import ANY
|
||||||
from tests.common import async_fire_mqtt_message, async_mock_service, mock_component
|
from tests.common import async_fire_mqtt_message, async_mock_service, mock_component
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -16,6 +16,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -19,6 +19,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -19,6 +19,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -3,6 +3,7 @@ from homeassistant.components import search
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
from tests.common import MockConfigEntry
|
from tests.common import MockConfigEntry
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
async def test_search(hass):
|
async def test_search(hass):
|
||||||
|
|
|
@ -16,6 +16,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
from tests.testing_config.custom_components.test.sensor import DEVICE_CLASSES
|
from tests.testing_config.custom_components.test.sensor import DEVICE_CLASSES
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
from tests.testing_config.custom_components.test.sensor import DEVICE_CLASSES
|
from tests.testing_config.custom_components.test.sensor import DEVICE_CLASSES
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ import homeassistant.util.dt as dt_util
|
||||||
|
|
||||||
from tests.async_mock import patch
|
from tests.async_mock import patch
|
||||||
from tests.common import async_fire_time_changed, async_mock_service, mock_component
|
from tests.common import async_fire_time_changed, async_mock_service, mock_component
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
ORIG_TIME_ZONE = dt_util.DEFAULT_TIME_ZONE
|
ORIG_TIME_ZONE = dt_util.DEFAULT_TIME_ZONE
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -19,6 +19,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -19,6 +19,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -8,6 +8,7 @@ from homeassistant.components.tag.const import DOMAIN, TAG_ID
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
from tests.common import async_mock_service
|
from tests.common import async_mock_service
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -18,6 +18,7 @@ from tests.common import (
|
||||||
async_fire_mqtt_message,
|
async_fire_mqtt_message,
|
||||||
async_get_device_automations,
|
async_get_device_automations,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
async def test_get_triggers(hass, device_reg, entity_reg, mqtt_mock, setup_tasmota):
|
async def test_get_triggers(hass, device_reg, entity_reg, mqtt_mock, setup_tasmota):
|
||||||
|
|
|
@ -17,6 +17,7 @@ from tests.common import (
|
||||||
async_mock_service,
|
async_mock_service,
|
||||||
mock_component,
|
mock_component,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -14,6 +14,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -19,6 +19,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -14,6 +14,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -14,6 +14,7 @@ from tests.common import (
|
||||||
mock_device_registry,
|
mock_device_registry,
|
||||||
mock_registry,
|
mock_registry,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -5,6 +5,7 @@ from homeassistant.core import callback
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
from tests.async_mock import patch
|
from tests.async_mock import patch
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
|
|
|
@ -16,6 +16,7 @@ from homeassistant.helpers.device_registry import async_get_registry
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
from tests.common import async_mock_service, mock_coro
|
from tests.common import async_mock_service, mock_coro
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
SHORT_PRESS = "remote_button_short_press"
|
SHORT_PRESS = "remote_button_short_press"
|
||||||
COMMAND = "command"
|
COMMAND = "command"
|
||||||
|
|
|
@ -19,6 +19,7 @@ from tests.common import (
|
||||||
async_get_device_automations,
|
async_get_device_automations,
|
||||||
async_mock_service,
|
async_mock_service,
|
||||||
)
|
)
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
ON = 1
|
ON = 1
|
||||||
OFF = 0
|
OFF = 0
|
||||||
|
|
|
@ -7,6 +7,7 @@ from homeassistant.core import Context
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
from tests.common import async_mock_service, mock_component
|
from tests.common import async_mock_service, mock_component
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -165,4 +165,4 @@ action:
|
||||||
}
|
}
|
||||||
with patch("os.path.isfile", return_value=True), patch_yaml_files(files):
|
with patch("os.path.isfile", return_value=True), patch_yaml_files(files):
|
||||||
res = await async_check_ha_config_file(hass)
|
res = await async_check_ha_config_file(hass)
|
||||||
assert len(res["automation"]) == 1
|
assert len(res.get("automation", [])) == 1
|
||||||
|
|
|
@ -6,7 +6,25 @@ from homeassistant.helpers import selector
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"schema", ({}, {"non_existing": {}}, {"device": {}, "entity": {}})
|
"schema",
|
||||||
|
(
|
||||||
|
{"device": None},
|
||||||
|
{"entity": None},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
def test_valid_base_schema(schema):
|
||||||
|
"""Test base schema validation."""
|
||||||
|
selector.validate_selector(schema)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"schema",
|
||||||
|
(
|
||||||
|
{},
|
||||||
|
{"non_existing": {}},
|
||||||
|
# Two keys
|
||||||
|
{"device": {}, "entity": {}},
|
||||||
|
),
|
||||||
)
|
)
|
||||||
def test_invalid_base_schema(schema):
|
def test_invalid_base_schema(schema):
|
||||||
"""Test base schema validation."""
|
"""Test base schema validation."""
|
||||||
|
|
Loading…
Add table
Reference in a new issue