Add default config if not there (#43321)

Co-authored-by: Bram Kragten <mail@bramkragten.nl>
This commit is contained in:
Paulus Schoutsen 2020-11-25 15:10:04 +01:00 committed by GitHub
parent 0cf3736162
commit b3be708db6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
75 changed files with 432 additions and 21 deletions

View file

@ -166,7 +166,8 @@ async def async_setup(hass, config):
# To register the automation blueprints
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):
"""Handle automation triggers."""
@ -487,12 +488,13 @@ async def _async_process_config(
hass: HomeAssistant,
config: Dict[str, Any],
component: EntityComponent,
) -> None:
) -> bool:
"""Process config and add automations.
This method is a coroutine.
Returns if blueprints were used.
"""
entities = []
blueprints_used = False
for config_key in extract_domain_configs(config, DOMAIN):
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):
if isinstance(config_block, blueprint.BlueprintInputs): # type: ignore
blueprints_used = True
blueprint_inputs = config_block
try:
@ -562,6 +565,8 @@ async def _async_process_config(
if entities:
await component.async_add_entities(entities)
return blueprints_used
async def _async_process_if(hass, config, p_config):
"""Process if checks."""

View file

@ -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

View file

@ -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 }}"

View file

@ -2,14 +2,16 @@
import asyncio
import logging
import pathlib
import shutil
from typing import Any, Dict, List, Optional, Union
from pkg_resources import parse_version
import voluptuous as vol
from voluptuous.humanize import humanize_error
from homeassistant import loader
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.helpers import placeholder
from homeassistant.util import yaml
@ -169,6 +171,11 @@ class DomainBlueprints:
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
def async_reset_cache(self) -> None:
"""Reset the blueprint cache."""
@ -177,9 +184,7 @@ class DomainBlueprints:
def _load_blueprint(self, blueprint_path) -> Blueprint:
"""Load a blueprint."""
try:
blueprint_data = yaml.load_yaml(
self.hass.config.path(BLUEPRINT_FOLDER, self.domain, blueprint_path)
)
blueprint_data = yaml.load_yaml(self.blueprint_folder / blueprint_path)
except (HomeAssistantError, FileNotFoundError) as 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:
"""Remove a blueprint file."""
path = pathlib.Path(
self.hass.config.path(BLUEPRINT_FOLDER, self.domain, blueprint_path)
)
path = self.blueprint_folder / blueprint_path
await self.hass.async_add_executor_job(path.unlink)
self._blueprints[blueprint_path] = None
@ -288,3 +290,18 @@ class DomainBlueprints:
)
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)

View file

@ -63,6 +63,7 @@ BLUEPRINT_SCHEMA = vol.Schema(
vol.Required(CONF_BLUEPRINT): vol.Schema(
{
vol.Required(CONF_NAME): str,
vol.Optional(CONF_DESCRIPTION): str,
vol.Required(CONF_DOMAIN): str,
vol.Optional(CONF_SOURCE_URL): cv.url,
vol.Optional(CONF_HOMEASSISTANT): {

View file

@ -453,18 +453,12 @@ def async_template(
) -> bool:
"""Test if template condition matches."""
try:
value = value_template.async_render(variables)
value: str = value_template.async_render(variables, parse_result=False)
except TemplateError as ex:
_LOGGER.error("Error during template condition: %s", ex)
return False
if isinstance(value, bool):
return value
if isinstance(value, str):
return value.lower() == "true"
return False
return value.lower() == "true"
def async_template_from_config(

View file

@ -23,6 +23,10 @@ def validate_selector(config: Any) -> Dict:
if selector_class is None:
raise vol.Invalid(f"Unknown selector type {selector_type} found")
# Seletors can be empty
if config[selector_type] is None:
return {selector_type: {}}
return {
selector_type: cast(Dict, selector_class.CONFIG_SCHEMA(config[selector_type]))
}
@ -44,6 +48,8 @@ class EntitySelector(Selector):
vol.Optional("integration"): str,
# Domain the entity belongs to
vol.Optional("domain"): str,
# Device class of the entity
vol.Optional("device_class"): str,
}
)

View file

@ -9,6 +9,7 @@ from io import StringIO
import json
import logging
import os
import pathlib
import threading
import time
import uuid
@ -704,6 +705,9 @@ def patch_yaml_files(files_dict, endswith=True):
def mock_open_f(fname, **_):
"""Mock open() in the yaml module, used by load_yaml."""
# Return the mocked file on full match
if isinstance(fname, pathlib.Path):
fname = str(fname)
if fname in files_dict:
_LOGGER.debug("patch_yaml_files match %s", fname)
res = StringIO(files_dict[fname])

View file

@ -23,6 +23,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -22,6 +22,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -22,6 +22,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -13,6 +13,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -0,0 +1,3 @@
"""Conftest for automation tests."""
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa

View 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

View file

@ -20,6 +20,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -20,6 +20,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View 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

View 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)

View file

@ -15,6 +15,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -15,6 +15,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -16,6 +16,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -5,6 +5,7 @@ from homeassistant.bootstrap import async_setup_component
from homeassistant.components import config
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):

View file

@ -4,6 +4,7 @@ import pytest
from homeassistant.components.config import device_registry
from tests.common import mock_device_registry
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -16,6 +16,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -22,6 +22,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -22,6 +22,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -19,6 +19,7 @@ from homeassistant.const import (
from .test_gateway import DECONZ_WEB_REQUEST, setup_deconz_integration
from tests.common import assert_lists_same, async_get_device_automations
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
SENSORS = {
"1": {

View file

@ -4,6 +4,7 @@ import pytest
from homeassistant.setup import async_setup_component
from tests.async_mock import patch
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture(autouse=True)

View file

@ -13,6 +13,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -15,6 +15,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -16,6 +16,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
AWAY_LATITUDE = 32.881011
AWAY_LONGITUDE = -117.234758

View file

@ -14,6 +14,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -15,6 +15,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -15,6 +15,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -7,6 +7,7 @@ from homeassistant.core import Context
from homeassistant.setup import async_setup_component
from tests.common import async_mock_service, mock_component
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -0,0 +1,3 @@
"""Conftest for HA triggers."""
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa

View file

@ -12,6 +12,7 @@ from tests.common import (
async_get_device_automations,
async_mock_service,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
from tests.components.homekit_controller.common import setup_test_component

View file

@ -15,6 +15,7 @@ from tests.common import (
async_mock_service,
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}

View file

@ -16,6 +16,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -17,6 +17,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -20,6 +20,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -16,6 +16,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -21,6 +21,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -19,6 +19,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -19,6 +19,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -11,6 +11,7 @@ import homeassistant.components.automation as automation
import homeassistant.util.dt as dt_util
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__)

View file

@ -15,6 +15,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -15,6 +15,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -15,6 +15,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -21,6 +21,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -16,6 +16,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -7,6 +7,7 @@ from homeassistant.setup import async_setup_component
from tests.async_mock import ANY
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

View file

@ -16,6 +16,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -19,6 +19,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -19,6 +19,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -3,6 +3,7 @@ from homeassistant.components import search
from homeassistant.setup import async_setup_component
from tests.common import MockConfigEntry
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
async def test_search(hass):

View file

@ -16,6 +16,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
from tests.testing_config.custom_components.test.sensor import DEVICE_CLASSES

View file

@ -20,6 +20,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
from tests.testing_config.custom_components.test.sensor import DEVICE_CLASSES

View file

@ -18,6 +18,7 @@ import homeassistant.util.dt as dt_util
from tests.async_mock import patch
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

View file

@ -16,6 +16,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -19,6 +19,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -19,6 +19,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -8,6 +8,7 @@ from homeassistant.components.tag.const import DOMAIN, TAG_ID
from homeassistant.setup import async_setup_component
from tests.common import async_mock_service
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -18,6 +18,7 @@ from tests.common import (
async_fire_mqtt_message,
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):

View file

@ -17,6 +17,7 @@ from tests.common import (
async_mock_service,
mock_component,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -14,6 +14,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -19,6 +19,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -14,6 +14,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -14,6 +14,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -5,6 +5,7 @@ from homeassistant.core import callback
from homeassistant.setup import async_setup_component
from tests.async_mock import patch
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture(autouse=True)

View file

@ -16,6 +16,7 @@ from homeassistant.helpers.device_registry import async_get_registry
from homeassistant.setup import async_setup_component
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"
COMMAND = "command"

View file

@ -19,6 +19,7 @@ from tests.common import (
async_get_device_automations,
async_mock_service,
)
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
ON = 1
OFF = 0

View file

@ -7,6 +7,7 @@ from homeassistant.core import Context
from homeassistant.setup import async_setup_component
from tests.common import async_mock_service, mock_component
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa
@pytest.fixture

View file

@ -165,4 +165,4 @@ action:
}
with patch("os.path.isfile", return_value=True), patch_yaml_files(files):
res = await async_check_ha_config_file(hass)
assert len(res["automation"]) == 1
assert len(res.get("automation", [])) == 1

View file

@ -6,7 +6,25 @@ from homeassistant.helpers import selector
@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):
"""Test base schema validation."""