mirror of
https://github.com/home-assistant/core.git
synced 2025-07-27 23:27:37 +00:00
Async bootstrap / component init (#3991)
* Async bootstrap * Adress comments * Fix tests * More fixes * Tests fixes
This commit is contained in:
parent
d9999f36e8
commit
d5368f6f78
@ -1,11 +1,10 @@
|
|||||||
"""Provides methods to bootstrap a home assistant instance."""
|
"""Provides methods to bootstrap a home assistant instance."""
|
||||||
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
import logging.handlers
|
import logging.handlers
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from threading import RLock
|
|
||||||
|
|
||||||
from types import ModuleType
|
from types import ModuleType
|
||||||
from typing import Any, Optional, Dict
|
from typing import Any, Optional, Dict
|
||||||
@ -19,6 +18,8 @@ import homeassistant.config as conf_util
|
|||||||
import homeassistant.core as core
|
import homeassistant.core as core
|
||||||
import homeassistant.loader as loader
|
import homeassistant.loader as loader
|
||||||
import homeassistant.util.package as pkg_util
|
import homeassistant.util.package as pkg_util
|
||||||
|
from homeassistant.util.async import (
|
||||||
|
run_coroutine_threadsafe, run_callback_threadsafe)
|
||||||
from homeassistant.util.yaml import clear_secret_cache
|
from homeassistant.util.yaml import clear_secret_cache
|
||||||
from homeassistant.const import EVENT_COMPONENT_LOADED, PLATFORM_FORMAT
|
from homeassistant.const import EVENT_COMPONENT_LOADED, PLATFORM_FORMAT
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
@ -26,7 +27,6 @@ from homeassistant.helpers import (
|
|||||||
event_decorators, service, config_per_platform, extract_domain_configs)
|
event_decorators, service, config_per_platform, extract_domain_configs)
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
_SETUP_LOCK = RLock()
|
|
||||||
_CURRENT_SETUP = []
|
_CURRENT_SETUP = []
|
||||||
|
|
||||||
ATTR_COMPONENT = 'component'
|
ATTR_COMPONENT = 'component'
|
||||||
@ -39,11 +39,23 @@ _PERSISTENT_VALIDATION = set()
|
|||||||
def setup_component(hass: core.HomeAssistant, domain: str,
|
def setup_component(hass: core.HomeAssistant, domain: str,
|
||||||
config: Optional[Dict]=None) -> bool:
|
config: Optional[Dict]=None) -> bool:
|
||||||
"""Setup a component and all its dependencies."""
|
"""Setup a component and all its dependencies."""
|
||||||
|
return run_coroutine_threadsafe(
|
||||||
|
async_setup_component(hass, domain, config), loop=hass.loop).result()
|
||||||
|
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def async_setup_component(hass: core.HomeAssistant, domain: str,
|
||||||
|
config: Optional[Dict]=None) -> bool:
|
||||||
|
"""Setup a component and all its dependencies.
|
||||||
|
|
||||||
|
This method need to run in a executor.
|
||||||
|
"""
|
||||||
if domain in hass.config.components:
|
if domain in hass.config.components:
|
||||||
_LOGGER.debug('Component %s already set up.', domain)
|
_LOGGER.debug('Component %s already set up.', domain)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
_ensure_loader_prepared(hass)
|
if not loader.PREPARED:
|
||||||
|
yield from hass.loop.run_in_executor(None, loader.prepare, hass)
|
||||||
|
|
||||||
if config is None:
|
if config is None:
|
||||||
config = defaultdict(dict)
|
config = defaultdict(dict)
|
||||||
@ -55,7 +67,8 @@ def setup_component(hass: core.HomeAssistant, domain: str,
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
for component in components:
|
for component in components:
|
||||||
if not _setup_component(hass, component, config):
|
res = yield from _async_setup_component(hass, component, config)
|
||||||
|
if not res:
|
||||||
_LOGGER.error('Component %s failed to setup', component)
|
_LOGGER.error('Component %s failed to setup', component)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -64,7 +77,11 @@ def setup_component(hass: core.HomeAssistant, domain: str,
|
|||||||
|
|
||||||
def _handle_requirements(hass: core.HomeAssistant, component,
|
def _handle_requirements(hass: core.HomeAssistant, component,
|
||||||
name: str) -> bool:
|
name: str) -> bool:
|
||||||
"""Install the requirements for a component."""
|
"""Install the requirements for a component.
|
||||||
|
|
||||||
|
Asyncio don't support file operation jet.
|
||||||
|
This method need to run in a executor.
|
||||||
|
"""
|
||||||
if hass.config.skip_pip or not hasattr(component, 'REQUIREMENTS'):
|
if hass.config.skip_pip or not hasattr(component, 'REQUIREMENTS'):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -77,65 +94,82 @@ def _handle_requirements(hass: core.HomeAssistant, component,
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def _setup_component(hass: core.HomeAssistant, domain: str, config) -> bool:
|
@asyncio.coroutine
|
||||||
"""Setup a component for Home Assistant."""
|
def _async_setup_component(hass: core.HomeAssistant,
|
||||||
|
domain: str, config) -> bool:
|
||||||
|
"""Setup a component for Home Assistant.
|
||||||
|
|
||||||
|
This method is a coroutine.
|
||||||
|
"""
|
||||||
# pylint: disable=too-many-return-statements,too-many-branches
|
# pylint: disable=too-many-return-statements,too-many-branches
|
||||||
# pylint: disable=too-many-statements
|
# pylint: disable=too-many-statements
|
||||||
if domain in hass.config.components:
|
if domain in hass.config.components:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
with _SETUP_LOCK:
|
if domain in _CURRENT_SETUP:
|
||||||
# It might have been loaded while waiting for lock
|
_LOGGER.error('Attempt made to setup %s during setup of %s',
|
||||||
if domain in hass.config.components:
|
domain, domain)
|
||||||
return True
|
return False
|
||||||
|
|
||||||
if domain in _CURRENT_SETUP:
|
config = yield from async_prepare_setup_component(hass, config, domain)
|
||||||
_LOGGER.error('Attempt made to setup %s during setup of %s',
|
|
||||||
domain, domain)
|
if config is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
component = loader.get_component(domain)
|
||||||
|
_CURRENT_SETUP.append(domain)
|
||||||
|
|
||||||
|
try:
|
||||||
|
if hasattr(component, 'async_setup'):
|
||||||
|
result = yield from component.async_setup(hass, config)
|
||||||
|
else:
|
||||||
|
result = yield from hass.loop.run_in_executor(
|
||||||
|
None, component.setup, hass, config)
|
||||||
|
|
||||||
|
if result is False:
|
||||||
|
_LOGGER.error('component %s failed to initialize', domain)
|
||||||
return False
|
return False
|
||||||
|
elif result is not True:
|
||||||
config = prepare_setup_component(hass, config, domain)
|
_LOGGER.error('component %s did not return boolean if setup '
|
||||||
|
'was successful. Disabling component.', domain)
|
||||||
if config is None:
|
loader.set_component(domain, None)
|
||||||
return False
|
return False
|
||||||
|
except Exception: # pylint: disable=broad-except
|
||||||
|
_LOGGER.exception('Error during setup of component %s', domain)
|
||||||
|
return False
|
||||||
|
finally:
|
||||||
|
_CURRENT_SETUP.remove(domain)
|
||||||
|
|
||||||
component = loader.get_component(domain)
|
hass.config.components.append(component.DOMAIN)
|
||||||
_CURRENT_SETUP.append(domain)
|
|
||||||
|
|
||||||
try:
|
# Assumption: if a component does not depend on groups
|
||||||
result = component.setup(hass, config)
|
# it communicates with devices
|
||||||
if result is False:
|
if 'group' not in getattr(component, 'DEPENDENCIES', []) and \
|
||||||
_LOGGER.error('component %s failed to initialize', domain)
|
hass.pool.worker_count <= 10:
|
||||||
return False
|
hass.pool.add_worker()
|
||||||
elif result is not True:
|
|
||||||
_LOGGER.error('component %s did not return boolean if setup '
|
|
||||||
'was successful. Disabling component.', domain)
|
|
||||||
loader.set_component(domain, None)
|
|
||||||
return False
|
|
||||||
except Exception: # pylint: disable=broad-except
|
|
||||||
_LOGGER.exception('Error during setup of component %s', domain)
|
|
||||||
return False
|
|
||||||
finally:
|
|
||||||
_CURRENT_SETUP.remove(domain)
|
|
||||||
|
|
||||||
hass.config.components.append(component.DOMAIN)
|
hass.bus.async_fire(
|
||||||
|
EVENT_COMPONENT_LOADED, {ATTR_COMPONENT: component.DOMAIN}
|
||||||
|
)
|
||||||
|
|
||||||
# Assumption: if a component does not depend on groups
|
return True
|
||||||
# it communicates with devices
|
|
||||||
if 'group' not in getattr(component, 'DEPENDENCIES', []) and \
|
|
||||||
hass.pool.worker_count <= 10:
|
|
||||||
hass.pool.add_worker()
|
|
||||||
|
|
||||||
hass.bus.fire(
|
|
||||||
EVENT_COMPONENT_LOADED, {ATTR_COMPONENT: component.DOMAIN}
|
|
||||||
)
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def prepare_setup_component(hass: core.HomeAssistant, config: dict,
|
def prepare_setup_component(hass: core.HomeAssistant, config: dict,
|
||||||
domain: str):
|
domain: str):
|
||||||
"""Prepare setup of a component and return processed config."""
|
"""Prepare setup of a component and return processed config."""
|
||||||
|
return run_coroutine_threadsafe(
|
||||||
|
async_prepare_setup_component(hass, config, domain), loop=hass.loop
|
||||||
|
).result()
|
||||||
|
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def async_prepare_setup_component(hass: core.HomeAssistant, config: dict,
|
||||||
|
domain: str):
|
||||||
|
"""Prepare setup of a component and return processed config.
|
||||||
|
|
||||||
|
This method is a coroutine.
|
||||||
|
"""
|
||||||
# pylint: disable=too-many-return-statements
|
# pylint: disable=too-many-return-statements
|
||||||
component = loader.get_component(domain)
|
component = loader.get_component(domain)
|
||||||
missing_deps = [dep for dep in getattr(component, 'DEPENDENCIES', [])
|
missing_deps = [dep for dep in getattr(component, 'DEPENDENCIES', [])
|
||||||
@ -151,7 +185,7 @@ def prepare_setup_component(hass: core.HomeAssistant, config: dict,
|
|||||||
try:
|
try:
|
||||||
config = component.CONFIG_SCHEMA(config)
|
config = component.CONFIG_SCHEMA(config)
|
||||||
except vol.Invalid as ex:
|
except vol.Invalid as ex:
|
||||||
log_exception(ex, domain, config, hass)
|
async_log_exception(ex, domain, config, hass)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
elif hasattr(component, 'PLATFORM_SCHEMA'):
|
elif hasattr(component, 'PLATFORM_SCHEMA'):
|
||||||
@ -161,7 +195,7 @@ def prepare_setup_component(hass: core.HomeAssistant, config: dict,
|
|||||||
try:
|
try:
|
||||||
p_validated = component.PLATFORM_SCHEMA(p_config)
|
p_validated = component.PLATFORM_SCHEMA(p_config)
|
||||||
except vol.Invalid as ex:
|
except vol.Invalid as ex:
|
||||||
log_exception(ex, domain, config, hass)
|
async_log_exception(ex, domain, config, hass)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Not all platform components follow same pattern for platforms
|
# Not all platform components follow same pattern for platforms
|
||||||
@ -171,8 +205,8 @@ def prepare_setup_component(hass: core.HomeAssistant, config: dict,
|
|||||||
platforms.append(p_validated)
|
platforms.append(p_validated)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
platform = prepare_setup_platform(hass, config, domain,
|
platform = yield from async_prepare_setup_platform(
|
||||||
p_name)
|
hass, config, domain, p_name)
|
||||||
|
|
||||||
if platform is None:
|
if platform is None:
|
||||||
continue
|
continue
|
||||||
@ -180,10 +214,11 @@ def prepare_setup_component(hass: core.HomeAssistant, config: dict,
|
|||||||
# Validate platform specific schema
|
# Validate platform specific schema
|
||||||
if hasattr(platform, 'PLATFORM_SCHEMA'):
|
if hasattr(platform, 'PLATFORM_SCHEMA'):
|
||||||
try:
|
try:
|
||||||
|
# pylint: disable=no-member
|
||||||
p_validated = platform.PLATFORM_SCHEMA(p_validated)
|
p_validated = platform.PLATFORM_SCHEMA(p_validated)
|
||||||
except vol.Invalid as ex:
|
except vol.Invalid as ex:
|
||||||
log_exception(ex, '{}.{}'.format(domain, p_name),
|
async_log_exception(ex, '{}.{}'.format(domain, p_name),
|
||||||
p_validated, hass)
|
p_validated, hass)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
platforms.append(p_validated)
|
platforms.append(p_validated)
|
||||||
@ -195,7 +230,9 @@ def prepare_setup_component(hass: core.HomeAssistant, config: dict,
|
|||||||
if key not in filter_keys}
|
if key not in filter_keys}
|
||||||
config[domain] = platforms
|
config[domain] = platforms
|
||||||
|
|
||||||
if not _handle_requirements(hass, component, domain):
|
res = yield from hass.loop.run_in_executor(
|
||||||
|
None, _handle_requirements, hass, component, domain)
|
||||||
|
if not res:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return config
|
return config
|
||||||
@ -204,7 +241,22 @@ def prepare_setup_component(hass: core.HomeAssistant, config: dict,
|
|||||||
def prepare_setup_platform(hass: core.HomeAssistant, config, domain: str,
|
def prepare_setup_platform(hass: core.HomeAssistant, config, domain: str,
|
||||||
platform_name: str) -> Optional[ModuleType]:
|
platform_name: str) -> Optional[ModuleType]:
|
||||||
"""Load a platform and makes sure dependencies are setup."""
|
"""Load a platform and makes sure dependencies are setup."""
|
||||||
_ensure_loader_prepared(hass)
|
return run_coroutine_threadsafe(
|
||||||
|
async_prepare_setup_platform(hass, config, domain, platform_name),
|
||||||
|
loop=hass.loop
|
||||||
|
).result()
|
||||||
|
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def async_prepare_setup_platform(hass: core.HomeAssistant, config, domain: str,
|
||||||
|
platform_name: str) \
|
||||||
|
-> Optional[ModuleType]:
|
||||||
|
"""Load a platform and makes sure dependencies are setup.
|
||||||
|
|
||||||
|
This method is a coroutine.
|
||||||
|
"""
|
||||||
|
if not loader.PREPARED:
|
||||||
|
yield from hass.loop.run_in_executor(None, loader.prepare, hass)
|
||||||
|
|
||||||
platform_path = PLATFORM_FORMAT.format(domain, platform_name)
|
platform_path = PLATFORM_FORMAT.format(domain, platform_name)
|
||||||
|
|
||||||
@ -218,7 +270,7 @@ def prepare_setup_platform(hass: core.HomeAssistant, config, domain: str,
|
|||||||
message = ('Unable to find the following platforms: ' +
|
message = ('Unable to find the following platforms: ' +
|
||||||
', '.join(list(_PERSISTENT_PLATFORMS)) +
|
', '.join(list(_PERSISTENT_PLATFORMS)) +
|
||||||
'(please check your configuration)')
|
'(please check your configuration)')
|
||||||
persistent_notification.create(
|
persistent_notification.async_create(
|
||||||
hass, message, 'Invalid platforms', 'platform_errors')
|
hass, message, 'Invalid platforms', 'platform_errors')
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -228,14 +280,17 @@ def prepare_setup_platform(hass: core.HomeAssistant, config, domain: str,
|
|||||||
|
|
||||||
# Load dependencies
|
# Load dependencies
|
||||||
for component in getattr(platform, 'DEPENDENCIES', []):
|
for component in getattr(platform, 'DEPENDENCIES', []):
|
||||||
if not setup_component(hass, component, config):
|
res = yield from async_setup_component(hass, component, config)
|
||||||
|
if not res:
|
||||||
_LOGGER.error(
|
_LOGGER.error(
|
||||||
'Unable to prepare setup for platform %s because '
|
'Unable to prepare setup for platform %s because '
|
||||||
'dependency %s could not be initialized', platform_path,
|
'dependency %s could not be initialized', platform_path,
|
||||||
component)
|
component)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if not _handle_requirements(hass, platform, platform_path):
|
res = yield from hass.loop.run_in_executor(
|
||||||
|
None, _handle_requirements, hass, platform, platform_path)
|
||||||
|
if not res:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return platform
|
return platform
|
||||||
@ -261,15 +316,50 @@ def from_config_dict(config: Dict[str, Any],
|
|||||||
hass.config.config_dir = config_dir
|
hass.config.config_dir = config_dir
|
||||||
mount_local_lib_path(config_dir)
|
mount_local_lib_path(config_dir)
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def _async_init_from_config_dict(future):
|
||||||
|
try:
|
||||||
|
re_hass = yield from async_from_config_dict(
|
||||||
|
config, hass, config_dir, enable_log, verbose, skip_pip,
|
||||||
|
log_rotate_days)
|
||||||
|
future.set_result(re_hass)
|
||||||
|
# pylint: disable=broad-except
|
||||||
|
except Exception as exc:
|
||||||
|
future.set_exception(exc)
|
||||||
|
|
||||||
|
# run task
|
||||||
|
future = asyncio.Future()
|
||||||
|
asyncio.Task(_async_init_from_config_dict(future), loop=hass.loop)
|
||||||
|
hass.loop.run_until_complete(future)
|
||||||
|
|
||||||
|
return future.result()
|
||||||
|
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
# pylint: disable=too-many-branches, too-many-statements, too-many-arguments
|
||||||
|
def async_from_config_dict(config: Dict[str, Any],
|
||||||
|
hass: core.HomeAssistant,
|
||||||
|
config_dir: Optional[str]=None,
|
||||||
|
enable_log: bool=True,
|
||||||
|
verbose: bool=False,
|
||||||
|
skip_pip: bool=False,
|
||||||
|
log_rotate_days: Any=None) \
|
||||||
|
-> Optional[core.HomeAssistant]:
|
||||||
|
"""Try to configure Home Assistant from a config dict.
|
||||||
|
|
||||||
|
Dynamically loads required components and its dependencies.
|
||||||
|
This method is a coroutine.
|
||||||
|
"""
|
||||||
core_config = config.get(core.DOMAIN, {})
|
core_config = config.get(core.DOMAIN, {})
|
||||||
|
|
||||||
try:
|
try:
|
||||||
conf_util.process_ha_core_config(hass, core_config)
|
yield from conf_util.async_process_ha_core_config(hass, core_config)
|
||||||
except vol.Invalid as ex:
|
except vol.Invalid as ex:
|
||||||
log_exception(ex, 'homeassistant', core_config, hass)
|
async_log_exception(ex, 'homeassistant', core_config, hass)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
conf_util.process_ha_config_upgrade(hass)
|
yield from hass.loop.run_in_executor(
|
||||||
|
None, conf_util.process_ha_config_upgrade, hass)
|
||||||
|
|
||||||
if enable_log:
|
if enable_log:
|
||||||
enable_logging(hass, verbose, log_rotate_days)
|
enable_logging(hass, verbose, log_rotate_days)
|
||||||
@ -279,7 +369,8 @@ def from_config_dict(config: Dict[str, Any],
|
|||||||
_LOGGER.warning('Skipping pip installation of required modules. '
|
_LOGGER.warning('Skipping pip installation of required modules. '
|
||||||
'This may cause issues.')
|
'This may cause issues.')
|
||||||
|
|
||||||
_ensure_loader_prepared(hass)
|
if not loader.PREPARED:
|
||||||
|
yield from hass.loop.run_in_executor(None, loader.prepare, hass)
|
||||||
|
|
||||||
# Make a copy because we are mutating it.
|
# Make a copy because we are mutating it.
|
||||||
# Convert it to defaultdict so components can always have config dict
|
# Convert it to defaultdict so components can always have config dict
|
||||||
@ -291,29 +382,25 @@ def from_config_dict(config: Dict[str, Any],
|
|||||||
components = set(key.split(' ')[0] for key in config.keys()
|
components = set(key.split(' ')[0] for key in config.keys()
|
||||||
if key != core.DOMAIN)
|
if key != core.DOMAIN)
|
||||||
|
|
||||||
# Setup in a thread to avoid blocking
|
# setup components
|
||||||
def component_setup():
|
# pylint: disable=not-an-iterable
|
||||||
"""Set up a component."""
|
res = yield from core_components.async_setup(hass, config)
|
||||||
if not core_components.setup(hass, config):
|
if not res:
|
||||||
_LOGGER.error('Home Assistant core failed to initialize. '
|
_LOGGER.error('Home Assistant core failed to initialize. '
|
||||||
'Further initialization aborted.')
|
'Further initialization aborted.')
|
||||||
return hass
|
return hass
|
||||||
|
|
||||||
persistent_notification.setup(hass, config)
|
yield from persistent_notification.async_setup(hass, config)
|
||||||
|
|
||||||
_LOGGER.info('Home Assistant core initialized')
|
_LOGGER.info('Home Assistant core initialized')
|
||||||
|
|
||||||
# Give event decorators access to HASS
|
# Give event decorators access to HASS
|
||||||
event_decorators.HASS = hass
|
event_decorators.HASS = hass
|
||||||
service.HASS = hass
|
service.HASS = hass
|
||||||
|
|
||||||
# Setup the components
|
# Setup the components
|
||||||
for domain in loader.load_order_components(components):
|
for domain in loader.load_order_components(components):
|
||||||
_setup_component(hass, domain, config)
|
yield from _async_setup_component(hass, domain, config)
|
||||||
|
|
||||||
hass.loop.run_until_complete(
|
|
||||||
hass.loop.run_in_executor(None, component_setup)
|
|
||||||
)
|
|
||||||
|
|
||||||
return hass
|
return hass
|
||||||
|
|
||||||
@ -331,27 +418,62 @@ def from_config_file(config_path: str,
|
|||||||
if hass is None:
|
if hass is None:
|
||||||
hass = core.HomeAssistant()
|
hass = core.HomeAssistant()
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def _async_init_from_config_file(future):
|
||||||
|
try:
|
||||||
|
re_hass = yield from async_from_config_file(
|
||||||
|
config_path, hass, verbose, skip_pip, log_rotate_days)
|
||||||
|
future.set_result(re_hass)
|
||||||
|
# pylint: disable=broad-except
|
||||||
|
except Exception as exc:
|
||||||
|
future.set_exception(exc)
|
||||||
|
|
||||||
|
# run task
|
||||||
|
future = asyncio.Future()
|
||||||
|
asyncio.Task(_async_init_from_config_file(future), loop=hass.loop)
|
||||||
|
hass.loop.run_until_complete(future)
|
||||||
|
|
||||||
|
return future.result()
|
||||||
|
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def async_from_config_file(config_path: str,
|
||||||
|
hass: core.HomeAssistant,
|
||||||
|
verbose: bool=False,
|
||||||
|
skip_pip: bool=True,
|
||||||
|
log_rotate_days: Any=None):
|
||||||
|
"""Read the configuration file and try to start all the functionality.
|
||||||
|
|
||||||
|
Will add functionality to 'hass' parameter.
|
||||||
|
This method is a coroutine.
|
||||||
|
"""
|
||||||
# Set config dir to directory holding config file
|
# Set config dir to directory holding config file
|
||||||
config_dir = os.path.abspath(os.path.dirname(config_path))
|
config_dir = os.path.abspath(os.path.dirname(config_path))
|
||||||
hass.config.config_dir = config_dir
|
hass.config.config_dir = config_dir
|
||||||
mount_local_lib_path(config_dir)
|
yield from hass.loop.run_in_executor(
|
||||||
|
None, mount_local_lib_path, config_dir)
|
||||||
|
|
||||||
enable_logging(hass, verbose, log_rotate_days)
|
enable_logging(hass, verbose, log_rotate_days)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
config_dict = conf_util.load_yaml_config_file(config_path)
|
config_dict = yield from hass.loop.run_in_executor(
|
||||||
|
None, conf_util.load_yaml_config_file, config_path)
|
||||||
except HomeAssistantError:
|
except HomeAssistantError:
|
||||||
return None
|
return None
|
||||||
finally:
|
finally:
|
||||||
clear_secret_cache()
|
clear_secret_cache()
|
||||||
|
|
||||||
return from_config_dict(config_dict, hass, enable_log=False,
|
hass = yield from async_from_config_dict(
|
||||||
skip_pip=skip_pip)
|
config_dict, hass, enable_log=False, skip_pip=skip_pip)
|
||||||
|
return hass
|
||||||
|
|
||||||
|
|
||||||
def enable_logging(hass: core.HomeAssistant, verbose: bool=False,
|
def enable_logging(hass: core.HomeAssistant, verbose: bool=False,
|
||||||
log_rotate_days=None) -> None:
|
log_rotate_days=None) -> None:
|
||||||
"""Setup the logging."""
|
"""Setup the logging.
|
||||||
|
|
||||||
|
Async friendly.
|
||||||
|
"""
|
||||||
logging.basicConfig(level=logging.INFO)
|
logging.basicConfig(level=logging.INFO)
|
||||||
fmt = ("%(log_color)s%(asctime)s %(levelname)s (%(threadName)s) "
|
fmt = ("%(log_color)s%(asctime)s %(levelname)s (%(threadName)s) "
|
||||||
"[%(name)s] %(message)s%(reset)s")
|
"[%(name)s] %(message)s%(reset)s")
|
||||||
@ -407,44 +529,50 @@ def enable_logging(hass: core.HomeAssistant, verbose: bool=False,
|
|||||||
'Unable to setup error log %s (access denied)', err_log_path)
|
'Unable to setup error log %s (access denied)', err_log_path)
|
||||||
|
|
||||||
|
|
||||||
def _ensure_loader_prepared(hass: core.HomeAssistant) -> None:
|
def log_exception(ex, domain, config, hass):
|
||||||
"""Ensure Home Assistant loader is prepared."""
|
|
||||||
if not loader.PREPARED:
|
|
||||||
loader.prepare(hass)
|
|
||||||
|
|
||||||
|
|
||||||
def log_exception(ex, domain, config, hass=None):
|
|
||||||
"""Generate log exception for config validation."""
|
"""Generate log exception for config validation."""
|
||||||
|
run_callback_threadsafe(
|
||||||
|
hass.loop, async_log_exception, ex, domain, config, hass).result()
|
||||||
|
|
||||||
|
|
||||||
|
@core.callback
|
||||||
|
def async_log_exception(ex, domain, config, hass):
|
||||||
|
"""Generate log exception for config validation.
|
||||||
|
|
||||||
|
Need to run in a async loop.
|
||||||
|
"""
|
||||||
message = 'Invalid config for [{}]: '.format(domain)
|
message = 'Invalid config for [{}]: '.format(domain)
|
||||||
if hass is not None:
|
_PERSISTENT_VALIDATION.add(domain)
|
||||||
_PERSISTENT_VALIDATION.add(domain)
|
message = ('The following platforms contain invalid configuration: ' +
|
||||||
message = ('The following platforms contain invalid configuration: ' +
|
', '.join(list(_PERSISTENT_VALIDATION)) +
|
||||||
', '.join(list(_PERSISTENT_VALIDATION)) +
|
' (please check your configuration). ')
|
||||||
' (please check your configuration)')
|
persistent_notification.async_create(
|
||||||
persistent_notification.create(
|
hass, message, 'Invalid config', 'invalid_config')
|
||||||
hass, message, 'Invalid config', 'invalid_config')
|
|
||||||
|
|
||||||
if 'extra keys not allowed' in ex.error_message:
|
if 'extra keys not allowed' in ex.error_message:
|
||||||
message += '[{}] is an invalid option for [{}]. Check: {}->{}.'\
|
message += '[{}] is an invalid option for [{}]. Check: {}->{}.'\
|
||||||
.format(ex.path[-1], domain, domain,
|
.format(ex.path[-1], domain, domain,
|
||||||
'->'.join('%s' % m for m in ex.path))
|
'->'.join(str(m) for m in ex.path))
|
||||||
else:
|
else:
|
||||||
message += '{}.'.format(humanize_error(config, ex))
|
message += '{}.'.format(humanize_error(config, ex))
|
||||||
|
|
||||||
domain_config = config.get(domain, config)
|
domain_config = config.get(domain, config)
|
||||||
message += " (See {}:{})".format(
|
message += " (See {}:{}). ".format(
|
||||||
getattr(domain_config, '__config_file__', '?'),
|
getattr(domain_config, '__config_file__', '?'),
|
||||||
getattr(domain_config, '__line__', '?'))
|
getattr(domain_config, '__line__', '?'))
|
||||||
|
|
||||||
if domain != 'homeassistant':
|
if domain != 'homeassistant':
|
||||||
message += (' Please check the docs at '
|
message += ('Please check the docs at '
|
||||||
'https://home-assistant.io/components/{}/'.format(domain))
|
'https://home-assistant.io/components/{}/'.format(domain))
|
||||||
|
|
||||||
_LOGGER.error(message)
|
_LOGGER.error(message)
|
||||||
|
|
||||||
|
|
||||||
def mount_local_lib_path(config_dir: str) -> str:
|
def mount_local_lib_path(config_dir: str) -> str:
|
||||||
"""Add local library to Python Path."""
|
"""Add local library to Python Path.
|
||||||
|
|
||||||
|
Async friendly.
|
||||||
|
"""
|
||||||
deps_dir = os.path.join(config_dir, 'deps')
|
deps_dir = os.path.join(config_dir, 'deps')
|
||||||
if deps_dir not in sys.path:
|
if deps_dir not in sys.path:
|
||||||
sys.path.insert(0, os.path.join(config_dir, 'deps'))
|
sys.path.insert(0, os.path.join(config_dir, 'deps'))
|
||||||
|
@ -7,6 +7,7 @@ Component design guidelines:
|
|||||||
format "<DOMAIN>.<OBJECT_ID>".
|
format "<DOMAIN>.<OBJECT_ID>".
|
||||||
- Each component should publish services only under its own domain.
|
- Each component should publish services only under its own domain.
|
||||||
"""
|
"""
|
||||||
|
import asyncio
|
||||||
import itertools as it
|
import itertools as it
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
@ -79,8 +80,10 @@ def reload_core_config(hass):
|
|||||||
hass.services.call(ha.DOMAIN, SERVICE_RELOAD_CORE_CONFIG)
|
hass.services.call(ha.DOMAIN, SERVICE_RELOAD_CORE_CONFIG)
|
||||||
|
|
||||||
|
|
||||||
def setup(hass, config):
|
@asyncio.coroutine
|
||||||
|
def async_setup(hass, config):
|
||||||
"""Setup general services related to Home Assistant."""
|
"""Setup general services related to Home Assistant."""
|
||||||
|
@asyncio.coroutine
|
||||||
def handle_turn_service(service):
|
def handle_turn_service(service):
|
||||||
"""Method to handle calls to homeassistant.turn_on/off."""
|
"""Method to handle calls to homeassistant.turn_on/off."""
|
||||||
entity_ids = extract_entity_ids(hass, service)
|
entity_ids = extract_entity_ids(hass, service)
|
||||||
@ -96,6 +99,8 @@ def setup(hass, config):
|
|||||||
by_domain = it.groupby(sorted(entity_ids),
|
by_domain = it.groupby(sorted(entity_ids),
|
||||||
lambda item: ha.split_entity_id(item)[0])
|
lambda item: ha.split_entity_id(item)[0])
|
||||||
|
|
||||||
|
tasks = []
|
||||||
|
|
||||||
for domain, ent_ids in by_domain:
|
for domain, ent_ids in by_domain:
|
||||||
# We want to block for all calls and only return when all calls
|
# We want to block for all calls and only return when all calls
|
||||||
# have been processed. If a service does not exist it causes a 10
|
# have been processed. If a service does not exist it causes a 10
|
||||||
@ -111,27 +116,34 @@ def setup(hass, config):
|
|||||||
# ent_ids is a generator, convert it to a list.
|
# ent_ids is a generator, convert it to a list.
|
||||||
data[ATTR_ENTITY_ID] = list(ent_ids)
|
data[ATTR_ENTITY_ID] = list(ent_ids)
|
||||||
|
|
||||||
hass.services.call(domain, service.service, data, blocking)
|
tasks.append(hass.services.async_call(
|
||||||
|
domain, service.service, data, blocking))
|
||||||
|
|
||||||
hass.services.register(ha.DOMAIN, SERVICE_TURN_OFF, handle_turn_service)
|
yield from asyncio.gather(*tasks, loop=hass.loop)
|
||||||
hass.services.register(ha.DOMAIN, SERVICE_TURN_ON, handle_turn_service)
|
|
||||||
hass.services.register(ha.DOMAIN, SERVICE_TOGGLE, handle_turn_service)
|
|
||||||
|
|
||||||
|
hass.services.async_register(
|
||||||
|
ha.DOMAIN, SERVICE_TURN_OFF, handle_turn_service)
|
||||||
|
hass.services.async_register(
|
||||||
|
ha.DOMAIN, SERVICE_TURN_ON, handle_turn_service)
|
||||||
|
hass.services.async_register(
|
||||||
|
ha.DOMAIN, SERVICE_TOGGLE, handle_turn_service)
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
def handle_reload_config(call):
|
def handle_reload_config(call):
|
||||||
"""Service handler for reloading core config."""
|
"""Service handler for reloading core config."""
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant import config as conf_util
|
from homeassistant import config as conf_util
|
||||||
|
|
||||||
try:
|
try:
|
||||||
path = conf_util.find_config_file(hass.config.config_dir)
|
conf = yield from conf_util.async_hass_config_yaml(hass)
|
||||||
conf = conf_util.load_yaml_config_file(path)
|
|
||||||
except HomeAssistantError as err:
|
except HomeAssistantError as err:
|
||||||
_LOGGER.error(err)
|
_LOGGER.error(err)
|
||||||
return
|
return
|
||||||
|
|
||||||
conf_util.process_ha_core_config(hass, conf.get(ha.DOMAIN) or {})
|
yield from conf_util.async_process_ha_core_config(
|
||||||
|
hass, conf.get(ha.DOMAIN) or {})
|
||||||
|
|
||||||
hass.services.register(ha.DOMAIN, SERVICE_RELOAD_CORE_CONFIG,
|
hass.services.async_register(
|
||||||
handle_reload_config)
|
ha.DOMAIN, SERVICE_RELOAD_CORE_CONFIG, handle_reload_config)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
@ -11,7 +11,6 @@ import os
|
|||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.core import callback
|
|
||||||
from homeassistant.bootstrap import prepare_setup_platform
|
from homeassistant.bootstrap import prepare_setup_platform
|
||||||
from homeassistant import config as conf_util
|
from homeassistant import config as conf_util
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
@ -25,7 +24,6 @@ from homeassistant.helpers.entity_component import EntityComponent
|
|||||||
from homeassistant.loader import get_platform
|
from homeassistant.loader import get_platform
|
||||||
from homeassistant.util.dt import utcnow
|
from homeassistant.util.dt import utcnow
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.util.async import run_coroutine_threadsafe
|
|
||||||
|
|
||||||
DOMAIN = 'automation'
|
DOMAIN = 'automation'
|
||||||
ENTITY_ID_FORMAT = DOMAIN + '.{}'
|
ENTITY_ID_FORMAT = DOMAIN + '.{}'
|
||||||
@ -144,42 +142,50 @@ def reload(hass):
|
|||||||
hass.services.call(DOMAIN, SERVICE_RELOAD)
|
hass.services.call(DOMAIN, SERVICE_RELOAD)
|
||||||
|
|
||||||
|
|
||||||
def setup(hass, config):
|
@asyncio.coroutine
|
||||||
|
def async_setup(hass, config):
|
||||||
"""Setup the automation."""
|
"""Setup the automation."""
|
||||||
component = EntityComponent(_LOGGER, DOMAIN, hass,
|
component = EntityComponent(_LOGGER, DOMAIN, hass,
|
||||||
group_name=GROUP_NAME_ALL_AUTOMATIONS)
|
group_name=GROUP_NAME_ALL_AUTOMATIONS)
|
||||||
|
|
||||||
success = run_coroutine_threadsafe(
|
success = yield from _async_process_config(hass, config, component)
|
||||||
_async_process_config(hass, config, component), hass.loop).result()
|
|
||||||
|
|
||||||
if not success:
|
if not success:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
descriptions = conf_util.load_yaml_config_file(
|
descriptions = yield from hass.loop.run_in_executor(
|
||||||
os.path.join(os.path.dirname(__file__), 'services.yaml'))
|
None, conf_util.load_yaml_config_file, os.path.join(
|
||||||
|
os.path.dirname(__file__), 'services.yaml')
|
||||||
|
)
|
||||||
|
|
||||||
@callback
|
@asyncio.coroutine
|
||||||
def trigger_service_handler(service_call):
|
def trigger_service_handler(service_call):
|
||||||
"""Handle automation triggers."""
|
"""Handle automation triggers."""
|
||||||
|
tasks = []
|
||||||
for entity in component.async_extract_from_service(service_call):
|
for entity in component.async_extract_from_service(service_call):
|
||||||
hass.loop.create_task(entity.async_trigger(
|
tasks.append(entity.async_trigger(
|
||||||
service_call.data.get(ATTR_VARIABLES), True))
|
service_call.data.get(ATTR_VARIABLES), True))
|
||||||
|
yield from asyncio.gather(*tasks, loop=hass.loop)
|
||||||
|
|
||||||
@callback
|
@asyncio.coroutine
|
||||||
def turn_onoff_service_handler(service_call):
|
def turn_onoff_service_handler(service_call):
|
||||||
"""Handle automation turn on/off service calls."""
|
"""Handle automation turn on/off service calls."""
|
||||||
|
tasks = []
|
||||||
method = 'async_{}'.format(service_call.service)
|
method = 'async_{}'.format(service_call.service)
|
||||||
for entity in component.async_extract_from_service(service_call):
|
for entity in component.async_extract_from_service(service_call):
|
||||||
hass.loop.create_task(getattr(entity, method)())
|
tasks.append(getattr(entity, method)())
|
||||||
|
yield from asyncio.gather(*tasks, loop=hass.loop)
|
||||||
|
|
||||||
@callback
|
@asyncio.coroutine
|
||||||
def toggle_service_handler(service_call):
|
def toggle_service_handler(service_call):
|
||||||
"""Handle automation toggle service calls."""
|
"""Handle automation toggle service calls."""
|
||||||
|
tasks = []
|
||||||
for entity in component.async_extract_from_service(service_call):
|
for entity in component.async_extract_from_service(service_call):
|
||||||
if entity.is_on:
|
if entity.is_on:
|
||||||
hass.loop.create_task(entity.async_turn_off())
|
tasks.append(entity.async_turn_off())
|
||||||
else:
|
else:
|
||||||
hass.loop.create_task(entity.async_turn_on())
|
tasks.append(entity.async_turn_on())
|
||||||
|
yield from asyncio.gather(*tasks, loop=hass.loop)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def reload_service_handler(service_call):
|
def reload_service_handler(service_call):
|
||||||
@ -187,24 +193,24 @@ def setup(hass, config):
|
|||||||
conf = yield from component.async_prepare_reload()
|
conf = yield from component.async_prepare_reload()
|
||||||
if conf is None:
|
if conf is None:
|
||||||
return
|
return
|
||||||
hass.loop.create_task(_async_process_config(hass, conf, component))
|
yield from _async_process_config(hass, conf, component)
|
||||||
|
|
||||||
hass.services.register(DOMAIN, SERVICE_TRIGGER, trigger_service_handler,
|
hass.services.async_register(
|
||||||
descriptions.get(SERVICE_TRIGGER),
|
DOMAIN, SERVICE_TRIGGER, trigger_service_handler,
|
||||||
schema=TRIGGER_SERVICE_SCHEMA)
|
descriptions.get(SERVICE_TRIGGER), schema=TRIGGER_SERVICE_SCHEMA)
|
||||||
|
|
||||||
hass.services.register(DOMAIN, SERVICE_RELOAD, reload_service_handler,
|
hass.services.async_register(
|
||||||
descriptions.get(SERVICE_RELOAD),
|
DOMAIN, SERVICE_RELOAD, reload_service_handler,
|
||||||
schema=RELOAD_SERVICE_SCHEMA)
|
descriptions.get(SERVICE_RELOAD), schema=RELOAD_SERVICE_SCHEMA)
|
||||||
|
|
||||||
hass.services.register(DOMAIN, SERVICE_TOGGLE, toggle_service_handler,
|
hass.services.async_register(
|
||||||
descriptions.get(SERVICE_TOGGLE),
|
DOMAIN, SERVICE_TOGGLE, toggle_service_handler,
|
||||||
schema=SERVICE_SCHEMA)
|
descriptions.get(SERVICE_TOGGLE), schema=SERVICE_SCHEMA)
|
||||||
|
|
||||||
for service in (SERVICE_TURN_ON, SERVICE_TURN_OFF):
|
for service in (SERVICE_TURN_ON, SERVICE_TURN_OFF):
|
||||||
hass.services.register(DOMAIN, service, turn_onoff_service_handler,
|
hass.services.async_register(
|
||||||
descriptions.get(service),
|
DOMAIN, service, turn_onoff_service_handler,
|
||||||
schema=SERVICE_SCHEMA)
|
descriptions.get(service), schema=SERVICE_SCHEMA)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ def setup(hass: HomeAssistantType, config: ConfigType):
|
|||||||
try:
|
try:
|
||||||
conf = config.get(DOMAIN, [])
|
conf = config.get(DOMAIN, [])
|
||||||
except vol.Invalid as ex:
|
except vol.Invalid as ex:
|
||||||
log_exception(ex, DOMAIN, config)
|
log_exception(ex, DOMAIN, config, hass)
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
conf = conf[0] if len(conf) > 0 else {}
|
conf = conf[0] if len(conf) > 0 else {}
|
||||||
@ -431,7 +431,7 @@ def load_config(path: str, hass: HomeAssistantType, consider_home: timedelta):
|
|||||||
device = dev_schema(device)
|
device = dev_schema(device)
|
||||||
device['dev_id'] = cv.slugify(dev_id)
|
device['dev_id'] = cv.slugify(dev_id)
|
||||||
except vol.Invalid as exp:
|
except vol.Invalid as exp:
|
||||||
log_exception(exp, dev_id, devices)
|
log_exception(exp, dev_id, devices, hass)
|
||||||
else:
|
else:
|
||||||
result.append(Device(hass, **device))
|
result.append(Device(hass, **device))
|
||||||
return result
|
return result
|
||||||
|
@ -144,15 +144,17 @@ def get_entity_ids(hass, entity_id, domain_filter=None):
|
|||||||
if ent_id.startswith(domain_filter)]
|
if ent_id.startswith(domain_filter)]
|
||||||
|
|
||||||
|
|
||||||
def setup(hass, config):
|
@asyncio.coroutine
|
||||||
|
def async_setup(hass, config):
|
||||||
"""Setup all groups found definded in the configuration."""
|
"""Setup all groups found definded in the configuration."""
|
||||||
component = EntityComponent(_LOGGER, DOMAIN, hass)
|
component = EntityComponent(_LOGGER, DOMAIN, hass)
|
||||||
|
|
||||||
run_coroutine_threadsafe(
|
yield from _async_process_config(hass, config, component)
|
||||||
_async_process_config(hass, config, component), hass.loop).result()
|
|
||||||
|
|
||||||
descriptions = conf_util.load_yaml_config_file(
|
descriptions = yield from hass.loop.run_in_executor(
|
||||||
os.path.join(os.path.dirname(__file__), 'services.yaml'))
|
None, conf_util.load_yaml_config_file, os.path.join(
|
||||||
|
os.path.dirname(__file__), 'services.yaml')
|
||||||
|
)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def reload_service_handler(service_call):
|
def reload_service_handler(service_call):
|
||||||
@ -162,9 +164,9 @@ def setup(hass, config):
|
|||||||
return
|
return
|
||||||
hass.loop.create_task(_async_process_config(hass, conf, component))
|
hass.loop.create_task(_async_process_config(hass, conf, component))
|
||||||
|
|
||||||
hass.services.register(DOMAIN, SERVICE_RELOAD, reload_service_handler,
|
hass.services.async_register(
|
||||||
descriptions[DOMAIN][SERVICE_RELOAD],
|
DOMAIN, SERVICE_RELOAD, reload_service_handler,
|
||||||
schema=RELOAD_SERVICE_SCHEMA)
|
descriptions[DOMAIN][SERVICE_RELOAD], schema=RELOAD_SERVICE_SCHEMA)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -10,12 +10,13 @@ import logging
|
|||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
|
from homeassistant.core import callback
|
||||||
from homeassistant.exceptions import TemplateError
|
from homeassistant.exceptions import TemplateError
|
||||||
from homeassistant.helpers import config_validation as cv
|
from homeassistant.helpers import config_validation as cv
|
||||||
from homeassistant.helpers.entity import generate_entity_id
|
from homeassistant.helpers.entity import async_generate_entity_id
|
||||||
from homeassistant.util import slugify
|
from homeassistant.util import slugify
|
||||||
from homeassistant.config import load_yaml_config_file
|
from homeassistant.config import load_yaml_config_file
|
||||||
from homeassistant.util.async import run_coroutine_threadsafe
|
from homeassistant.util.async import run_callback_threadsafe
|
||||||
|
|
||||||
DOMAIN = 'persistent_notification'
|
DOMAIN = 'persistent_notification'
|
||||||
ENTITY_ID_FORMAT = DOMAIN + '.{}'
|
ENTITY_ID_FORMAT = DOMAIN + '.{}'
|
||||||
@ -38,12 +39,12 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
|
|
||||||
def create(hass, message, title=None, notification_id=None):
|
def create(hass, message, title=None, notification_id=None):
|
||||||
"""Generate a notification."""
|
"""Generate a notification."""
|
||||||
run_coroutine_threadsafe(
|
run_callback_threadsafe(
|
||||||
async_create(hass, message, title, notification_id), hass.loop
|
hass.loop, async_create, hass, message, title, notification_id
|
||||||
).result()
|
).result()
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
@callback
|
||||||
def async_create(hass, message, title=None, notification_id=None):
|
def async_create(hass, message, title=None, notification_id=None):
|
||||||
"""Generate a notification."""
|
"""Generate a notification."""
|
||||||
data = {
|
data = {
|
||||||
@ -54,11 +55,14 @@ def async_create(hass, message, title=None, notification_id=None):
|
|||||||
] if value is not None
|
] if value is not None
|
||||||
}
|
}
|
||||||
|
|
||||||
yield from hass.services.async_call(DOMAIN, SERVICE_CREATE, data)
|
hass.loop.create_task(
|
||||||
|
hass.services.async_call(DOMAIN, SERVICE_CREATE, data))
|
||||||
|
|
||||||
|
|
||||||
def setup(hass, config):
|
@asyncio.coroutine
|
||||||
|
def async_setup(hass, config):
|
||||||
"""Setup the persistent notification component."""
|
"""Setup the persistent notification component."""
|
||||||
|
@callback
|
||||||
def create_service(call):
|
def create_service(call):
|
||||||
"""Handle a create notification service call."""
|
"""Handle a create notification service call."""
|
||||||
title = call.data.get(ATTR_TITLE)
|
title = call.data.get(ATTR_TITLE)
|
||||||
@ -68,13 +72,13 @@ def setup(hass, config):
|
|||||||
if notification_id is not None:
|
if notification_id is not None:
|
||||||
entity_id = ENTITY_ID_FORMAT.format(slugify(notification_id))
|
entity_id = ENTITY_ID_FORMAT.format(slugify(notification_id))
|
||||||
else:
|
else:
|
||||||
entity_id = generate_entity_id(ENTITY_ID_FORMAT, DEFAULT_OBJECT_ID,
|
entity_id = async_generate_entity_id(
|
||||||
hass=hass)
|
ENTITY_ID_FORMAT, DEFAULT_OBJECT_ID, hass=hass)
|
||||||
attr = {}
|
attr = {}
|
||||||
if title is not None:
|
if title is not None:
|
||||||
try:
|
try:
|
||||||
title.hass = hass
|
title.hass = hass
|
||||||
title = title.render()
|
title = title.async_render()
|
||||||
except TemplateError as ex:
|
except TemplateError as ex:
|
||||||
_LOGGER.error('Error rendering title %s: %s', title, ex)
|
_LOGGER.error('Error rendering title %s: %s', title, ex)
|
||||||
title = title.template
|
title = title.template
|
||||||
@ -83,17 +87,19 @@ def setup(hass, config):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
message.hass = hass
|
message.hass = hass
|
||||||
message = message.render()
|
message = message.async_render()
|
||||||
except TemplateError as ex:
|
except TemplateError as ex:
|
||||||
_LOGGER.error('Error rendering message %s: %s', message, ex)
|
_LOGGER.error('Error rendering message %s: %s', message, ex)
|
||||||
message = message.template
|
message = message.template
|
||||||
|
|
||||||
hass.states.set(entity_id, message, attr)
|
hass.states.async_set(entity_id, message, attr)
|
||||||
|
|
||||||
descriptions = load_yaml_config_file(
|
descriptions = yield from hass.loop.run_in_executor(
|
||||||
os.path.join(os.path.dirname(__file__), 'services.yaml'))
|
None, load_yaml_config_file, os.path.join(
|
||||||
hass.services.register(DOMAIN, SERVICE_CREATE, create_service,
|
os.path.dirname(__file__), 'services.yaml')
|
||||||
descriptions[DOMAIN][SERVICE_CREATE],
|
)
|
||||||
SCHEMA_SERVICE_CREATE)
|
hass.services.async_register(DOMAIN, SERVICE_CREATE, create_service,
|
||||||
|
descriptions[DOMAIN][SERVICE_CREATE],
|
||||||
|
SCHEMA_SERVICE_CREATE)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
"""Module to help with parsing and generating configuration files."""
|
"""Module to help with parsing and generating configuration files."""
|
||||||
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
@ -180,6 +181,24 @@ def create_default_config(config_dir, detect_location=True):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def async_hass_config_yaml(hass):
|
||||||
|
"""Load YAML from hass config File.
|
||||||
|
|
||||||
|
This function allow component inside asyncio loop to reload his config by
|
||||||
|
self.
|
||||||
|
|
||||||
|
This method is a coroutine.
|
||||||
|
"""
|
||||||
|
def _load_hass_yaml_config():
|
||||||
|
path = find_config_file(hass.config.config_dir)
|
||||||
|
conf = load_yaml_config_file(path)
|
||||||
|
return conf
|
||||||
|
|
||||||
|
conf = yield from hass.loop.run_in_executor(None, _load_hass_yaml_config)
|
||||||
|
return conf
|
||||||
|
|
||||||
|
|
||||||
def find_config_file(config_dir):
|
def find_config_file(config_dir):
|
||||||
"""Look in given directory for supported configuration files."""
|
"""Look in given directory for supported configuration files."""
|
||||||
config_path = os.path.join(config_dir, YAML_CONFIG_FILE)
|
config_path = os.path.join(config_dir, YAML_CONFIG_FILE)
|
||||||
@ -201,7 +220,11 @@ def load_yaml_config_file(config_path):
|
|||||||
|
|
||||||
|
|
||||||
def process_ha_config_upgrade(hass):
|
def process_ha_config_upgrade(hass):
|
||||||
"""Upgrade config if necessary."""
|
"""Upgrade config if necessary.
|
||||||
|
|
||||||
|
Asyncio don't support file operation jet.
|
||||||
|
This method need to run in a executor.
|
||||||
|
"""
|
||||||
version_path = hass.config.path(VERSION_FILE)
|
version_path = hass.config.path(VERSION_FILE)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -225,8 +248,12 @@ def process_ha_config_upgrade(hass):
|
|||||||
outp.write(__version__)
|
outp.write(__version__)
|
||||||
|
|
||||||
|
|
||||||
def process_ha_core_config(hass, config):
|
@asyncio.coroutine
|
||||||
"""Process the [homeassistant] section from the config."""
|
def async_process_ha_core_config(hass, config):
|
||||||
|
"""Process the [homeassistant] section from the config.
|
||||||
|
|
||||||
|
This method is a coroutine.
|
||||||
|
"""
|
||||||
# pylint: disable=too-many-branches
|
# pylint: disable=too-many-branches
|
||||||
config = CORE_CONFIG_SCHEMA(config)
|
config = CORE_CONFIG_SCHEMA(config)
|
||||||
hac = hass.config
|
hac = hass.config
|
||||||
@ -282,7 +309,8 @@ def process_ha_core_config(hass, config):
|
|||||||
# If we miss some of the needed values, auto detect them
|
# If we miss some of the needed values, auto detect them
|
||||||
if None in (hac.latitude, hac.longitude, hac.units,
|
if None in (hac.latitude, hac.longitude, hac.units,
|
||||||
hac.time_zone):
|
hac.time_zone):
|
||||||
info = loc_util.detect_location_info()
|
info = yield from hass.loop.run_in_executor(
|
||||||
|
None, loc_util.detect_location_info)
|
||||||
|
|
||||||
if info is None:
|
if info is None:
|
||||||
_LOGGER.error('Could not detect location information')
|
_LOGGER.error('Could not detect location information')
|
||||||
@ -307,7 +335,8 @@ def process_ha_core_config(hass, config):
|
|||||||
|
|
||||||
if hac.elevation is None and hac.latitude is not None and \
|
if hac.elevation is None and hac.latitude is not None and \
|
||||||
hac.longitude is not None:
|
hac.longitude is not None:
|
||||||
elevation = loc_util.elevation(hac.latitude, hac.longitude)
|
elevation = yield from hass.loop.run_in_executor(
|
||||||
|
None, loc_util.elevation, hac.latitude, hac.longitude)
|
||||||
hac.elevation = elevation
|
hac.elevation = elevation
|
||||||
discovered.append(('elevation', elevation))
|
discovered.append(('elevation', elevation))
|
||||||
|
|
||||||
|
@ -56,7 +56,10 @@ def async_generate_entity_id(entity_id_format: str, name: Optional[str],
|
|||||||
|
|
||||||
|
|
||||||
def set_customize(customize: Dict[str, Any]) -> None:
|
def set_customize(customize: Dict[str, Any]) -> None:
|
||||||
"""Overwrite all current customize settings."""
|
"""Overwrite all current customize settings.
|
||||||
|
|
||||||
|
Async friendly.
|
||||||
|
"""
|
||||||
global _OVERWRITE
|
global _OVERWRITE
|
||||||
|
|
||||||
_OVERWRITE = {key.lower(): val for key, val in customize.items()}
|
_OVERWRITE = {key.lower(): val for key, val in customize.items()}
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
from homeassistant import config as conf_util
|
from homeassistant import config as conf_util
|
||||||
from homeassistant.bootstrap import (prepare_setup_platform,
|
from homeassistant.bootstrap import (
|
||||||
prepare_setup_component)
|
async_prepare_setup_platform, async_prepare_setup_component)
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_ENTITY_ID, CONF_SCAN_INTERVAL, CONF_ENTITY_NAMESPACE,
|
ATTR_ENTITY_ID, CONF_SCAN_INTERVAL, CONF_ENTITY_NAMESPACE,
|
||||||
DEVICE_DEFAULT_NAME)
|
DEVICE_DEFAULT_NAME)
|
||||||
@ -118,10 +118,8 @@ class EntityComponent(object):
|
|||||||
|
|
||||||
This method must be run in the event loop.
|
This method must be run in the event loop.
|
||||||
"""
|
"""
|
||||||
platform = yield from self.hass.loop.run_in_executor(
|
platform = yield from async_prepare_setup_platform(
|
||||||
None, prepare_setup_platform, self.hass, self.config, self.domain,
|
self.hass, self.config, self.domain, platform_type)
|
||||||
platform_type
|
|
||||||
)
|
|
||||||
|
|
||||||
if platform is None:
|
if platform is None:
|
||||||
return
|
return
|
||||||
@ -238,20 +236,8 @@ class EntityComponent(object):
|
|||||||
|
|
||||||
def prepare_reload(self):
|
def prepare_reload(self):
|
||||||
"""Prepare reloading this entity component."""
|
"""Prepare reloading this entity component."""
|
||||||
try:
|
return run_coroutine_threadsafe(
|
||||||
path = conf_util.find_config_file(self.hass.config.config_dir)
|
self.async_prepare_reload(), loop=self.hass.loop).result()
|
||||||
conf = conf_util.load_yaml_config_file(path)
|
|
||||||
except HomeAssistantError as err:
|
|
||||||
self.logger.error(err)
|
|
||||||
return None
|
|
||||||
|
|
||||||
conf = prepare_setup_component(self.hass, conf, self.domain)
|
|
||||||
|
|
||||||
if conf is None:
|
|
||||||
return None
|
|
||||||
|
|
||||||
self.reset()
|
|
||||||
return conf
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_prepare_reload(self):
|
def async_prepare_reload(self):
|
||||||
@ -259,9 +245,20 @@ class EntityComponent(object):
|
|||||||
|
|
||||||
This method must be run in the event loop.
|
This method must be run in the event loop.
|
||||||
"""
|
"""
|
||||||
conf = yield from self.hass.loop.run_in_executor(
|
try:
|
||||||
None, self.prepare_reload
|
conf = yield from \
|
||||||
)
|
conf_util.async_hass_config_yaml(self.hass)
|
||||||
|
except HomeAssistantError as err:
|
||||||
|
self.logger.error(err)
|
||||||
|
return None
|
||||||
|
|
||||||
|
conf = yield from async_prepare_setup_component(
|
||||||
|
self.hass, conf, self.domain)
|
||||||
|
|
||||||
|
if conf is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
yield from self.async_reset()
|
||||||
return conf
|
return conf
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,7 +40,11 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
def prepare(hass: 'HomeAssistant'):
|
def prepare(hass: 'HomeAssistant'):
|
||||||
"""Prepare the loading of components."""
|
"""Prepare the loading of components.
|
||||||
|
|
||||||
|
Asyncio don't support file operation jet.
|
||||||
|
This method need to run in a executor.
|
||||||
|
"""
|
||||||
global PREPARED # pylint: disable=global-statement
|
global PREPARED # pylint: disable=global-statement
|
||||||
|
|
||||||
# Load the built-in components
|
# Load the built-in components
|
||||||
@ -81,14 +85,20 @@ def prepare(hass: 'HomeAssistant'):
|
|||||||
|
|
||||||
|
|
||||||
def set_component(comp_name: str, component: ModuleType) -> None:
|
def set_component(comp_name: str, component: ModuleType) -> None:
|
||||||
"""Set a component in the cache."""
|
"""Set a component in the cache.
|
||||||
|
|
||||||
|
Async friendly.
|
||||||
|
"""
|
||||||
_check_prepared()
|
_check_prepared()
|
||||||
|
|
||||||
_COMPONENT_CACHE[comp_name] = component
|
_COMPONENT_CACHE[comp_name] = component
|
||||||
|
|
||||||
|
|
||||||
def get_platform(domain: str, platform: str) -> Optional[ModuleType]:
|
def get_platform(domain: str, platform: str) -> Optional[ModuleType]:
|
||||||
"""Try to load specified platform."""
|
"""Try to load specified platform.
|
||||||
|
|
||||||
|
Async friendly.
|
||||||
|
"""
|
||||||
return get_component(PLATFORM_FORMAT.format(domain, platform))
|
return get_component(PLATFORM_FORMAT.format(domain, platform))
|
||||||
|
|
||||||
|
|
||||||
@ -97,6 +107,8 @@ def get_component(comp_name) -> Optional[ModuleType]:
|
|||||||
|
|
||||||
Looks in config dir first, then built-in components.
|
Looks in config dir first, then built-in components.
|
||||||
Only returns it if also found to be valid.
|
Only returns it if also found to be valid.
|
||||||
|
|
||||||
|
Async friendly.
|
||||||
"""
|
"""
|
||||||
if comp_name in _COMPONENT_CACHE:
|
if comp_name in _COMPONENT_CACHE:
|
||||||
return _COMPONENT_CACHE[comp_name]
|
return _COMPONENT_CACHE[comp_name]
|
||||||
@ -166,6 +178,8 @@ def load_order_components(components: Sequence[str]) -> OrderedSet:
|
|||||||
- Will ensure that all components that do not directly depend on
|
- Will ensure that all components that do not directly depend on
|
||||||
the group component will be loaded before the group component.
|
the group component will be loaded before the group component.
|
||||||
- returns an OrderedSet load order.
|
- returns an OrderedSet load order.
|
||||||
|
|
||||||
|
Async friendly.
|
||||||
"""
|
"""
|
||||||
_check_prepared()
|
_check_prepared()
|
||||||
|
|
||||||
@ -192,13 +206,18 @@ def load_order_component(comp_name: str) -> OrderedSet:
|
|||||||
|
|
||||||
Raises HomeAssistantError if a circular dependency is detected.
|
Raises HomeAssistantError if a circular dependency is detected.
|
||||||
Returns an empty list if component could not be loaded.
|
Returns an empty list if component could not be loaded.
|
||||||
|
|
||||||
|
Async friendly.
|
||||||
"""
|
"""
|
||||||
return _load_order_component(comp_name, OrderedSet(), set())
|
return _load_order_component(comp_name, OrderedSet(), set())
|
||||||
|
|
||||||
|
|
||||||
def _load_order_component(comp_name: str, load_order: OrderedSet,
|
def _load_order_component(comp_name: str, load_order: OrderedSet,
|
||||||
loading: Set) -> OrderedSet:
|
loading: Set) -> OrderedSet:
|
||||||
"""Recursive function to get load order of components."""
|
"""Recursive function to get load order of components.
|
||||||
|
|
||||||
|
Async friendly.
|
||||||
|
"""
|
||||||
component = get_component(comp_name)
|
component = get_component(comp_name)
|
||||||
|
|
||||||
# If None it does not exist, error already thrown by get_component.
|
# If None it does not exist, error already thrown by get_component.
|
||||||
@ -235,7 +254,10 @@ def _load_order_component(comp_name: str, load_order: OrderedSet,
|
|||||||
|
|
||||||
|
|
||||||
def _check_prepared() -> None:
|
def _check_prepared() -> None:
|
||||||
"""Issue a warning if loader.prepare() has never been called."""
|
"""Issue a warning if loader.prepare() has never been called.
|
||||||
|
|
||||||
|
Async friendly.
|
||||||
|
"""
|
||||||
if not PREPARED:
|
if not PREPARED:
|
||||||
_LOGGER.warning((
|
_LOGGER.warning((
|
||||||
"You did not call loader.prepare() yet. "
|
"You did not call loader.prepare() yet. "
|
||||||
|
@ -26,8 +26,8 @@ MOCKS = {
|
|||||||
'load*': ("homeassistant.config.load_yaml", yaml.load_yaml),
|
'load*': ("homeassistant.config.load_yaml", yaml.load_yaml),
|
||||||
'get': ("homeassistant.loader.get_component", loader.get_component),
|
'get': ("homeassistant.loader.get_component", loader.get_component),
|
||||||
'secrets': ("homeassistant.util.yaml._secret_yaml", yaml._secret_yaml),
|
'secrets': ("homeassistant.util.yaml._secret_yaml", yaml._secret_yaml),
|
||||||
'except': ("homeassistant.bootstrap.log_exception",
|
'except': ("homeassistant.bootstrap.async_log_exception",
|
||||||
bootstrap.log_exception)
|
bootstrap.async_log_exception)
|
||||||
}
|
}
|
||||||
SILENCE = (
|
SILENCE = (
|
||||||
'homeassistant.bootstrap.clear_secret_cache',
|
'homeassistant.bootstrap.clear_secret_cache',
|
||||||
@ -185,9 +185,15 @@ def check(config_path):
|
|||||||
# Test if platform/component and overwrite setup
|
# Test if platform/component and overwrite setup
|
||||||
if '.' in comp_name:
|
if '.' in comp_name:
|
||||||
module.setup_platform = mock_setup
|
module.setup_platform = mock_setup
|
||||||
|
|
||||||
|
if hasattr(module, 'async_setup_platform'):
|
||||||
|
del module.async_setup_platform
|
||||||
else:
|
else:
|
||||||
module.setup = mock_setup
|
module.setup = mock_setup
|
||||||
|
|
||||||
|
if hasattr(module, 'async_setup'):
|
||||||
|
del module.async_setup
|
||||||
|
|
||||||
return module
|
return module
|
||||||
|
|
||||||
def mock_secrets(ldr, node): # pylint: disable=unused-variable
|
def mock_secrets(ldr, node): # pylint: disable=unused-variable
|
||||||
|
@ -23,7 +23,10 @@ DATETIME_RE = re.compile(
|
|||||||
|
|
||||||
|
|
||||||
def set_default_time_zone(time_zone: dt.tzinfo) -> None:
|
def set_default_time_zone(time_zone: dt.tzinfo) -> None:
|
||||||
"""Set a default time zone to be used when none is specified."""
|
"""Set a default time zone to be used when none is specified.
|
||||||
|
|
||||||
|
Async friendly.
|
||||||
|
"""
|
||||||
global DEFAULT_TIME_ZONE # pylint: disable=global-statement
|
global DEFAULT_TIME_ZONE # pylint: disable=global-statement
|
||||||
|
|
||||||
# NOTE: Remove in the future in favour of typing
|
# NOTE: Remove in the future in favour of typing
|
||||||
@ -33,7 +36,10 @@ def set_default_time_zone(time_zone: dt.tzinfo) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def get_time_zone(time_zone_str: str) -> Optional[dt.tzinfo]:
|
def get_time_zone(time_zone_str: str) -> Optional[dt.tzinfo]:
|
||||||
"""Get time zone from string. Return None if unable to determine."""
|
"""Get time zone from string. Return None if unable to determine.
|
||||||
|
|
||||||
|
Async friendly.
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
return pytz.timezone(time_zone_str)
|
return pytz.timezone(time_zone_str)
|
||||||
except pytz.exceptions.UnknownTimeZoneError:
|
except pytz.exceptions.UnknownTimeZoneError:
|
||||||
|
@ -49,7 +49,10 @@ def load_yaml(fname: str) -> Union[List, Dict]:
|
|||||||
|
|
||||||
|
|
||||||
def clear_secret_cache() -> None:
|
def clear_secret_cache() -> None:
|
||||||
"""Clear the secret cache."""
|
"""Clear the secret cache.
|
||||||
|
|
||||||
|
Async friendly.
|
||||||
|
"""
|
||||||
__SECRET_CACHE.clear()
|
__SECRET_CACHE.clear()
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,7 +10,8 @@ import threading
|
|||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
|
||||||
from homeassistant import core as ha, loader
|
from homeassistant import core as ha, loader
|
||||||
from homeassistant.bootstrap import setup_component, prepare_setup_component
|
from homeassistant.bootstrap import (
|
||||||
|
setup_component, async_prepare_setup_component)
|
||||||
from homeassistant.helpers.entity import ToggleEntity
|
from homeassistant.helpers.entity import ToggleEntity
|
||||||
from homeassistant.util.unit_system import METRIC_SYSTEM
|
from homeassistant.util.unit_system import METRIC_SYSTEM
|
||||||
import homeassistant.util.dt as date_util
|
import homeassistant.util.dt as date_util
|
||||||
@ -234,6 +235,7 @@ class MockModule(object):
|
|||||||
self.DOMAIN = domain
|
self.DOMAIN = domain
|
||||||
self.DEPENDENCIES = dependencies or []
|
self.DEPENDENCIES = dependencies or []
|
||||||
self.REQUIREMENTS = requirements or []
|
self.REQUIREMENTS = requirements or []
|
||||||
|
self._setup = setup
|
||||||
|
|
||||||
if config_schema is not None:
|
if config_schema is not None:
|
||||||
self.CONFIG_SCHEMA = config_schema
|
self.CONFIG_SCHEMA = config_schema
|
||||||
@ -241,11 +243,11 @@ class MockModule(object):
|
|||||||
if platform_schema is not None:
|
if platform_schema is not None:
|
||||||
self.PLATFORM_SCHEMA = platform_schema
|
self.PLATFORM_SCHEMA = platform_schema
|
||||||
|
|
||||||
# Setup a mock setup if none given.
|
def setup(self, hass, config):
|
||||||
if setup is None:
|
"""Setup the component."""
|
||||||
self.setup = lambda hass, config: True
|
if self._setup is not None:
|
||||||
else:
|
return self._setup(hass, config)
|
||||||
self.setup = setup
|
return True
|
||||||
|
|
||||||
|
|
||||||
class MockPlatform(object):
|
class MockPlatform(object):
|
||||||
@ -366,16 +368,19 @@ def assert_setup_component(count, domain=None):
|
|||||||
"""
|
"""
|
||||||
config = {}
|
config = {}
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
def mock_psc(hass, config_input, domain):
|
def mock_psc(hass, config_input, domain):
|
||||||
"""Mock the prepare_setup_component to capture config."""
|
"""Mock the prepare_setup_component to capture config."""
|
||||||
res = prepare_setup_component(hass, config_input, domain)
|
res = yield from async_prepare_setup_component(
|
||||||
|
hass, config_input, domain)
|
||||||
config[domain] = None if res is None else res.get(domain)
|
config[domain] = None if res is None else res.get(domain)
|
||||||
_LOGGER.debug('Configuration for %s, Validated: %s, Original %s',
|
_LOGGER.debug('Configuration for %s, Validated: %s, Original %s',
|
||||||
domain, config[domain], config_input.get(domain))
|
domain, config[domain], config_input.get(domain))
|
||||||
return res
|
return res
|
||||||
|
|
||||||
assert isinstance(config, dict)
|
assert isinstance(config, dict)
|
||||||
with patch('homeassistant.bootstrap.prepare_setup_component', mock_psc):
|
with patch('homeassistant.bootstrap.async_prepare_setup_component',
|
||||||
|
mock_psc):
|
||||||
yield config
|
yield config
|
||||||
|
|
||||||
if domain is None:
|
if domain is None:
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"""The tests for the Event automation."""
|
"""The tests for the Event automation."""
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from homeassistant.bootstrap import _setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
import homeassistant.components.automation as automation
|
import homeassistant.components.automation as automation
|
||||||
|
|
||||||
from tests.common import get_test_home_assistant
|
from tests.common import get_test_home_assistant
|
||||||
@ -28,7 +28,7 @@ class TestAutomationEvent(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fires_on_event(self):
|
def test_if_fires_on_event(self):
|
||||||
"""Test the firing of events."""
|
"""Test the firing of events."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'event',
|
'platform': 'event',
|
||||||
@ -53,7 +53,7 @@ class TestAutomationEvent(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fires_on_event_with_data(self):
|
def test_if_fires_on_event_with_data(self):
|
||||||
"""Test the firing of events with data."""
|
"""Test the firing of events with data."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'event',
|
'platform': 'event',
|
||||||
@ -73,7 +73,7 @@ class TestAutomationEvent(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_not_fires_if_event_data_not_matches(self):
|
def test_if_not_fires_if_event_data_not_matches(self):
|
||||||
"""Test firing of event if no match."""
|
"""Test firing of event if no match."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'event',
|
'platform': 'event',
|
||||||
|
@ -379,21 +379,22 @@ class TestAutomation(unittest.TestCase):
|
|||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
assert automation.is_on(self.hass, entity_id)
|
assert automation.is_on(self.hass, entity_id)
|
||||||
|
|
||||||
@patch('homeassistant.config.load_yaml_config_file', return_value={
|
@patch('homeassistant.config.load_yaml_config_file', autospec=True,
|
||||||
automation.DOMAIN: {
|
return_value={
|
||||||
'alias': 'bye',
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'alias': 'bye',
|
||||||
'platform': 'event',
|
'trigger': {
|
||||||
'event_type': 'test_event2',
|
'platform': 'event',
|
||||||
},
|
'event_type': 'test_event2',
|
||||||
'action': {
|
},
|
||||||
'service': 'test.automation',
|
'action': {
|
||||||
'data_template': {
|
'service': 'test.automation',
|
||||||
'event': '{{ trigger.event.event_type }}'
|
'data_template': {
|
||||||
|
'event': '{{ trigger.event.event_type }}'
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
|
||||||
})
|
|
||||||
def test_reload_config_service(self, mock_load_yaml):
|
def test_reload_config_service(self, mock_load_yaml):
|
||||||
"""Test the reload config service."""
|
"""Test the reload config service."""
|
||||||
assert setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
@ -443,9 +444,8 @@ class TestAutomation(unittest.TestCase):
|
|||||||
assert len(self.calls) == 2
|
assert len(self.calls) == 2
|
||||||
assert self.calls[1].data.get('event') == 'test_event2'
|
assert self.calls[1].data.get('event') == 'test_event2'
|
||||||
|
|
||||||
@patch('homeassistant.config.load_yaml_config_file', return_value={
|
@patch('homeassistant.config.load_yaml_config_file', autospec=True,
|
||||||
automation.DOMAIN: 'not valid',
|
return_value={automation.DOMAIN: 'not valid'})
|
||||||
})
|
|
||||||
def test_reload_config_when_invalid_config(self, mock_load_yaml):
|
def test_reload_config_when_invalid_config(self, mock_load_yaml):
|
||||||
"""Test the reload config service handling invalid config."""
|
"""Test the reload config service handling invalid config."""
|
||||||
with assert_setup_component(1):
|
with assert_setup_component(1):
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"""The tests for the MQTT automation."""
|
"""The tests for the MQTT automation."""
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from homeassistant.bootstrap import _setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
import homeassistant.components.automation as automation
|
import homeassistant.components.automation as automation
|
||||||
from tests.common import (
|
from tests.common import (
|
||||||
mock_mqtt_component, fire_mqtt_message, get_test_home_assistant)
|
mock_mqtt_component, fire_mqtt_message, get_test_home_assistant)
|
||||||
@ -28,7 +28,7 @@ class TestAutomationMQTT(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fires_on_topic_match(self):
|
def test_if_fires_on_topic_match(self):
|
||||||
"""Test if message is fired on topic match."""
|
"""Test if message is fired on topic match."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
@ -58,7 +58,7 @@ class TestAutomationMQTT(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fires_on_topic_and_payload_match(self):
|
def test_if_fires_on_topic_and_payload_match(self):
|
||||||
"""Test if message is fired on topic and payload match."""
|
"""Test if message is fired on topic and payload match."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
@ -77,7 +77,7 @@ class TestAutomationMQTT(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_not_fires_on_topic_but_no_payload_match(self):
|
def test_if_not_fires_on_topic_but_no_payload_match(self):
|
||||||
"""Test if message is not fired on topic but no payload."""
|
"""Test if message is not fired on topic but no payload."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"""The tests for numeric state automation."""
|
"""The tests for numeric state automation."""
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from homeassistant.bootstrap import _setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
import homeassistant.components.automation as automation
|
import homeassistant.components.automation as automation
|
||||||
|
|
||||||
from tests.common import get_test_home_assistant
|
from tests.common import get_test_home_assistant
|
||||||
@ -28,7 +28,7 @@ class TestAutomationNumericState(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fires_on_entity_change_below(self):
|
def test_if_fires_on_entity_change_below(self):
|
||||||
""""Test the firing with changed entity."""
|
""""Test the firing with changed entity."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'numeric_state',
|
'platform': 'numeric_state',
|
||||||
@ -58,7 +58,7 @@ class TestAutomationNumericState(unittest.TestCase):
|
|||||||
self.hass.states.set('test.entity', 11)
|
self.hass.states.set('test.entity', 11)
|
||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
|
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'numeric_state',
|
'platform': 'numeric_state',
|
||||||
@ -81,7 +81,7 @@ class TestAutomationNumericState(unittest.TestCase):
|
|||||||
self.hass.states.set('test.entity', 9)
|
self.hass.states.set('test.entity', 9)
|
||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
|
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'numeric_state',
|
'platform': 'numeric_state',
|
||||||
@ -101,7 +101,7 @@ class TestAutomationNumericState(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fires_on_entity_change_above(self):
|
def test_if_fires_on_entity_change_above(self):
|
||||||
""""Test the firing with changed entity."""
|
""""Test the firing with changed entity."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'numeric_state',
|
'platform': 'numeric_state',
|
||||||
@ -124,7 +124,7 @@ class TestAutomationNumericState(unittest.TestCase):
|
|||||||
self.hass.states.set('test.entity', 9)
|
self.hass.states.set('test.entity', 9)
|
||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
|
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'numeric_state',
|
'platform': 'numeric_state',
|
||||||
@ -148,7 +148,7 @@ class TestAutomationNumericState(unittest.TestCase):
|
|||||||
self.hass.states.set('test.entity', 11)
|
self.hass.states.set('test.entity', 11)
|
||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
|
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'numeric_state',
|
'platform': 'numeric_state',
|
||||||
@ -168,7 +168,7 @@ class TestAutomationNumericState(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fires_on_entity_change_below_range(self):
|
def test_if_fires_on_entity_change_below_range(self):
|
||||||
""""Test the firing with changed entity."""
|
""""Test the firing with changed entity."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'numeric_state',
|
'platform': 'numeric_state',
|
||||||
@ -188,7 +188,7 @@ class TestAutomationNumericState(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fires_on_entity_change_below_above_range(self):
|
def test_if_fires_on_entity_change_below_above_range(self):
|
||||||
""""Test the firing with changed entity."""
|
""""Test the firing with changed entity."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'numeric_state',
|
'platform': 'numeric_state',
|
||||||
@ -211,7 +211,7 @@ class TestAutomationNumericState(unittest.TestCase):
|
|||||||
self.hass.states.set('test.entity', 11)
|
self.hass.states.set('test.entity', 11)
|
||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
|
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'numeric_state',
|
'platform': 'numeric_state',
|
||||||
@ -235,7 +235,7 @@ class TestAutomationNumericState(unittest.TestCase):
|
|||||||
self.hass.states.set('test.entity', 11)
|
self.hass.states.set('test.entity', 11)
|
||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
|
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'numeric_state',
|
'platform': 'numeric_state',
|
||||||
@ -256,7 +256,7 @@ class TestAutomationNumericState(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_not_fires_if_entity_not_match(self):
|
def test_if_not_fires_if_entity_not_match(self):
|
||||||
""""Test if not fired with non matching entity."""
|
""""Test if not fired with non matching entity."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'numeric_state',
|
'platform': 'numeric_state',
|
||||||
@ -275,7 +275,7 @@ class TestAutomationNumericState(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fires_on_entity_change_below_with_attribute(self):
|
def test_if_fires_on_entity_change_below_with_attribute(self):
|
||||||
""""Test attributes change."""
|
""""Test attributes change."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'numeric_state',
|
'platform': 'numeric_state',
|
||||||
@ -294,7 +294,7 @@ class TestAutomationNumericState(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_not_fires_on_entity_change_not_below_with_attribute(self):
|
def test_if_not_fires_on_entity_change_not_below_with_attribute(self):
|
||||||
""""Test attributes."""
|
""""Test attributes."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'numeric_state',
|
'platform': 'numeric_state',
|
||||||
@ -313,7 +313,7 @@ class TestAutomationNumericState(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fires_on_attribute_change_with_attribute_below(self):
|
def test_if_fires_on_attribute_change_with_attribute_below(self):
|
||||||
""""Test attributes change."""
|
""""Test attributes change."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'numeric_state',
|
'platform': 'numeric_state',
|
||||||
@ -333,7 +333,7 @@ class TestAutomationNumericState(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_not_fires_on_attribute_change_with_attribute_not_below(self):
|
def test_if_not_fires_on_attribute_change_with_attribute_not_below(self):
|
||||||
""""Test attributes change."""
|
""""Test attributes change."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'numeric_state',
|
'platform': 'numeric_state',
|
||||||
@ -353,7 +353,7 @@ class TestAutomationNumericState(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_not_fires_on_entity_change_with_attribute_below(self):
|
def test_if_not_fires_on_entity_change_with_attribute_below(self):
|
||||||
""""Test attributes change."""
|
""""Test attributes change."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'numeric_state',
|
'platform': 'numeric_state',
|
||||||
@ -373,7 +373,7 @@ class TestAutomationNumericState(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_not_fires_on_entity_change_with_not_attribute_below(self):
|
def test_if_not_fires_on_entity_change_with_not_attribute_below(self):
|
||||||
""""Test attributes change."""
|
""""Test attributes change."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'numeric_state',
|
'platform': 'numeric_state',
|
||||||
@ -393,7 +393,7 @@ class TestAutomationNumericState(unittest.TestCase):
|
|||||||
|
|
||||||
def test_fires_on_attr_change_with_attribute_below_and_multiple_attr(self):
|
def test_fires_on_attr_change_with_attribute_below_and_multiple_attr(self):
|
||||||
""""Test attributes change."""
|
""""Test attributes change."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'numeric_state',
|
'platform': 'numeric_state',
|
||||||
@ -414,7 +414,7 @@ class TestAutomationNumericState(unittest.TestCase):
|
|||||||
|
|
||||||
def test_template_list(self):
|
def test_template_list(self):
|
||||||
""""Test template list."""
|
""""Test template list."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'numeric_state',
|
'platform': 'numeric_state',
|
||||||
@ -436,7 +436,7 @@ class TestAutomationNumericState(unittest.TestCase):
|
|||||||
|
|
||||||
def test_template_string(self):
|
def test_template_string(self):
|
||||||
""""Test template string."""
|
""""Test template string."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'numeric_state',
|
'platform': 'numeric_state',
|
||||||
@ -469,7 +469,7 @@ class TestAutomationNumericState(unittest.TestCase):
|
|||||||
|
|
||||||
def test_not_fires_on_attr_change_with_attr_not_below_multiple_attr(self):
|
def test_not_fires_on_attr_change_with_attr_not_below_multiple_attr(self):
|
||||||
""""Test if not fired changed attributes."""
|
""""Test if not fired changed attributes."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'numeric_state',
|
'platform': 'numeric_state',
|
||||||
@ -492,7 +492,7 @@ class TestAutomationNumericState(unittest.TestCase):
|
|||||||
""""Test if action."""
|
""""Test if action."""
|
||||||
entity_id = 'domain.test_entity'
|
entity_id = 'domain.test_entity'
|
||||||
test_state = 10
|
test_state = 10
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'event',
|
'platform': 'event',
|
||||||
|
@ -3,11 +3,12 @@ import unittest
|
|||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
from homeassistant.bootstrap import _setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
import homeassistant.util.dt as dt_util
|
import homeassistant.util.dt as dt_util
|
||||||
import homeassistant.components.automation as automation
|
import homeassistant.components.automation as automation
|
||||||
|
|
||||||
from tests.common import fire_time_changed, get_test_home_assistant
|
from tests.common import (
|
||||||
|
fire_time_changed, get_test_home_assistant, assert_setup_component)
|
||||||
|
|
||||||
|
|
||||||
class TestAutomationState(unittest.TestCase):
|
class TestAutomationState(unittest.TestCase):
|
||||||
@ -34,7 +35,7 @@ class TestAutomationState(unittest.TestCase):
|
|||||||
self.hass.states.set('test.entity', 'hello')
|
self.hass.states.set('test.entity', 'hello')
|
||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
|
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'state',
|
'platform': 'state',
|
||||||
@ -67,7 +68,7 @@ class TestAutomationState(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fires_on_entity_change_with_from_filter(self):
|
def test_if_fires_on_entity_change_with_from_filter(self):
|
||||||
"""Test for firing on entity change with filter."""
|
"""Test for firing on entity change with filter."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'state',
|
'platform': 'state',
|
||||||
@ -86,7 +87,7 @@ class TestAutomationState(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fires_on_entity_change_with_to_filter(self):
|
def test_if_fires_on_entity_change_with_to_filter(self):
|
||||||
"""Test for firing on entity change with no filter."""
|
"""Test for firing on entity change with no filter."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'state',
|
'platform': 'state',
|
||||||
@ -105,7 +106,7 @@ class TestAutomationState(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fires_on_entity_change_with_state_filter(self):
|
def test_if_fires_on_entity_change_with_state_filter(self):
|
||||||
"""Test for firing on entity change with state filter."""
|
"""Test for firing on entity change with state filter."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'state',
|
'platform': 'state',
|
||||||
@ -124,7 +125,7 @@ class TestAutomationState(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fires_on_entity_change_with_both_filters(self):
|
def test_if_fires_on_entity_change_with_both_filters(self):
|
||||||
"""Test for firing if both filters are a non match."""
|
"""Test for firing if both filters are a non match."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'state',
|
'platform': 'state',
|
||||||
@ -144,7 +145,7 @@ class TestAutomationState(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_not_fires_if_to_filter_not_match(self):
|
def test_if_not_fires_if_to_filter_not_match(self):
|
||||||
"""Test for not firing if to filter is not a match."""
|
"""Test for not firing if to filter is not a match."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'state',
|
'platform': 'state',
|
||||||
@ -166,7 +167,7 @@ class TestAutomationState(unittest.TestCase):
|
|||||||
"""Test for not firing if from filter is not a match."""
|
"""Test for not firing if from filter is not a match."""
|
||||||
self.hass.states.set('test.entity', 'bye')
|
self.hass.states.set('test.entity', 'bye')
|
||||||
|
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'state',
|
'platform': 'state',
|
||||||
@ -186,7 +187,7 @@ class TestAutomationState(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_not_fires_if_entity_not_match(self):
|
def test_if_not_fires_if_entity_not_match(self):
|
||||||
"""Test for not firing if entity is not matching."""
|
"""Test for not firing if entity is not matching."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'state',
|
'platform': 'state',
|
||||||
@ -206,7 +207,7 @@ class TestAutomationState(unittest.TestCase):
|
|||||||
"""Test for to action."""
|
"""Test for to action."""
|
||||||
entity_id = 'domain.test_entity'
|
entity_id = 'domain.test_entity'
|
||||||
test_state = 'new_state'
|
test_state = 'new_state'
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'event',
|
'platform': 'event',
|
||||||
@ -237,68 +238,72 @@ class TestAutomationState(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fails_setup_if_to_boolean_value(self):
|
def test_if_fails_setup_if_to_boolean_value(self):
|
||||||
"""Test for setup failure for boolean to."""
|
"""Test for setup failure for boolean to."""
|
||||||
assert not _setup_component(self.hass, automation.DOMAIN, {
|
with assert_setup_component(0):
|
||||||
automation.DOMAIN: {
|
assert not setup_component(self.hass, automation.DOMAIN, {
|
||||||
'trigger': {
|
automation.DOMAIN: {
|
||||||
'platform': 'state',
|
'trigger': {
|
||||||
'entity_id': 'test.entity',
|
'platform': 'state',
|
||||||
'to': True,
|
'entity_id': 'test.entity',
|
||||||
},
|
'to': True,
|
||||||
'action': {
|
},
|
||||||
'service': 'homeassistant.turn_on',
|
'action': {
|
||||||
}
|
'service': 'homeassistant.turn_on',
|
||||||
}})
|
}
|
||||||
|
}})
|
||||||
|
|
||||||
def test_if_fails_setup_if_from_boolean_value(self):
|
def test_if_fails_setup_if_from_boolean_value(self):
|
||||||
"""Test for setup failure for boolean from."""
|
"""Test for setup failure for boolean from."""
|
||||||
assert not _setup_component(self.hass, automation.DOMAIN, {
|
with assert_setup_component(0):
|
||||||
automation.DOMAIN: {
|
assert not setup_component(self.hass, automation.DOMAIN, {
|
||||||
'trigger': {
|
automation.DOMAIN: {
|
||||||
'platform': 'state',
|
'trigger': {
|
||||||
'entity_id': 'test.entity',
|
'platform': 'state',
|
||||||
'from': True,
|
'entity_id': 'test.entity',
|
||||||
},
|
'from': True,
|
||||||
'action': {
|
},
|
||||||
'service': 'homeassistant.turn_on',
|
'action': {
|
||||||
}
|
'service': 'homeassistant.turn_on',
|
||||||
}})
|
}
|
||||||
|
}})
|
||||||
|
|
||||||
def test_if_fails_setup_bad_for(self):
|
def test_if_fails_setup_bad_for(self):
|
||||||
"""Test for setup failure for bad for."""
|
"""Test for setup failure for bad for."""
|
||||||
assert not _setup_component(self.hass, automation.DOMAIN, {
|
with assert_setup_component(0):
|
||||||
automation.DOMAIN: {
|
assert not setup_component(self.hass, automation.DOMAIN, {
|
||||||
'trigger': {
|
automation.DOMAIN: {
|
||||||
'platform': 'state',
|
'trigger': {
|
||||||
'entity_id': 'test.entity',
|
'platform': 'state',
|
||||||
'to': 'world',
|
'entity_id': 'test.entity',
|
||||||
'for': {
|
'to': 'world',
|
||||||
'invalid': 5
|
'for': {
|
||||||
|
'invalid': 5
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
'action': {
|
||||||
'action': {
|
'service': 'homeassistant.turn_on',
|
||||||
'service': 'homeassistant.turn_on',
|
}
|
||||||
}
|
}})
|
||||||
}})
|
|
||||||
|
|
||||||
def test_if_fails_setup_for_without_to(self):
|
def test_if_fails_setup_for_without_to(self):
|
||||||
"""Test for setup failures for missing to."""
|
"""Test for setup failures for missing to."""
|
||||||
assert not _setup_component(self.hass, automation.DOMAIN, {
|
with assert_setup_component(0):
|
||||||
automation.DOMAIN: {
|
assert not setup_component(self.hass, automation.DOMAIN, {
|
||||||
'trigger': {
|
automation.DOMAIN: {
|
||||||
'platform': 'state',
|
'trigger': {
|
||||||
'entity_id': 'test.entity',
|
'platform': 'state',
|
||||||
'for': {
|
'entity_id': 'test.entity',
|
||||||
'seconds': 5
|
'for': {
|
||||||
|
'seconds': 5
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
'action': {
|
||||||
'action': {
|
'service': 'homeassistant.turn_on',
|
||||||
'service': 'homeassistant.turn_on',
|
}
|
||||||
}
|
}})
|
||||||
}})
|
|
||||||
|
|
||||||
def test_if_not_fires_on_entity_change_with_for(self):
|
def test_if_not_fires_on_entity_change_with_for(self):
|
||||||
"""Test for not firing on entity change with for."""
|
"""Test for not firing on entity change with for."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'state',
|
'platform': 'state',
|
||||||
@ -324,7 +329,7 @@ class TestAutomationState(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fires_on_entity_change_with_for(self):
|
def test_if_fires_on_entity_change_with_for(self):
|
||||||
"""Test for firing on entity change with for."""
|
"""Test for firing on entity change with for."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'state',
|
'platform': 'state',
|
||||||
@ -353,7 +358,7 @@ class TestAutomationState(unittest.TestCase):
|
|||||||
with patch('homeassistant.core.dt_util.utcnow') as mock_utcnow:
|
with patch('homeassistant.core.dt_util.utcnow') as mock_utcnow:
|
||||||
mock_utcnow.return_value = point1
|
mock_utcnow.return_value = point1
|
||||||
self.hass.states.set('test.entity', 'on')
|
self.hass.states.set('test.entity', 'on')
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'event',
|
'platform': 'event',
|
||||||
@ -384,32 +389,34 @@ class TestAutomationState(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fails_setup_for_without_time(self):
|
def test_if_fails_setup_for_without_time(self):
|
||||||
"""Test for setup failure if no time is provided."""
|
"""Test for setup failure if no time is provided."""
|
||||||
assert not _setup_component(self.hass, automation.DOMAIN, {
|
with assert_setup_component(0):
|
||||||
automation.DOMAIN: {
|
assert not setup_component(self.hass, automation.DOMAIN, {
|
||||||
'trigger': {
|
automation.DOMAIN: {
|
||||||
'platform': 'event',
|
'trigger': {
|
||||||
'event_type': 'bla'
|
'platform': 'event',
|
||||||
},
|
'event_type': 'bla'
|
||||||
'condition': {
|
},
|
||||||
'platform': 'state',
|
'condition': {
|
||||||
'entity_id': 'test.entity',
|
'platform': 'state',
|
||||||
'state': 'on',
|
'entity_id': 'test.entity',
|
||||||
'for': {},
|
'state': 'on',
|
||||||
},
|
'for': {},
|
||||||
'action': {'service': 'test.automation'},
|
},
|
||||||
}})
|
'action': {'service': 'test.automation'},
|
||||||
|
}})
|
||||||
|
|
||||||
def test_if_fails_setup_for_without_entity(self):
|
def test_if_fails_setup_for_without_entity(self):
|
||||||
"""Test for setup failure if no entity is provided."""
|
"""Test for setup failure if no entity is provided."""
|
||||||
assert not _setup_component(self.hass, automation.DOMAIN, {
|
with assert_setup_component(0):
|
||||||
automation.DOMAIN: {
|
assert not setup_component(self.hass, automation.DOMAIN, {
|
||||||
'trigger': {'event_type': 'bla'},
|
automation.DOMAIN: {
|
||||||
'condition': {
|
'trigger': {'event_type': 'bla'},
|
||||||
'platform': 'state',
|
'condition': {
|
||||||
'state': 'on',
|
'platform': 'state',
|
||||||
'for': {
|
'state': 'on',
|
||||||
'seconds': 5
|
'for': {
|
||||||
|
'seconds': 5
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
'action': {'service': 'test.automation'},
|
||||||
'action': {'service': 'test.automation'},
|
}})
|
||||||
}})
|
|
||||||
|
@ -3,7 +3,7 @@ from datetime import datetime
|
|||||||
import unittest
|
import unittest
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
from homeassistant.bootstrap import _setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
from homeassistant.components import sun
|
from homeassistant.components import sun
|
||||||
import homeassistant.components.automation as automation
|
import homeassistant.components.automation as automation
|
||||||
import homeassistant.util.dt as dt_util
|
import homeassistant.util.dt as dt_util
|
||||||
@ -42,7 +42,7 @@ class TestAutomationSun(unittest.TestCase):
|
|||||||
|
|
||||||
with patch('homeassistant.util.dt.utcnow',
|
with patch('homeassistant.util.dt.utcnow',
|
||||||
return_value=now):
|
return_value=now):
|
||||||
_setup_component(self.hass, automation.DOMAIN, {
|
setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'sun',
|
'platform': 'sun',
|
||||||
@ -81,7 +81,7 @@ class TestAutomationSun(unittest.TestCase):
|
|||||||
|
|
||||||
with patch('homeassistant.util.dt.utcnow',
|
with patch('homeassistant.util.dt.utcnow',
|
||||||
return_value=now):
|
return_value=now):
|
||||||
_setup_component(self.hass, automation.DOMAIN, {
|
setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'sun',
|
'platform': 'sun',
|
||||||
@ -108,7 +108,7 @@ class TestAutomationSun(unittest.TestCase):
|
|||||||
|
|
||||||
with patch('homeassistant.util.dt.utcnow',
|
with patch('homeassistant.util.dt.utcnow',
|
||||||
return_value=now):
|
return_value=now):
|
||||||
_setup_component(self.hass, automation.DOMAIN, {
|
setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'sun',
|
'platform': 'sun',
|
||||||
@ -142,7 +142,7 @@ class TestAutomationSun(unittest.TestCase):
|
|||||||
|
|
||||||
with patch('homeassistant.util.dt.utcnow',
|
with patch('homeassistant.util.dt.utcnow',
|
||||||
return_value=now):
|
return_value=now):
|
||||||
_setup_component(self.hass, automation.DOMAIN, {
|
setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'sun',
|
'platform': 'sun',
|
||||||
@ -165,7 +165,7 @@ class TestAutomationSun(unittest.TestCase):
|
|||||||
sun.STATE_ATTR_NEXT_RISING: '2015-09-16T14:00:00Z',
|
sun.STATE_ATTR_NEXT_RISING: '2015-09-16T14:00:00Z',
|
||||||
})
|
})
|
||||||
|
|
||||||
_setup_component(self.hass, automation.DOMAIN, {
|
setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'event',
|
'platform': 'event',
|
||||||
@ -201,7 +201,7 @@ class TestAutomationSun(unittest.TestCase):
|
|||||||
sun.STATE_ATTR_NEXT_RISING: '2015-09-16T14:00:00Z',
|
sun.STATE_ATTR_NEXT_RISING: '2015-09-16T14:00:00Z',
|
||||||
})
|
})
|
||||||
|
|
||||||
_setup_component(self.hass, automation.DOMAIN, {
|
setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'event',
|
'platform': 'event',
|
||||||
@ -237,7 +237,7 @@ class TestAutomationSun(unittest.TestCase):
|
|||||||
sun.STATE_ATTR_NEXT_RISING: '2015-09-16T14:00:00Z',
|
sun.STATE_ATTR_NEXT_RISING: '2015-09-16T14:00:00Z',
|
||||||
})
|
})
|
||||||
|
|
||||||
_setup_component(self.hass, automation.DOMAIN, {
|
setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'event',
|
'platform': 'event',
|
||||||
@ -274,7 +274,7 @@ class TestAutomationSun(unittest.TestCase):
|
|||||||
sun.STATE_ATTR_NEXT_RISING: '2015-09-16T14:00:00Z',
|
sun.STATE_ATTR_NEXT_RISING: '2015-09-16T14:00:00Z',
|
||||||
})
|
})
|
||||||
|
|
||||||
_setup_component(self.hass, automation.DOMAIN, {
|
setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'event',
|
'platform': 'event',
|
||||||
@ -312,7 +312,7 @@ class TestAutomationSun(unittest.TestCase):
|
|||||||
sun.STATE_ATTR_NEXT_SETTING: '2015-09-16T15:00:00Z',
|
sun.STATE_ATTR_NEXT_SETTING: '2015-09-16T15:00:00Z',
|
||||||
})
|
})
|
||||||
|
|
||||||
_setup_component(self.hass, automation.DOMAIN, {
|
setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'event',
|
'platform': 'event',
|
||||||
@ -358,7 +358,7 @@ class TestAutomationSun(unittest.TestCase):
|
|||||||
sun.STATE_ATTR_NEXT_SETTING: '2015-09-16T17:30:00Z',
|
sun.STATE_ATTR_NEXT_SETTING: '2015-09-16T17:30:00Z',
|
||||||
})
|
})
|
||||||
|
|
||||||
_setup_component(self.hass, automation.DOMAIN, {
|
setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'event',
|
'platform': 'event',
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
"""The tests for the Template automation."""
|
"""The tests for the Template automation."""
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from homeassistant.bootstrap import _setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
import homeassistant.components.automation as automation
|
import homeassistant.components.automation as automation
|
||||||
|
|
||||||
from tests.common import get_test_home_assistant
|
from tests.common import get_test_home_assistant, assert_setup_component
|
||||||
|
|
||||||
|
|
||||||
class TestAutomationTemplate(unittest.TestCase):
|
class TestAutomationTemplate(unittest.TestCase):
|
||||||
@ -29,7 +29,7 @@ class TestAutomationTemplate(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fires_on_change_bool(self):
|
def test_if_fires_on_change_bool(self):
|
||||||
"""Test for firing on boolean change."""
|
"""Test for firing on boolean change."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'template',
|
'platform': 'template',
|
||||||
@ -54,7 +54,7 @@ class TestAutomationTemplate(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fires_on_change_str(self):
|
def test_if_fires_on_change_str(self):
|
||||||
"""Test for firing on change."""
|
"""Test for firing on change."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'template',
|
'platform': 'template',
|
||||||
@ -72,7 +72,7 @@ class TestAutomationTemplate(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fires_on_change_str_crazy(self):
|
def test_if_fires_on_change_str_crazy(self):
|
||||||
"""Test for firing on change."""
|
"""Test for firing on change."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'template',
|
'platform': 'template',
|
||||||
@ -90,7 +90,7 @@ class TestAutomationTemplate(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_not_fires_on_change_bool(self):
|
def test_if_not_fires_on_change_bool(self):
|
||||||
"""Test for not firing on boolean change."""
|
"""Test for not firing on boolean change."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'template',
|
'platform': 'template',
|
||||||
@ -108,7 +108,7 @@ class TestAutomationTemplate(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_not_fires_on_change_str(self):
|
def test_if_not_fires_on_change_str(self):
|
||||||
"""Test for not firing on string change."""
|
"""Test for not firing on string change."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'template',
|
'platform': 'template',
|
||||||
@ -126,7 +126,7 @@ class TestAutomationTemplate(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_not_fires_on_change_str_crazy(self):
|
def test_if_not_fires_on_change_str_crazy(self):
|
||||||
"""Test for not firing on string change."""
|
"""Test for not firing on string change."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'template',
|
'platform': 'template',
|
||||||
@ -144,7 +144,7 @@ class TestAutomationTemplate(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fires_on_no_change(self):
|
def test_if_fires_on_no_change(self):
|
||||||
"""Test for firing on no change."""
|
"""Test for firing on no change."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'template',
|
'platform': 'template',
|
||||||
@ -165,7 +165,7 @@ class TestAutomationTemplate(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fires_on_two_change(self):
|
def test_if_fires_on_two_change(self):
|
||||||
"""Test for firing on two changes."""
|
"""Test for firing on two changes."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'template',
|
'platform': 'template',
|
||||||
@ -189,7 +189,7 @@ class TestAutomationTemplate(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fires_on_change_with_template(self):
|
def test_if_fires_on_change_with_template(self):
|
||||||
"""Test for firing on change with template."""
|
"""Test for firing on change with template."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'template',
|
'platform': 'template',
|
||||||
@ -207,7 +207,7 @@ class TestAutomationTemplate(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_not_fires_on_change_with_template(self):
|
def test_if_not_fires_on_change_with_template(self):
|
||||||
"""Test for not firing on change with template."""
|
"""Test for not firing on change with template."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'template',
|
'platform': 'template',
|
||||||
@ -228,7 +228,7 @@ class TestAutomationTemplate(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fires_on_change_with_template_advanced(self):
|
def test_if_fires_on_change_with_template_advanced(self):
|
||||||
"""Test for firing on change with template advanced."""
|
"""Test for firing on change with template advanced."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'template',
|
'platform': 'template',
|
||||||
@ -262,7 +262,7 @@ class TestAutomationTemplate(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fires_on_no_change_with_template_advanced(self):
|
def test_if_fires_on_no_change_with_template_advanced(self):
|
||||||
"""Test for firing on no change with template advanced."""
|
"""Test for firing on no change with template advanced."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'template',
|
'platform': 'template',
|
||||||
@ -290,7 +290,7 @@ class TestAutomationTemplate(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fires_on_change_with_template_2(self):
|
def test_if_fires_on_change_with_template_2(self):
|
||||||
"""Test for firing on change with template."""
|
"""Test for firing on change with template."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'template',
|
'platform': 'template',
|
||||||
@ -332,7 +332,7 @@ class TestAutomationTemplate(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_action(self):
|
def test_if_action(self):
|
||||||
"""Test for firing if action."""
|
"""Test for firing if action."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'event',
|
'platform': 'event',
|
||||||
@ -365,21 +365,22 @@ class TestAutomationTemplate(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fires_on_change_with_bad_template(self):
|
def test_if_fires_on_change_with_bad_template(self):
|
||||||
"""Test for firing on change with bad template."""
|
"""Test for firing on change with bad template."""
|
||||||
assert not _setup_component(self.hass, automation.DOMAIN, {
|
with assert_setup_component(0):
|
||||||
automation.DOMAIN: {
|
assert not setup_component(self.hass, automation.DOMAIN, {
|
||||||
'trigger': {
|
automation.DOMAIN: {
|
||||||
'platform': 'template',
|
'trigger': {
|
||||||
'value_template': '{{ ',
|
'platform': 'template',
|
||||||
},
|
'value_template': '{{ ',
|
||||||
'action': {
|
},
|
||||||
'service': 'test.automation'
|
'action': {
|
||||||
|
'service': 'test.automation'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
})
|
|
||||||
|
|
||||||
def test_if_fires_on_change_with_bad_template_2(self):
|
def test_if_fires_on_change_with_bad_template_2(self):
|
||||||
"""Test for firing on change with bad template."""
|
"""Test for firing on change with bad template."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'template',
|
'platform': 'template',
|
||||||
|
@ -3,11 +3,12 @@ from datetime import timedelta
|
|||||||
import unittest
|
import unittest
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
from homeassistant.bootstrap import _setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
import homeassistant.util.dt as dt_util
|
import homeassistant.util.dt as dt_util
|
||||||
import homeassistant.components.automation as automation
|
import homeassistant.components.automation as automation
|
||||||
|
|
||||||
from tests.common import fire_time_changed, get_test_home_assistant
|
from tests.common import (
|
||||||
|
fire_time_changed, get_test_home_assistant, assert_setup_component)
|
||||||
|
|
||||||
|
|
||||||
class TestAutomationTime(unittest.TestCase):
|
class TestAutomationTime(unittest.TestCase):
|
||||||
@ -30,7 +31,7 @@ class TestAutomationTime(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fires_when_hour_matches(self):
|
def test_if_fires_when_hour_matches(self):
|
||||||
"""Test for firing if hour is matching."""
|
"""Test for firing if hour is matching."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'time',
|
'platform': 'time',
|
||||||
@ -55,7 +56,7 @@ class TestAutomationTime(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fires_when_minute_matches(self):
|
def test_if_fires_when_minute_matches(self):
|
||||||
"""Test for firing if minutes are matching."""
|
"""Test for firing if minutes are matching."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'time',
|
'platform': 'time',
|
||||||
@ -74,7 +75,7 @@ class TestAutomationTime(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fires_when_second_matches(self):
|
def test_if_fires_when_second_matches(self):
|
||||||
"""Test for firing if seconds are matching."""
|
"""Test for firing if seconds are matching."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'time',
|
'platform': 'time',
|
||||||
@ -93,7 +94,7 @@ class TestAutomationTime(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fires_when_all_matches(self):
|
def test_if_fires_when_all_matches(self):
|
||||||
"""Test for firing if everything matches."""
|
"""Test for firing if everything matches."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'time',
|
'platform': 'time',
|
||||||
@ -115,7 +116,7 @@ class TestAutomationTime(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fires_periodic_seconds(self):
|
def test_if_fires_periodic_seconds(self):
|
||||||
"""Test for firing periodically every second."""
|
"""Test for firing periodically every second."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'time',
|
'platform': 'time',
|
||||||
@ -135,7 +136,7 @@ class TestAutomationTime(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fires_periodic_minutes(self):
|
def test_if_fires_periodic_minutes(self):
|
||||||
"""Test for firing periodically every minute."""
|
"""Test for firing periodically every minute."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'time',
|
'platform': 'time',
|
||||||
@ -155,7 +156,7 @@ class TestAutomationTime(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fires_periodic_hours(self):
|
def test_if_fires_periodic_hours(self):
|
||||||
"""Test for firing periodically every hour."""
|
"""Test for firing periodically every hour."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'time',
|
'platform': 'time',
|
||||||
@ -175,7 +176,7 @@ class TestAutomationTime(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_fires_using_after(self):
|
def test_if_fires_using_after(self):
|
||||||
"""Test for firing after."""
|
"""Test for firing after."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'time',
|
'platform': 'time',
|
||||||
@ -200,16 +201,17 @@ class TestAutomationTime(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_not_working_if_no_values_in_conf_provided(self):
|
def test_if_not_working_if_no_values_in_conf_provided(self):
|
||||||
"""Test for failure if no configuration."""
|
"""Test for failure if no configuration."""
|
||||||
assert not _setup_component(self.hass, automation.DOMAIN, {
|
with assert_setup_component(0):
|
||||||
automation.DOMAIN: {
|
assert not setup_component(self.hass, automation.DOMAIN, {
|
||||||
'trigger': {
|
automation.DOMAIN: {
|
||||||
'platform': 'time',
|
'trigger': {
|
||||||
},
|
'platform': 'time',
|
||||||
'action': {
|
},
|
||||||
'service': 'test.automation'
|
'action': {
|
||||||
|
'service': 'test.automation'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
})
|
|
||||||
|
|
||||||
fire_time_changed(self.hass, dt_util.utcnow().replace(
|
fire_time_changed(self.hass, dt_util.utcnow().replace(
|
||||||
hour=5, minute=0, second=0))
|
hour=5, minute=0, second=0))
|
||||||
@ -222,18 +224,19 @@ class TestAutomationTime(unittest.TestCase):
|
|||||||
|
|
||||||
This should break the before rule.
|
This should break the before rule.
|
||||||
"""
|
"""
|
||||||
assert not _setup_component(self.hass, automation.DOMAIN, {
|
with assert_setup_component(0):
|
||||||
automation.DOMAIN: {
|
assert not setup_component(self.hass, automation.DOMAIN, {
|
||||||
'trigger': {
|
automation.DOMAIN: {
|
||||||
'platform': 'time',
|
'trigger': {
|
||||||
'after': 3605,
|
'platform': 'time',
|
||||||
# Total seconds. Hour = 3600 second
|
'after': 3605,
|
||||||
},
|
# Total seconds. Hour = 3600 second
|
||||||
'action': {
|
},
|
||||||
'service': 'test.automation'
|
'action': {
|
||||||
|
'service': 'test.automation'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
})
|
|
||||||
|
|
||||||
fire_time_changed(self.hass, dt_util.utcnow().replace(
|
fire_time_changed(self.hass, dt_util.utcnow().replace(
|
||||||
hour=1, minute=0, second=5))
|
hour=1, minute=0, second=5))
|
||||||
@ -243,7 +246,7 @@ class TestAutomationTime(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_action_before(self):
|
def test_if_action_before(self):
|
||||||
"""Test for if action before."""
|
"""Test for if action before."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'event',
|
'platform': 'event',
|
||||||
@ -278,7 +281,7 @@ class TestAutomationTime(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_action_after(self):
|
def test_if_action_after(self):
|
||||||
"""Test for if action after."""
|
"""Test for if action after."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'event',
|
'platform': 'event',
|
||||||
@ -313,7 +316,7 @@ class TestAutomationTime(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_action_one_weekday(self):
|
def test_if_action_one_weekday(self):
|
||||||
"""Test for if action with one weekday."""
|
"""Test for if action with one weekday."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'event',
|
'platform': 'event',
|
||||||
@ -349,7 +352,7 @@ class TestAutomationTime(unittest.TestCase):
|
|||||||
|
|
||||||
def test_if_action_list_weekday(self):
|
def test_if_action_list_weekday(self):
|
||||||
"""Test for action with a list of weekdays."""
|
"""Test for action with a list of weekdays."""
|
||||||
assert _setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'event',
|
'platform': 'event',
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"""The tests for the MQTT binary sensor platform."""
|
"""The tests for the MQTT binary sensor platform."""
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from homeassistant.bootstrap import _setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
import homeassistant.components.binary_sensor as binary_sensor
|
import homeassistant.components.binary_sensor as binary_sensor
|
||||||
from tests.common import mock_mqtt_component, fire_mqtt_message
|
from tests.common import mock_mqtt_component, fire_mqtt_message
|
||||||
from homeassistant.const import (STATE_OFF, STATE_ON)
|
from homeassistant.const import (STATE_OFF, STATE_ON)
|
||||||
@ -24,7 +24,7 @@ class TestSensorMQTT(unittest.TestCase):
|
|||||||
def test_setting_sensor_value_via_mqtt_message(self):
|
def test_setting_sensor_value_via_mqtt_message(self):
|
||||||
"""Test the setting of the value via MQTT."""
|
"""Test the setting of the value via MQTT."""
|
||||||
self.hass.config.components = ['mqtt']
|
self.hass.config.components = ['mqtt']
|
||||||
assert _setup_component(self.hass, binary_sensor.DOMAIN, {
|
assert setup_component(self.hass, binary_sensor.DOMAIN, {
|
||||||
binary_sensor.DOMAIN: {
|
binary_sensor.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
'name': 'test',
|
'name': 'test',
|
||||||
@ -50,7 +50,7 @@ class TestSensorMQTT(unittest.TestCase):
|
|||||||
def test_valid_sensor_class(self):
|
def test_valid_sensor_class(self):
|
||||||
"""Test the setting of a valid sensor class."""
|
"""Test the setting of a valid sensor class."""
|
||||||
self.hass.config.components = ['mqtt']
|
self.hass.config.components = ['mqtt']
|
||||||
assert _setup_component(self.hass, binary_sensor.DOMAIN, {
|
assert setup_component(self.hass, binary_sensor.DOMAIN, {
|
||||||
binary_sensor.DOMAIN: {
|
binary_sensor.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
'name': 'test',
|
'name': 'test',
|
||||||
@ -65,7 +65,7 @@ class TestSensorMQTT(unittest.TestCase):
|
|||||||
def test_invalid_sensor_class(self):
|
def test_invalid_sensor_class(self):
|
||||||
"""Test the setting of an invalid sensor class."""
|
"""Test the setting of an invalid sensor class."""
|
||||||
self.hass.config.components = ['mqtt']
|
self.hass.config.components = ['mqtt']
|
||||||
assert _setup_component(self.hass, binary_sensor.DOMAIN, {
|
assert setup_component(self.hass, binary_sensor.DOMAIN, {
|
||||||
binary_sensor.DOMAIN: {
|
binary_sensor.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
'name': 'test',
|
'name': 'test',
|
||||||
|
@ -8,6 +8,8 @@ from nx584 import client as nx584_client
|
|||||||
from homeassistant.components.binary_sensor import nx584
|
from homeassistant.components.binary_sensor import nx584
|
||||||
from homeassistant.bootstrap import setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
|
|
||||||
|
from tests.common import get_test_home_assistant
|
||||||
|
|
||||||
|
|
||||||
class StopMe(Exception):
|
class StopMe(Exception):
|
||||||
"""Stop helper."""
|
"""Stop helper."""
|
||||||
@ -20,6 +22,7 @@ class TestNX584SensorSetup(unittest.TestCase):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""Setup things to be run when tests are started."""
|
"""Setup things to be run when tests are started."""
|
||||||
|
self.hass = get_test_home_assistant()
|
||||||
self._mock_client = mock.patch.object(nx584_client, 'Client')
|
self._mock_client = mock.patch.object(nx584_client, 'Client')
|
||||||
self._mock_client.start()
|
self._mock_client.start()
|
||||||
|
|
||||||
@ -35,6 +38,7 @@ class TestNX584SensorSetup(unittest.TestCase):
|
|||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
"""Stop everything that was started."""
|
"""Stop everything that was started."""
|
||||||
|
self.hass.stop()
|
||||||
self._mock_client.stop()
|
self._mock_client.stop()
|
||||||
|
|
||||||
@mock.patch('homeassistant.components.binary_sensor.nx584.NX584Watcher')
|
@mock.patch('homeassistant.components.binary_sensor.nx584.NX584Watcher')
|
||||||
@ -42,14 +46,13 @@ class TestNX584SensorSetup(unittest.TestCase):
|
|||||||
def test_setup_defaults(self, mock_nx, mock_watcher):
|
def test_setup_defaults(self, mock_nx, mock_watcher):
|
||||||
"""Test the setup with no configuration."""
|
"""Test the setup with no configuration."""
|
||||||
add_devices = mock.MagicMock()
|
add_devices = mock.MagicMock()
|
||||||
hass = mock.MagicMock()
|
|
||||||
config = {
|
config = {
|
||||||
'host': nx584.DEFAULT_HOST,
|
'host': nx584.DEFAULT_HOST,
|
||||||
'port': nx584.DEFAULT_PORT,
|
'port': nx584.DEFAULT_PORT,
|
||||||
'exclude_zones': [],
|
'exclude_zones': [],
|
||||||
'zone_types': {},
|
'zone_types': {},
|
||||||
}
|
}
|
||||||
self.assertTrue(nx584.setup_platform(hass, config, add_devices))
|
self.assertTrue(nx584.setup_platform(self.hass, config, add_devices))
|
||||||
mock_nx.assert_has_calls(
|
mock_nx.assert_has_calls(
|
||||||
[mock.call(zone, 'opening') for zone in self.fake_zones])
|
[mock.call(zone, 'opening') for zone in self.fake_zones])
|
||||||
self.assertTrue(add_devices.called)
|
self.assertTrue(add_devices.called)
|
||||||
@ -69,8 +72,7 @@ class TestNX584SensorSetup(unittest.TestCase):
|
|||||||
'zone_types': {3: 'motion'},
|
'zone_types': {3: 'motion'},
|
||||||
}
|
}
|
||||||
add_devices = mock.MagicMock()
|
add_devices = mock.MagicMock()
|
||||||
hass = mock.MagicMock()
|
self.assertTrue(nx584.setup_platform(self.hass, config, add_devices))
|
||||||
self.assertTrue(nx584.setup_platform(hass, config, add_devices))
|
|
||||||
mock_nx.assert_has_calls([
|
mock_nx.assert_has_calls([
|
||||||
mock.call(self.fake_zones[0], 'opening'),
|
mock.call(self.fake_zones[0], 'opening'),
|
||||||
mock.call(self.fake_zones[2], 'motion'),
|
mock.call(self.fake_zones[2], 'motion'),
|
||||||
@ -84,9 +86,8 @@ class TestNX584SensorSetup(unittest.TestCase):
|
|||||||
|
|
||||||
def _test_assert_graceful_fail(self, config):
|
def _test_assert_graceful_fail(self, config):
|
||||||
"""Test the failing."""
|
"""Test the failing."""
|
||||||
hass = add_devices = mock.MagicMock()
|
self.assertFalse(setup_component(
|
||||||
self.assertFalse(setup_component(hass, 'binary_sensor.nx584', config))
|
self.hass, 'binary_sensor.nx584', config))
|
||||||
self.assertFalse(add_devices.called)
|
|
||||||
|
|
||||||
def test_setup_bad_config(self):
|
def test_setup_bad_config(self):
|
||||||
"""Test the setup with bad configuration."""
|
"""Test the setup with bad configuration."""
|
||||||
@ -113,8 +114,8 @@ class TestNX584SensorSetup(unittest.TestCase):
|
|||||||
def test_setup_no_zones(self):
|
def test_setup_no_zones(self):
|
||||||
"""Test the setup with no zones."""
|
"""Test the setup with no zones."""
|
||||||
nx584_client.Client.return_value.list_zones.return_value = []
|
nx584_client.Client.return_value.list_zones.return_value = []
|
||||||
hass = add_devices = mock.MagicMock()
|
add_devices = mock.MagicMock()
|
||||||
self.assertTrue(nx584.setup_platform(hass, {}, add_devices))
|
self.assertTrue(nx584.setup_platform(self.hass, {}, add_devices))
|
||||||
self.assertFalse(add_devices.called)
|
self.assertFalse(add_devices.called)
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import unittest
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant.bootstrap import _setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
from homeassistant.components import rfxtrx as rfxtrx_core
|
from homeassistant.components import rfxtrx as rfxtrx_core
|
||||||
|
|
||||||
from tests.common import get_test_home_assistant
|
from tests.common import get_test_home_assistant
|
||||||
@ -28,7 +28,7 @@ class TestCoverRfxtrx(unittest.TestCase):
|
|||||||
|
|
||||||
def test_valid_config(self):
|
def test_valid_config(self):
|
||||||
"""Test configuration."""
|
"""Test configuration."""
|
||||||
self.assertTrue(_setup_component(self.hass, 'cover', {
|
self.assertTrue(setup_component(self.hass, 'cover', {
|
||||||
'cover': {'platform': 'rfxtrx',
|
'cover': {'platform': 'rfxtrx',
|
||||||
'automatic_add': True,
|
'automatic_add': True,
|
||||||
'devices':
|
'devices':
|
||||||
@ -39,7 +39,7 @@ class TestCoverRfxtrx(unittest.TestCase):
|
|||||||
|
|
||||||
def test_invalid_config_capital_letters(self):
|
def test_invalid_config_capital_letters(self):
|
||||||
"""Test configuration."""
|
"""Test configuration."""
|
||||||
self.assertFalse(_setup_component(self.hass, 'cover', {
|
self.assertFalse(setup_component(self.hass, 'cover', {
|
||||||
'cover': {'platform': 'rfxtrx',
|
'cover': {'platform': 'rfxtrx',
|
||||||
'automatic_add': True,
|
'automatic_add': True,
|
||||||
'devices':
|
'devices':
|
||||||
@ -51,7 +51,7 @@ class TestCoverRfxtrx(unittest.TestCase):
|
|||||||
|
|
||||||
def test_invalid_config_extra_key(self):
|
def test_invalid_config_extra_key(self):
|
||||||
"""Test configuration."""
|
"""Test configuration."""
|
||||||
self.assertFalse(_setup_component(self.hass, 'cover', {
|
self.assertFalse(setup_component(self.hass, 'cover', {
|
||||||
'cover': {'platform': 'rfxtrx',
|
'cover': {'platform': 'rfxtrx',
|
||||||
'automatic_add': True,
|
'automatic_add': True,
|
||||||
'invalid_key': 'afda',
|
'invalid_key': 'afda',
|
||||||
@ -64,7 +64,7 @@ class TestCoverRfxtrx(unittest.TestCase):
|
|||||||
|
|
||||||
def test_invalid_config_capital_packetid(self):
|
def test_invalid_config_capital_packetid(self):
|
||||||
"""Test configuration."""
|
"""Test configuration."""
|
||||||
self.assertFalse(_setup_component(self.hass, 'cover', {
|
self.assertFalse(setup_component(self.hass, 'cover', {
|
||||||
'cover': {'platform': 'rfxtrx',
|
'cover': {'platform': 'rfxtrx',
|
||||||
'automatic_add': True,
|
'automatic_add': True,
|
||||||
'devices':
|
'devices':
|
||||||
@ -76,7 +76,7 @@ class TestCoverRfxtrx(unittest.TestCase):
|
|||||||
|
|
||||||
def test_invalid_config_missing_packetid(self):
|
def test_invalid_config_missing_packetid(self):
|
||||||
"""Test configuration."""
|
"""Test configuration."""
|
||||||
self.assertFalse(_setup_component(self.hass, 'cover', {
|
self.assertFalse(setup_component(self.hass, 'cover', {
|
||||||
'cover': {'platform': 'rfxtrx',
|
'cover': {'platform': 'rfxtrx',
|
||||||
'automatic_add': True,
|
'automatic_add': True,
|
||||||
'devices':
|
'devices':
|
||||||
@ -87,14 +87,14 @@ class TestCoverRfxtrx(unittest.TestCase):
|
|||||||
|
|
||||||
def test_default_config(self):
|
def test_default_config(self):
|
||||||
"""Test with 0 cover."""
|
"""Test with 0 cover."""
|
||||||
self.assertTrue(_setup_component(self.hass, 'cover', {
|
self.assertTrue(setup_component(self.hass, 'cover', {
|
||||||
'cover': {'platform': 'rfxtrx',
|
'cover': {'platform': 'rfxtrx',
|
||||||
'devices': {}}}))
|
'devices': {}}}))
|
||||||
self.assertEqual(0, len(rfxtrx_core.RFX_DEVICES))
|
self.assertEqual(0, len(rfxtrx_core.RFX_DEVICES))
|
||||||
|
|
||||||
def test_one_cover(self):
|
def test_one_cover(self):
|
||||||
"""Test with 1 cover."""
|
"""Test with 1 cover."""
|
||||||
self.assertTrue(_setup_component(self.hass, 'cover', {
|
self.assertTrue(setup_component(self.hass, 'cover', {
|
||||||
'cover': {'platform': 'rfxtrx',
|
'cover': {'platform': 'rfxtrx',
|
||||||
'devices':
|
'devices':
|
||||||
{'0b1400cd0213c7f210010f51': {
|
{'0b1400cd0213c7f210010f51': {
|
||||||
@ -117,7 +117,7 @@ class TestCoverRfxtrx(unittest.TestCase):
|
|||||||
|
|
||||||
def test_several_covers(self):
|
def test_several_covers(self):
|
||||||
"""Test with 3 covers."""
|
"""Test with 3 covers."""
|
||||||
self.assertTrue(_setup_component(self.hass, 'cover', {
|
self.assertTrue(setup_component(self.hass, 'cover', {
|
||||||
'cover': {'platform': 'rfxtrx',
|
'cover': {'platform': 'rfxtrx',
|
||||||
'signal_repetitions': 3,
|
'signal_repetitions': 3,
|
||||||
'devices':
|
'devices':
|
||||||
@ -145,7 +145,7 @@ class TestCoverRfxtrx(unittest.TestCase):
|
|||||||
|
|
||||||
def test_discover_covers(self):
|
def test_discover_covers(self):
|
||||||
"""Test with discovery of covers."""
|
"""Test with discovery of covers."""
|
||||||
self.assertTrue(_setup_component(self.hass, 'cover', {
|
self.assertTrue(setup_component(self.hass, 'cover', {
|
||||||
'cover': {'platform': 'rfxtrx',
|
'cover': {'platform': 'rfxtrx',
|
||||||
'automatic_add': True,
|
'automatic_add': True,
|
||||||
'devices': {}}}))
|
'devices': {}}}))
|
||||||
@ -183,7 +183,7 @@ class TestCoverRfxtrx(unittest.TestCase):
|
|||||||
|
|
||||||
def test_discover_cover_noautoadd(self):
|
def test_discover_cover_noautoadd(self):
|
||||||
"""Test with discovery of cover when auto add is False."""
|
"""Test with discovery of cover when auto add is False."""
|
||||||
self.assertTrue(_setup_component(self.hass, 'cover', {
|
self.assertTrue(setup_component(self.hass, 'cover', {
|
||||||
'cover': {'platform': 'rfxtrx',
|
'cover': {'platform': 'rfxtrx',
|
||||||
'automatic_add': False,
|
'automatic_add': False,
|
||||||
'devices': {}}}))
|
'devices': {}}}))
|
||||||
|
@ -4,7 +4,7 @@ from unittest.mock import patch
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from homeassistant.bootstrap import _setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
from homeassistant.components import device_tracker
|
from homeassistant.components import device_tracker
|
||||||
from homeassistant.const import CONF_PLATFORM
|
from homeassistant.const import CONF_PLATFORM
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ class TestComponentsDeviceTrackerMQTT(unittest.TestCase):
|
|||||||
dev_id = 'paulus'
|
dev_id = 'paulus'
|
||||||
topic = '/location/paulus'
|
topic = '/location/paulus'
|
||||||
self.hass.config.components = ['mqtt', 'zone']
|
self.hass.config.components = ['mqtt', 'zone']
|
||||||
assert _setup_component(self.hass, device_tracker.DOMAIN, {
|
assert setup_component(self.hass, device_tracker.DOMAIN, {
|
||||||
device_tracker.DOMAIN: {
|
device_tracker.DOMAIN: {
|
||||||
CONF_PLATFORM: 'mqtt',
|
CONF_PLATFORM: 'mqtt',
|
||||||
'devices': {dev_id: topic}
|
'devices': {dev_id: topic}
|
||||||
@ -58,7 +58,7 @@ class TestComponentsDeviceTrackerMQTT(unittest.TestCase):
|
|||||||
location = 'work'
|
location = 'work'
|
||||||
|
|
||||||
self.hass.config.components = ['mqtt', 'zone']
|
self.hass.config.components = ['mqtt', 'zone']
|
||||||
assert _setup_component(self.hass, device_tracker.DOMAIN, {
|
assert setup_component(self.hass, device_tracker.DOMAIN, {
|
||||||
device_tracker.DOMAIN: {
|
device_tracker.DOMAIN: {
|
||||||
CONF_PLATFORM: 'mqtt',
|
CONF_PLATFORM: 'mqtt',
|
||||||
'devices': {dev_id: topic}
|
'devices': {dev_id: topic}
|
||||||
|
@ -30,7 +30,7 @@ light:
|
|||||||
import json
|
import json
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from homeassistant.bootstrap import _setup_component, setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
from homeassistant.const import STATE_ON, STATE_OFF, ATTR_ASSUMED_STATE
|
from homeassistant.const import STATE_ON, STATE_OFF, ATTR_ASSUMED_STATE
|
||||||
import homeassistant.components.light as light
|
import homeassistant.components.light as light
|
||||||
from tests.common import (
|
from tests.common import (
|
||||||
@ -67,7 +67,7 @@ class TestLightMQTTJSON(unittest.TestCase):
|
|||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
"""Test if there is no color and brightness if they aren't defined."""
|
"""Test if there is no color and brightness if they aren't defined."""
|
||||||
self.hass.config.components = ['mqtt']
|
self.hass.config.components = ['mqtt']
|
||||||
assert _setup_component(self.hass, light.DOMAIN, {
|
assert setup_component(self.hass, light.DOMAIN, {
|
||||||
light.DOMAIN: {
|
light.DOMAIN: {
|
||||||
'platform': 'mqtt_json',
|
'platform': 'mqtt_json',
|
||||||
'name': 'test',
|
'name': 'test',
|
||||||
@ -93,7 +93,7 @@ class TestLightMQTTJSON(unittest.TestCase):
|
|||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
"""Test the controlling of the state via topic."""
|
"""Test the controlling of the state via topic."""
|
||||||
self.hass.config.components = ['mqtt']
|
self.hass.config.components = ['mqtt']
|
||||||
assert _setup_component(self.hass, light.DOMAIN, {
|
assert setup_component(self.hass, light.DOMAIN, {
|
||||||
light.DOMAIN: {
|
light.DOMAIN: {
|
||||||
'platform': 'mqtt_json',
|
'platform': 'mqtt_json',
|
||||||
'name': 'test',
|
'name': 'test',
|
||||||
@ -153,7 +153,7 @@ class TestLightMQTTJSON(unittest.TestCase):
|
|||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
"""Test the sending of command in optimistic mode."""
|
"""Test the sending of command in optimistic mode."""
|
||||||
self.hass.config.components = ['mqtt']
|
self.hass.config.components = ['mqtt']
|
||||||
assert _setup_component(self.hass, light.DOMAIN, {
|
assert setup_component(self.hass, light.DOMAIN, {
|
||||||
light.DOMAIN: {
|
light.DOMAIN: {
|
||||||
'platform': 'mqtt_json',
|
'platform': 'mqtt_json',
|
||||||
'name': 'test',
|
'name': 'test',
|
||||||
@ -209,7 +209,7 @@ class TestLightMQTTJSON(unittest.TestCase):
|
|||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
"""Test for flash length being sent when included."""
|
"""Test for flash length being sent when included."""
|
||||||
self.hass.config.components = ['mqtt']
|
self.hass.config.components = ['mqtt']
|
||||||
assert _setup_component(self.hass, light.DOMAIN, {
|
assert setup_component(self.hass, light.DOMAIN, {
|
||||||
light.DOMAIN: {
|
light.DOMAIN: {
|
||||||
'platform': 'mqtt_json',
|
'platform': 'mqtt_json',
|
||||||
'name': 'test',
|
'name': 'test',
|
||||||
@ -251,7 +251,7 @@ class TestLightMQTTJSON(unittest.TestCase):
|
|||||||
def test_transition(self):
|
def test_transition(self):
|
||||||
"""Test for transition time being sent when included."""
|
"""Test for transition time being sent when included."""
|
||||||
self.hass.config.components = ['mqtt']
|
self.hass.config.components = ['mqtt']
|
||||||
assert _setup_component(self.hass, light.DOMAIN, {
|
assert setup_component(self.hass, light.DOMAIN, {
|
||||||
light.DOMAIN: {
|
light.DOMAIN: {
|
||||||
'platform': 'mqtt_json',
|
'platform': 'mqtt_json',
|
||||||
'name': 'test',
|
'name': 'test',
|
||||||
@ -293,7 +293,7 @@ class TestLightMQTTJSON(unittest.TestCase):
|
|||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
"""Test that invalid color/brightness values are ignored."""
|
"""Test that invalid color/brightness values are ignored."""
|
||||||
self.hass.config.components = ['mqtt']
|
self.hass.config.components = ['mqtt']
|
||||||
assert _setup_component(self.hass, light.DOMAIN, {
|
assert setup_component(self.hass, light.DOMAIN, {
|
||||||
light.DOMAIN: {
|
light.DOMAIN: {
|
||||||
'platform': 'mqtt_json',
|
'platform': 'mqtt_json',
|
||||||
'name': 'test',
|
'name': 'test',
|
||||||
|
@ -3,7 +3,7 @@ import unittest
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant.bootstrap import _setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
from homeassistant.components import rfxtrx as rfxtrx_core
|
from homeassistant.components import rfxtrx as rfxtrx_core
|
||||||
|
|
||||||
from tests.common import get_test_home_assistant
|
from tests.common import get_test_home_assistant
|
||||||
@ -28,7 +28,7 @@ class TestLightRfxtrx(unittest.TestCase):
|
|||||||
|
|
||||||
def test_valid_config(self):
|
def test_valid_config(self):
|
||||||
"""Test configuration."""
|
"""Test configuration."""
|
||||||
self.assertTrue(_setup_component(self.hass, 'light', {
|
self.assertTrue(setup_component(self.hass, 'light', {
|
||||||
'light': {'platform': 'rfxtrx',
|
'light': {'platform': 'rfxtrx',
|
||||||
'automatic_add': True,
|
'automatic_add': True,
|
||||||
'devices':
|
'devices':
|
||||||
@ -36,7 +36,7 @@ class TestLightRfxtrx(unittest.TestCase):
|
|||||||
'name': 'Test',
|
'name': 'Test',
|
||||||
rfxtrx_core.ATTR_FIREEVENT: True}}}}))
|
rfxtrx_core.ATTR_FIREEVENT: True}}}}))
|
||||||
|
|
||||||
self.assertTrue(_setup_component(self.hass, 'light', {
|
self.assertTrue(setup_component(self.hass, 'light', {
|
||||||
'light': {'platform': 'rfxtrx',
|
'light': {'platform': 'rfxtrx',
|
||||||
'automatic_add': True,
|
'automatic_add': True,
|
||||||
'devices':
|
'devices':
|
||||||
@ -47,7 +47,7 @@ class TestLightRfxtrx(unittest.TestCase):
|
|||||||
|
|
||||||
def test_invalid_config(self):
|
def test_invalid_config(self):
|
||||||
"""Test configuration."""
|
"""Test configuration."""
|
||||||
self.assertFalse(_setup_component(self.hass, 'light', {
|
self.assertFalse(setup_component(self.hass, 'light', {
|
||||||
'light': {'platform': 'rfxtrx',
|
'light': {'platform': 'rfxtrx',
|
||||||
'automatic_add': True,
|
'automatic_add': True,
|
||||||
'invalid_key': 'afda',
|
'invalid_key': 'afda',
|
||||||
@ -59,14 +59,14 @@ class TestLightRfxtrx(unittest.TestCase):
|
|||||||
|
|
||||||
def test_default_config(self):
|
def test_default_config(self):
|
||||||
"""Test with 0 switches."""
|
"""Test with 0 switches."""
|
||||||
self.assertTrue(_setup_component(self.hass, 'light', {
|
self.assertTrue(setup_component(self.hass, 'light', {
|
||||||
'light': {'platform': 'rfxtrx',
|
'light': {'platform': 'rfxtrx',
|
||||||
'devices': {}}}))
|
'devices': {}}}))
|
||||||
self.assertEqual(0, len(rfxtrx_core.RFX_DEVICES))
|
self.assertEqual(0, len(rfxtrx_core.RFX_DEVICES))
|
||||||
|
|
||||||
def test_old_config(self):
|
def test_old_config(self):
|
||||||
"""Test with 1 light."""
|
"""Test with 1 light."""
|
||||||
self.assertTrue(_setup_component(self.hass, 'light', {
|
self.assertTrue(setup_component(self.hass, 'light', {
|
||||||
'light': {'platform': 'rfxtrx',
|
'light': {'platform': 'rfxtrx',
|
||||||
'devices':
|
'devices':
|
||||||
{'123efab1': {
|
{'123efab1': {
|
||||||
@ -110,7 +110,7 @@ class TestLightRfxtrx(unittest.TestCase):
|
|||||||
|
|
||||||
def test_one_light(self):
|
def test_one_light(self):
|
||||||
"""Test with 1 light."""
|
"""Test with 1 light."""
|
||||||
self.assertTrue(_setup_component(self.hass, 'light', {
|
self.assertTrue(setup_component(self.hass, 'light', {
|
||||||
'light': {'platform': 'rfxtrx',
|
'light': {'platform': 'rfxtrx',
|
||||||
'devices':
|
'devices':
|
||||||
{'0b1100cd0213c7f210010f51': {
|
{'0b1100cd0213c7f210010f51': {
|
||||||
@ -179,7 +179,7 @@ class TestLightRfxtrx(unittest.TestCase):
|
|||||||
|
|
||||||
def test_several_lights(self):
|
def test_several_lights(self):
|
||||||
"""Test with 3 lights."""
|
"""Test with 3 lights."""
|
||||||
self.assertTrue(_setup_component(self.hass, 'light', {
|
self.assertTrue(setup_component(self.hass, 'light', {
|
||||||
'light': {'platform': 'rfxtrx',
|
'light': {'platform': 'rfxtrx',
|
||||||
'signal_repetitions': 3,
|
'signal_repetitions': 3,
|
||||||
'devices':
|
'devices':
|
||||||
@ -212,7 +212,7 @@ class TestLightRfxtrx(unittest.TestCase):
|
|||||||
|
|
||||||
def test_discover_light(self):
|
def test_discover_light(self):
|
||||||
"""Test with discovery of lights."""
|
"""Test with discovery of lights."""
|
||||||
self.assertTrue(_setup_component(self.hass, 'light', {
|
self.assertTrue(setup_component(self.hass, 'light', {
|
||||||
'light': {'platform': 'rfxtrx',
|
'light': {'platform': 'rfxtrx',
|
||||||
'automatic_add': True,
|
'automatic_add': True,
|
||||||
'devices': {}}}))
|
'devices': {}}}))
|
||||||
@ -265,7 +265,7 @@ class TestLightRfxtrx(unittest.TestCase):
|
|||||||
|
|
||||||
def test_discover_light_noautoadd(self):
|
def test_discover_light_noautoadd(self):
|
||||||
"""Test with discover of light when auto add is False."""
|
"""Test with discover of light when auto add is False."""
|
||||||
self.assertTrue(_setup_component(self.hass, 'light', {
|
self.assertTrue(setup_component(self.hass, 'light', {
|
||||||
'light': {'platform': 'rfxtrx',
|
'light': {'platform': 'rfxtrx',
|
||||||
'automatic_add': False,
|
'automatic_add': False,
|
||||||
'devices': {}}}))
|
'devices': {}}}))
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"""The tests for the MQTT lock platform."""
|
"""The tests for the MQTT lock platform."""
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from homeassistant.bootstrap import _setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
from homeassistant.const import (STATE_LOCKED, STATE_UNLOCKED,
|
from homeassistant.const import (STATE_LOCKED, STATE_UNLOCKED,
|
||||||
ATTR_ASSUMED_STATE)
|
ATTR_ASSUMED_STATE)
|
||||||
import homeassistant.components.lock as lock
|
import homeassistant.components.lock as lock
|
||||||
@ -24,7 +24,7 @@ class TestLockMQTT(unittest.TestCase):
|
|||||||
def test_controlling_state_via_topic(self):
|
def test_controlling_state_via_topic(self):
|
||||||
"""Test the controlling state via topic."""
|
"""Test the controlling state via topic."""
|
||||||
self.hass.config.components = ['mqtt']
|
self.hass.config.components = ['mqtt']
|
||||||
assert _setup_component(self.hass, lock.DOMAIN, {
|
assert setup_component(self.hass, lock.DOMAIN, {
|
||||||
lock.DOMAIN: {
|
lock.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
'name': 'test',
|
'name': 'test',
|
||||||
@ -54,7 +54,7 @@ class TestLockMQTT(unittest.TestCase):
|
|||||||
def test_sending_mqtt_commands_and_optimistic(self):
|
def test_sending_mqtt_commands_and_optimistic(self):
|
||||||
"""Test the sending MQTT commands in optimistic mode."""
|
"""Test the sending MQTT commands in optimistic mode."""
|
||||||
self.hass.config.components = ['mqtt']
|
self.hass.config.components = ['mqtt']
|
||||||
assert _setup_component(self.hass, lock.DOMAIN, {
|
assert setup_component(self.hass, lock.DOMAIN, {
|
||||||
lock.DOMAIN: {
|
lock.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
'name': 'test',
|
'name': 'test',
|
||||||
@ -88,7 +88,7 @@ class TestLockMQTT(unittest.TestCase):
|
|||||||
def test_controlling_state_via_topic_and_json_message(self):
|
def test_controlling_state_via_topic_and_json_message(self):
|
||||||
"""Test the controlling state via topic and JSON message."""
|
"""Test the controlling state via topic and JSON message."""
|
||||||
self.hass.config.components = ['mqtt']
|
self.hass.config.components = ['mqtt']
|
||||||
assert _setup_component(self.hass, lock.DOMAIN, {
|
assert setup_component(self.hass, lock.DOMAIN, {
|
||||||
lock.DOMAIN: {
|
lock.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
'name': 'test',
|
'name': 'test',
|
||||||
|
@ -6,7 +6,7 @@ import socket
|
|||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.bootstrap import _setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
import homeassistant.components.mqtt as mqtt
|
import homeassistant.components.mqtt as mqtt
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
EVENT_CALL_SERVICE, ATTR_DOMAIN, ATTR_SERVICE, EVENT_HOMEASSISTANT_START,
|
EVENT_CALL_SERVICE, ATTR_DOMAIN, ATTR_SERVICE, EVENT_HOMEASSISTANT_START,
|
||||||
@ -52,7 +52,7 @@ class TestMQTT(unittest.TestCase):
|
|||||||
with mock.patch('homeassistant.components.mqtt.MQTT',
|
with mock.patch('homeassistant.components.mqtt.MQTT',
|
||||||
side_effect=socket.error()):
|
side_effect=socket.error()):
|
||||||
self.hass.config.components = []
|
self.hass.config.components = []
|
||||||
assert not _setup_component(self.hass, mqtt.DOMAIN, {
|
assert not setup_component(self.hass, mqtt.DOMAIN, {
|
||||||
mqtt.DOMAIN: {
|
mqtt.DOMAIN: {
|
||||||
mqtt.CONF_BROKER: 'test-broker',
|
mqtt.CONF_BROKER: 'test-broker',
|
||||||
}
|
}
|
||||||
@ -62,7 +62,7 @@ class TestMQTT(unittest.TestCase):
|
|||||||
"""Test for setup failure if connection to broker is missing."""
|
"""Test for setup failure if connection to broker is missing."""
|
||||||
with mock.patch('paho.mqtt.client.Client'):
|
with mock.patch('paho.mqtt.client.Client'):
|
||||||
self.hass.config.components = []
|
self.hass.config.components = []
|
||||||
assert _setup_component(self.hass, mqtt.DOMAIN, {
|
assert setup_component(self.hass, mqtt.DOMAIN, {
|
||||||
mqtt.DOMAIN: {
|
mqtt.DOMAIN: {
|
||||||
mqtt.CONF_BROKER: 'test-broker',
|
mqtt.CONF_BROKER: 'test-broker',
|
||||||
mqtt.CONF_PROTOCOL: 3.1,
|
mqtt.CONF_PROTOCOL: 3.1,
|
||||||
@ -222,7 +222,7 @@ class TestMQTTCallbacks(unittest.TestCase):
|
|||||||
|
|
||||||
with mock.patch('paho.mqtt.client.Client'):
|
with mock.patch('paho.mqtt.client.Client'):
|
||||||
self.hass.config.components = []
|
self.hass.config.components = []
|
||||||
assert _setup_component(self.hass, mqtt.DOMAIN, {
|
assert setup_component(self.hass, mqtt.DOMAIN, {
|
||||||
mqtt.DOMAIN: {
|
mqtt.DOMAIN: {
|
||||||
mqtt.CONF_BROKER: 'mock-broker',
|
mqtt.CONF_BROKER: 'mock-broker',
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"""The tests for the MQTT component embedded server."""
|
"""The tests for the MQTT component embedded server."""
|
||||||
from unittest.mock import Mock, MagicMock, patch
|
from unittest.mock import Mock, MagicMock, patch
|
||||||
|
|
||||||
from homeassistant.bootstrap import _setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
import homeassistant.components.mqtt as mqtt
|
import homeassistant.components.mqtt as mqtt
|
||||||
|
|
||||||
from tests.common import get_test_home_assistant
|
from tests.common import get_test_home_assistant
|
||||||
@ -29,7 +29,7 @@ class TestMQTT:
|
|||||||
password = 'super_secret'
|
password = 'super_secret'
|
||||||
|
|
||||||
self.hass.config.api = MagicMock(api_password=password)
|
self.hass.config.api = MagicMock(api_password=password)
|
||||||
assert _setup_component(self.hass, mqtt.DOMAIN, {})
|
assert setup_component(self.hass, mqtt.DOMAIN, {})
|
||||||
assert mock_mqtt.called
|
assert mock_mqtt.called
|
||||||
assert mock_mqtt.mock_calls[0][1][5] == 'homeassistant'
|
assert mock_mqtt.mock_calls[0][1][5] == 'homeassistant'
|
||||||
assert mock_mqtt.mock_calls[0][1][6] == password
|
assert mock_mqtt.mock_calls[0][1][6] == password
|
||||||
@ -38,7 +38,7 @@ class TestMQTT:
|
|||||||
|
|
||||||
self.hass.config.components = ['http']
|
self.hass.config.components = ['http']
|
||||||
self.hass.config.api = MagicMock(api_password=None)
|
self.hass.config.api = MagicMock(api_password=None)
|
||||||
assert _setup_component(self.hass, mqtt.DOMAIN, {})
|
assert setup_component(self.hass, mqtt.DOMAIN, {})
|
||||||
assert mock_mqtt.called
|
assert mock_mqtt.called
|
||||||
assert mock_mqtt.mock_calls[0][1][5] is None
|
assert mock_mqtt.mock_calls[0][1][5] is None
|
||||||
assert mock_mqtt.mock_calls[0][1][6] is None
|
assert mock_mqtt.mock_calls[0][1][6] is None
|
||||||
@ -54,6 +54,7 @@ class TestMQTT:
|
|||||||
mock_gather.side_effect = BrokerException
|
mock_gather.side_effect = BrokerException
|
||||||
|
|
||||||
self.hass.config.api = MagicMock(api_password=None)
|
self.hass.config.api = MagicMock(api_password=None)
|
||||||
assert not _setup_component(self.hass, mqtt.DOMAIN, {
|
|
||||||
|
assert not setup_component(self.hass, mqtt.DOMAIN, {
|
||||||
mqtt.DOMAIN: {mqtt.CONF_EMBEDDED: {}}
|
mqtt.DOMAIN: {mqtt.CONF_EMBEDDED: {}}
|
||||||
})
|
})
|
||||||
|
@ -8,9 +8,8 @@ import homeassistant.components.notify as notify
|
|||||||
from homeassistant.components.notify import (
|
from homeassistant.components.notify import (
|
||||||
ATTR_TITLE_DEFAULT)
|
ATTR_TITLE_DEFAULT)
|
||||||
import homeassistant.util.dt as dt_util
|
import homeassistant.util.dt as dt_util
|
||||||
from homeassistant.bootstrap import _setup_component
|
|
||||||
|
|
||||||
from tests.common import get_test_home_assistant
|
from tests.common import get_test_home_assistant, assert_setup_component
|
||||||
|
|
||||||
|
|
||||||
class TestNotifyFile(unittest.TestCase):
|
class TestNotifyFile(unittest.TestCase):
|
||||||
@ -26,12 +25,13 @@ class TestNotifyFile(unittest.TestCase):
|
|||||||
|
|
||||||
def test_bad_config(self):
|
def test_bad_config(self):
|
||||||
"""Test set up the platform with bad/missing config."""
|
"""Test set up the platform with bad/missing config."""
|
||||||
self.assertFalse(_setup_component(self.hass, notify.DOMAIN, {
|
with assert_setup_component(0):
|
||||||
'notify': {
|
assert not setup_component(self.hass, notify.DOMAIN, {
|
||||||
'name': 'test',
|
'notify': {
|
||||||
'platform': 'file',
|
'name': 'test',
|
||||||
},
|
'platform': 'file',
|
||||||
}))
|
},
|
||||||
|
})
|
||||||
|
|
||||||
@patch('homeassistant.components.notify.file.os.stat')
|
@patch('homeassistant.components.notify.file.os.stat')
|
||||||
@patch('homeassistant.util.dt.utcnow')
|
@patch('homeassistant.util.dt.utcnow')
|
||||||
|
@ -6,7 +6,7 @@ import unittest
|
|||||||
|
|
||||||
from homeassistant.const import MATCH_ALL
|
from homeassistant.const import MATCH_ALL
|
||||||
from homeassistant.components import recorder
|
from homeassistant.components import recorder
|
||||||
from homeassistant.bootstrap import _setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
from tests.common import get_test_home_assistant
|
from tests.common import get_test_home_assistant
|
||||||
|
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ class TestRecorder(unittest.TestCase):
|
|||||||
"""Setup things to be run when tests are started."""
|
"""Setup things to be run when tests are started."""
|
||||||
self.hass = get_test_home_assistant()
|
self.hass = get_test_home_assistant()
|
||||||
db_uri = 'sqlite://' # In memory DB
|
db_uri = 'sqlite://' # In memory DB
|
||||||
_setup_component(self.hass, recorder.DOMAIN, {
|
setup_component(self.hass, recorder.DOMAIN, {
|
||||||
recorder.DOMAIN: {recorder.CONF_DB_URL: db_uri}})
|
recorder.DOMAIN: {recorder.CONF_DB_URL: db_uri}})
|
||||||
self.hass.start()
|
self.hass.start()
|
||||||
recorder._verify_instance()
|
recorder._verify_instance()
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"""The tests for the MQTT sensor platform."""
|
"""The tests for the MQTT sensor platform."""
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from homeassistant.bootstrap import _setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
import homeassistant.components.sensor as sensor
|
import homeassistant.components.sensor as sensor
|
||||||
from tests.common import mock_mqtt_component, fire_mqtt_message
|
from tests.common import mock_mqtt_component, fire_mqtt_message
|
||||||
|
|
||||||
@ -23,7 +23,7 @@ class TestSensorMQTT(unittest.TestCase):
|
|||||||
def test_setting_sensor_value_via_mqtt_message(self):
|
def test_setting_sensor_value_via_mqtt_message(self):
|
||||||
"""Test the setting of the value via MQTT."""
|
"""Test the setting of the value via MQTT."""
|
||||||
self.hass.config.components = ['mqtt']
|
self.hass.config.components = ['mqtt']
|
||||||
assert _setup_component(self.hass, sensor.DOMAIN, {
|
assert setup_component(self.hass, sensor.DOMAIN, {
|
||||||
sensor.DOMAIN: {
|
sensor.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
'name': 'test',
|
'name': 'test',
|
||||||
@ -43,7 +43,7 @@ class TestSensorMQTT(unittest.TestCase):
|
|||||||
def test_setting_sensor_value_via_mqtt_json_message(self):
|
def test_setting_sensor_value_via_mqtt_json_message(self):
|
||||||
"""Test the setting of the value via MQTT with JSON playload."""
|
"""Test the setting of the value via MQTT with JSON playload."""
|
||||||
self.hass.config.components = ['mqtt']
|
self.hass.config.components = ['mqtt']
|
||||||
assert _setup_component(self.hass, sensor.DOMAIN, {
|
assert setup_component(self.hass, sensor.DOMAIN, {
|
||||||
sensor.DOMAIN: {
|
sensor.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
'name': 'test',
|
'name': 'test',
|
||||||
|
@ -3,7 +3,7 @@ import unittest
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant.bootstrap import _setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
from homeassistant.components import rfxtrx as rfxtrx_core
|
from homeassistant.components import rfxtrx as rfxtrx_core
|
||||||
from homeassistant.const import TEMP_CELSIUS
|
from homeassistant.const import TEMP_CELSIUS
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ class TestSensorRfxtrx(unittest.TestCase):
|
|||||||
|
|
||||||
def test_default_config(self):
|
def test_default_config(self):
|
||||||
"""Test with 0 sensor."""
|
"""Test with 0 sensor."""
|
||||||
self.assertTrue(_setup_component(self.hass, 'sensor', {
|
self.assertTrue(setup_component(self.hass, 'sensor', {
|
||||||
'sensor': {'platform': 'rfxtrx',
|
'sensor': {'platform': 'rfxtrx',
|
||||||
'devices':
|
'devices':
|
||||||
{}}}))
|
{}}}))
|
||||||
@ -37,7 +37,7 @@ class TestSensorRfxtrx(unittest.TestCase):
|
|||||||
|
|
||||||
def test_old_config_sensor(self):
|
def test_old_config_sensor(self):
|
||||||
"""Test with 1 sensor."""
|
"""Test with 1 sensor."""
|
||||||
self.assertTrue(_setup_component(self.hass, 'sensor', {
|
self.assertTrue(setup_component(self.hass, 'sensor', {
|
||||||
'sensor': {'platform': 'rfxtrx',
|
'sensor': {'platform': 'rfxtrx',
|
||||||
'devices':
|
'devices':
|
||||||
{'sensor_0502': {
|
{'sensor_0502': {
|
||||||
@ -53,7 +53,7 @@ class TestSensorRfxtrx(unittest.TestCase):
|
|||||||
|
|
||||||
def test_one_sensor(self):
|
def test_one_sensor(self):
|
||||||
"""Test with 1 sensor."""
|
"""Test with 1 sensor."""
|
||||||
self.assertTrue(_setup_component(self.hass, 'sensor', {
|
self.assertTrue(setup_component(self.hass, 'sensor', {
|
||||||
'sensor': {'platform': 'rfxtrx',
|
'sensor': {'platform': 'rfxtrx',
|
||||||
'devices':
|
'devices':
|
||||||
{'0a52080705020095220269': {
|
{'0a52080705020095220269': {
|
||||||
@ -68,7 +68,7 @@ class TestSensorRfxtrx(unittest.TestCase):
|
|||||||
|
|
||||||
def test_one_sensor_no_datatype(self):
|
def test_one_sensor_no_datatype(self):
|
||||||
"""Test with 1 sensor."""
|
"""Test with 1 sensor."""
|
||||||
self.assertTrue(_setup_component(self.hass, 'sensor', {
|
self.assertTrue(setup_component(self.hass, 'sensor', {
|
||||||
'sensor': {'platform': 'rfxtrx',
|
'sensor': {'platform': 'rfxtrx',
|
||||||
'devices':
|
'devices':
|
||||||
{'0a52080705020095220269': {
|
{'0a52080705020095220269': {
|
||||||
@ -88,7 +88,7 @@ class TestSensorRfxtrx(unittest.TestCase):
|
|||||||
|
|
||||||
def test_several_sensors(self):
|
def test_several_sensors(self):
|
||||||
"""Test with 3 sensors."""
|
"""Test with 3 sensors."""
|
||||||
self.assertTrue(_setup_component(self.hass, 'sensor', {
|
self.assertTrue(setup_component(self.hass, 'sensor', {
|
||||||
'sensor': {'platform': 'rfxtrx',
|
'sensor': {'platform': 'rfxtrx',
|
||||||
'devices':
|
'devices':
|
||||||
{'0a52080705020095220269': {
|
{'0a52080705020095220269': {
|
||||||
@ -124,7 +124,7 @@ class TestSensorRfxtrx(unittest.TestCase):
|
|||||||
|
|
||||||
def test_discover_sensor(self):
|
def test_discover_sensor(self):
|
||||||
"""Test with discovery of sensor."""
|
"""Test with discovery of sensor."""
|
||||||
self.assertTrue(_setup_component(self.hass, 'sensor', {
|
self.assertTrue(setup_component(self.hass, 'sensor', {
|
||||||
'sensor': {'platform': 'rfxtrx',
|
'sensor': {'platform': 'rfxtrx',
|
||||||
'automatic_add': True,
|
'automatic_add': True,
|
||||||
'devices': {}}}))
|
'devices': {}}}))
|
||||||
@ -182,7 +182,7 @@ class TestSensorRfxtrx(unittest.TestCase):
|
|||||||
|
|
||||||
def test_discover_sensor_noautoadd(self):
|
def test_discover_sensor_noautoadd(self):
|
||||||
"""Test with discover of sensor when auto add is False."""
|
"""Test with discover of sensor when auto add is False."""
|
||||||
self.assertTrue(_setup_component(self.hass, 'sensor', {
|
self.assertTrue(setup_component(self.hass, 'sensor', {
|
||||||
'sensor': {'platform': 'rfxtrx',
|
'sensor': {'platform': 'rfxtrx',
|
||||||
'automatic_add': False,
|
'automatic_add': False,
|
||||||
'devices': {}}}))
|
'devices': {}}}))
|
||||||
@ -209,7 +209,7 @@ class TestSensorRfxtrx(unittest.TestCase):
|
|||||||
|
|
||||||
def test_update_of_sensors(self):
|
def test_update_of_sensors(self):
|
||||||
"""Test with 3 sensors."""
|
"""Test with 3 sensors."""
|
||||||
self.assertTrue(_setup_component(self.hass, 'sensor', {
|
self.assertTrue(setup_component(self.hass, 'sensor', {
|
||||||
'sensor': {'platform': 'rfxtrx',
|
'sensor': {'platform': 'rfxtrx',
|
||||||
'devices':
|
'devices':
|
||||||
{'0a52080705020095220269': {
|
{'0a52080705020095220269': {
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
from homeassistant.bootstrap import _setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
import homeassistant.util.dt as dt_util
|
import homeassistant.util.dt as dt_util
|
||||||
from tests.common import get_test_home_assistant, load_fixture
|
from tests.common import get_test_home_assistant, load_fixture
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ class TestSensorYr:
|
|||||||
|
|
||||||
with patch('homeassistant.components.sensor.yr.dt_util.utcnow',
|
with patch('homeassistant.components.sensor.yr.dt_util.utcnow',
|
||||||
return_value=now):
|
return_value=now):
|
||||||
assert _setup_component(self.hass, 'sensor', {
|
assert setup_component(self.hass, 'sensor', {
|
||||||
'sensor': {'platform': 'yr',
|
'sensor': {'platform': 'yr',
|
||||||
'elevation': 0}})
|
'elevation': 0}})
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ class TestSensorYr:
|
|||||||
|
|
||||||
with patch('homeassistant.components.sensor.yr.dt_util.utcnow',
|
with patch('homeassistant.components.sensor.yr.dt_util.utcnow',
|
||||||
return_value=now):
|
return_value=now):
|
||||||
assert _setup_component(self.hass, 'sensor', {
|
assert setup_component(self.hass, 'sensor', {
|
||||||
'sensor': {'platform': 'yr',
|
'sensor': {'platform': 'yr',
|
||||||
'elevation': 0,
|
'elevation': 0,
|
||||||
'monitored_conditions': [
|
'monitored_conditions': [
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"""The tests for the MQTT switch platform."""
|
"""The tests for the MQTT switch platform."""
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from homeassistant.bootstrap import _setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
from homeassistant.const import STATE_ON, STATE_OFF, ATTR_ASSUMED_STATE
|
from homeassistant.const import STATE_ON, STATE_OFF, ATTR_ASSUMED_STATE
|
||||||
import homeassistant.components.switch as switch
|
import homeassistant.components.switch as switch
|
||||||
from tests.common import (
|
from tests.common import (
|
||||||
@ -23,7 +23,7 @@ class TestSensorMQTT(unittest.TestCase):
|
|||||||
def test_controlling_state_via_topic(self):
|
def test_controlling_state_via_topic(self):
|
||||||
"""Test the controlling state via topic."""
|
"""Test the controlling state via topic."""
|
||||||
self.hass.config.components = ['mqtt']
|
self.hass.config.components = ['mqtt']
|
||||||
assert _setup_component(self.hass, switch.DOMAIN, {
|
assert setup_component(self.hass, switch.DOMAIN, {
|
||||||
switch.DOMAIN: {
|
switch.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
'name': 'test',
|
'name': 'test',
|
||||||
@ -53,7 +53,7 @@ class TestSensorMQTT(unittest.TestCase):
|
|||||||
def test_sending_mqtt_commands_and_optimistic(self):
|
def test_sending_mqtt_commands_and_optimistic(self):
|
||||||
"""Test the sending MQTT commands in optimistic mode."""
|
"""Test the sending MQTT commands in optimistic mode."""
|
||||||
self.hass.config.components = ['mqtt']
|
self.hass.config.components = ['mqtt']
|
||||||
assert _setup_component(self.hass, switch.DOMAIN, {
|
assert setup_component(self.hass, switch.DOMAIN, {
|
||||||
switch.DOMAIN: {
|
switch.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
'name': 'test',
|
'name': 'test',
|
||||||
@ -87,7 +87,7 @@ class TestSensorMQTT(unittest.TestCase):
|
|||||||
def test_controlling_state_via_topic_and_json_message(self):
|
def test_controlling_state_via_topic_and_json_message(self):
|
||||||
"""Test the controlling state via topic and JSON message."""
|
"""Test the controlling state via topic and JSON message."""
|
||||||
self.hass.config.components = ['mqtt']
|
self.hass.config.components = ['mqtt']
|
||||||
assert _setup_component(self.hass, switch.DOMAIN, {
|
assert setup_component(self.hass, switch.DOMAIN, {
|
||||||
switch.DOMAIN: {
|
switch.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
'name': 'test',
|
'name': 'test',
|
||||||
|
@ -3,7 +3,7 @@ import unittest
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant.bootstrap import _setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
from homeassistant.components import rfxtrx as rfxtrx_core
|
from homeassistant.components import rfxtrx as rfxtrx_core
|
||||||
|
|
||||||
from tests.common import get_test_home_assistant
|
from tests.common import get_test_home_assistant
|
||||||
@ -28,7 +28,7 @@ class TestSwitchRfxtrx(unittest.TestCase):
|
|||||||
|
|
||||||
def test_valid_config(self):
|
def test_valid_config(self):
|
||||||
"""Test configuration."""
|
"""Test configuration."""
|
||||||
self.assertTrue(_setup_component(self.hass, 'switch', {
|
self.assertTrue(setup_component(self.hass, 'switch', {
|
||||||
'switch': {'platform': 'rfxtrx',
|
'switch': {'platform': 'rfxtrx',
|
||||||
'automatic_add': True,
|
'automatic_add': True,
|
||||||
'devices':
|
'devices':
|
||||||
@ -39,7 +39,7 @@ class TestSwitchRfxtrx(unittest.TestCase):
|
|||||||
|
|
||||||
def test_valid_config_int_device_id(self):
|
def test_valid_config_int_device_id(self):
|
||||||
"""Test configuration."""
|
"""Test configuration."""
|
||||||
self.assertTrue(_setup_component(self.hass, 'switch', {
|
self.assertTrue(setup_component(self.hass, 'switch', {
|
||||||
'switch': {'platform': 'rfxtrx',
|
'switch': {'platform': 'rfxtrx',
|
||||||
'automatic_add': True,
|
'automatic_add': True,
|
||||||
'devices':
|
'devices':
|
||||||
@ -49,7 +49,7 @@ class TestSwitchRfxtrx(unittest.TestCase):
|
|||||||
}}}))
|
}}}))
|
||||||
|
|
||||||
def test_invalid_config1(self):
|
def test_invalid_config1(self):
|
||||||
self.assertFalse(_setup_component(self.hass, 'switch', {
|
self.assertFalse(setup_component(self.hass, 'switch', {
|
||||||
'switch': {'platform': 'rfxtrx',
|
'switch': {'platform': 'rfxtrx',
|
||||||
'automatic_add': True,
|
'automatic_add': True,
|
||||||
'devices':
|
'devices':
|
||||||
@ -61,7 +61,7 @@ class TestSwitchRfxtrx(unittest.TestCase):
|
|||||||
|
|
||||||
def test_invalid_config2(self):
|
def test_invalid_config2(self):
|
||||||
"""Test configuration."""
|
"""Test configuration."""
|
||||||
self.assertFalse(_setup_component(self.hass, 'switch', {
|
self.assertFalse(setup_component(self.hass, 'switch', {
|
||||||
'switch': {'platform': 'rfxtrx',
|
'switch': {'platform': 'rfxtrx',
|
||||||
'automatic_add': True,
|
'automatic_add': True,
|
||||||
'invalid_key': 'afda',
|
'invalid_key': 'afda',
|
||||||
@ -73,7 +73,7 @@ class TestSwitchRfxtrx(unittest.TestCase):
|
|||||||
}}}))
|
}}}))
|
||||||
|
|
||||||
def test_invalid_config3(self):
|
def test_invalid_config3(self):
|
||||||
self.assertFalse(_setup_component(self.hass, 'switch', {
|
self.assertFalse(setup_component(self.hass, 'switch', {
|
||||||
'switch': {'platform': 'rfxtrx',
|
'switch': {'platform': 'rfxtrx',
|
||||||
'automatic_add': True,
|
'automatic_add': True,
|
||||||
'devices':
|
'devices':
|
||||||
@ -85,7 +85,7 @@ class TestSwitchRfxtrx(unittest.TestCase):
|
|||||||
|
|
||||||
def test_invalid_config4(self):
|
def test_invalid_config4(self):
|
||||||
"""Test configuration."""
|
"""Test configuration."""
|
||||||
self.assertFalse(_setup_component(self.hass, 'switch', {
|
self.assertFalse(setup_component(self.hass, 'switch', {
|
||||||
'switch': {'platform': 'rfxtrx',
|
'switch': {'platform': 'rfxtrx',
|
||||||
'automatic_add': True,
|
'automatic_add': True,
|
||||||
'devices':
|
'devices':
|
||||||
@ -96,7 +96,7 @@ class TestSwitchRfxtrx(unittest.TestCase):
|
|||||||
|
|
||||||
def test_default_config(self):
|
def test_default_config(self):
|
||||||
"""Test with 0 switches."""
|
"""Test with 0 switches."""
|
||||||
self.assertTrue(_setup_component(self.hass, 'switch', {
|
self.assertTrue(setup_component(self.hass, 'switch', {
|
||||||
'switch': {'platform': 'rfxtrx',
|
'switch': {'platform': 'rfxtrx',
|
||||||
'devices':
|
'devices':
|
||||||
{}}}))
|
{}}}))
|
||||||
@ -104,7 +104,7 @@ class TestSwitchRfxtrx(unittest.TestCase):
|
|||||||
|
|
||||||
def test_old_config(self):
|
def test_old_config(self):
|
||||||
"""Test with 1 switch."""
|
"""Test with 1 switch."""
|
||||||
self.assertTrue(_setup_component(self.hass, 'switch', {
|
self.assertTrue(setup_component(self.hass, 'switch', {
|
||||||
'switch': {'platform': 'rfxtrx',
|
'switch': {'platform': 'rfxtrx',
|
||||||
'devices':
|
'devices':
|
||||||
{'123efab1': {
|
{'123efab1': {
|
||||||
@ -132,7 +132,7 @@ class TestSwitchRfxtrx(unittest.TestCase):
|
|||||||
|
|
||||||
def test_one_switch(self):
|
def test_one_switch(self):
|
||||||
"""Test with 1 switch."""
|
"""Test with 1 switch."""
|
||||||
self.assertTrue(_setup_component(self.hass, 'switch', {
|
self.assertTrue(setup_component(self.hass, 'switch', {
|
||||||
'switch': {'platform': 'rfxtrx',
|
'switch': {'platform': 'rfxtrx',
|
||||||
'devices':
|
'devices':
|
||||||
{'0b1100cd0213c7f210010f51': {
|
{'0b1100cd0213c7f210010f51': {
|
||||||
@ -170,7 +170,7 @@ class TestSwitchRfxtrx(unittest.TestCase):
|
|||||||
|
|
||||||
def test_several_switches(self):
|
def test_several_switches(self):
|
||||||
"""Test with 3 switches."""
|
"""Test with 3 switches."""
|
||||||
self.assertTrue(_setup_component(self.hass, 'switch', {
|
self.assertTrue(setup_component(self.hass, 'switch', {
|
||||||
'switch': {'platform': 'rfxtrx',
|
'switch': {'platform': 'rfxtrx',
|
||||||
'signal_repetitions': 3,
|
'signal_repetitions': 3,
|
||||||
'devices':
|
'devices':
|
||||||
@ -203,7 +203,7 @@ class TestSwitchRfxtrx(unittest.TestCase):
|
|||||||
|
|
||||||
def test_discover_switch(self):
|
def test_discover_switch(self):
|
||||||
"""Test with discovery of switches."""
|
"""Test with discovery of switches."""
|
||||||
self.assertTrue(_setup_component(self.hass, 'switch', {
|
self.assertTrue(setup_component(self.hass, 'switch', {
|
||||||
'switch': {'platform': 'rfxtrx',
|
'switch': {'platform': 'rfxtrx',
|
||||||
'automatic_add': True,
|
'automatic_add': True,
|
||||||
'devices': {}}}))
|
'devices': {}}}))
|
||||||
@ -253,7 +253,7 @@ class TestSwitchRfxtrx(unittest.TestCase):
|
|||||||
|
|
||||||
def test_discover_switch_noautoadd(self):
|
def test_discover_switch_noautoadd(self):
|
||||||
"""Test with discovery of switch when auto add is False."""
|
"""Test with discovery of switch when auto add is False."""
|
||||||
self.assertTrue(_setup_component(self.hass, 'switch', {
|
self.assertTrue(setup_component(self.hass, 'switch', {
|
||||||
'switch': {'platform': 'rfxtrx',
|
'switch': {'platform': 'rfxtrx',
|
||||||
'automatic_add': False,
|
'automatic_add': False,
|
||||||
'devices': {}}}))
|
'devices': {}}}))
|
||||||
|
@ -7,8 +7,9 @@ from homeassistant.bootstrap import setup_component
|
|||||||
import homeassistant.components as core_components
|
import homeassistant.components as core_components
|
||||||
from homeassistant.components import conversation
|
from homeassistant.components import conversation
|
||||||
from homeassistant.const import ATTR_ENTITY_ID
|
from homeassistant.const import ATTR_ENTITY_ID
|
||||||
|
from homeassistant.util.async import run_coroutine_threadsafe
|
||||||
|
|
||||||
from tests.common import get_test_home_assistant
|
from tests.common import get_test_home_assistant, assert_setup_component
|
||||||
|
|
||||||
|
|
||||||
class TestConversation(unittest.TestCase):
|
class TestConversation(unittest.TestCase):
|
||||||
@ -19,9 +20,13 @@ class TestConversation(unittest.TestCase):
|
|||||||
self.ent_id = 'light.kitchen_lights'
|
self.ent_id = 'light.kitchen_lights'
|
||||||
self.hass = get_test_home_assistant(3)
|
self.hass = get_test_home_assistant(3)
|
||||||
self.hass.states.set(self.ent_id, 'on')
|
self.hass.states.set(self.ent_id, 'on')
|
||||||
self.assertTrue(core_components.setup(self.hass, {}))
|
self.assertTrue(run_coroutine_threadsafe(
|
||||||
self.assertTrue(setup_component(self.hass, conversation.DOMAIN, {
|
core_components.async_setup(self.hass, {}), self.hass.loop
|
||||||
conversation.DOMAIN: {}}))
|
).result())
|
||||||
|
with assert_setup_component(0):
|
||||||
|
self.assertTrue(setup_component(self.hass, conversation.DOMAIN, {
|
||||||
|
conversation.DOMAIN: {}
|
||||||
|
}))
|
||||||
|
|
||||||
def tearDown(self): # pylint: disable=invalid-name
|
def tearDown(self): # pylint: disable=invalid-name
|
||||||
"""Stop everything that was started."""
|
"""Stop everything that was started."""
|
||||||
|
@ -1,425 +1,429 @@
|
|||||||
"""The tests for the emulated Hue component."""
|
"""The tests for the emulated Hue component."""
|
||||||
import time
|
import time
|
||||||
import json
|
import json
|
||||||
import threading
|
import threading
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from homeassistant import bootstrap, const, core
|
from homeassistant import bootstrap, const, core
|
||||||
import homeassistant.components as core_components
|
import homeassistant.components as core_components
|
||||||
from homeassistant.components import emulated_hue, http, light
|
from homeassistant.components import emulated_hue, http, light
|
||||||
from homeassistant.const import STATE_ON, STATE_OFF
|
from homeassistant.const import STATE_ON, STATE_OFF
|
||||||
from homeassistant.components.emulated_hue import (
|
from homeassistant.components.emulated_hue import (
|
||||||
HUE_API_STATE_ON, HUE_API_STATE_BRI)
|
HUE_API_STATE_ON, HUE_API_STATE_BRI)
|
||||||
|
from homeassistant.util.async import run_coroutine_threadsafe
|
||||||
from tests.common import get_test_instance_port, get_test_home_assistant
|
|
||||||
|
from tests.common import get_test_instance_port, get_test_home_assistant
|
||||||
HTTP_SERVER_PORT = get_test_instance_port()
|
|
||||||
BRIDGE_SERVER_PORT = get_test_instance_port()
|
HTTP_SERVER_PORT = get_test_instance_port()
|
||||||
|
BRIDGE_SERVER_PORT = get_test_instance_port()
|
||||||
BRIDGE_URL_BASE = "http://127.0.0.1:{}".format(BRIDGE_SERVER_PORT) + "{}"
|
|
||||||
JSON_HEADERS = {const.HTTP_HEADER_CONTENT_TYPE: const.CONTENT_TYPE_JSON}
|
BRIDGE_URL_BASE = "http://127.0.0.1:{}".format(BRIDGE_SERVER_PORT) + "{}"
|
||||||
|
JSON_HEADERS = {const.HTTP_HEADER_CONTENT_TYPE: const.CONTENT_TYPE_JSON}
|
||||||
|
|
||||||
def setup_hass_instance(emulated_hue_config):
|
|
||||||
"""Setup the Home Assistant instance to test."""
|
def setup_hass_instance(emulated_hue_config):
|
||||||
hass = get_test_home_assistant()
|
"""Setup the Home Assistant instance to test."""
|
||||||
|
hass = get_test_home_assistant()
|
||||||
# We need to do this to get access to homeassistant/turn_(on,off)
|
|
||||||
core_components.setup(hass, {core.DOMAIN: {}})
|
# We need to do this to get access to homeassistant/turn_(on,off)
|
||||||
|
run_coroutine_threadsafe(
|
||||||
bootstrap.setup_component(
|
core_components.async_setup(hass, {core.DOMAIN: {}}), hass.loop
|
||||||
hass, http.DOMAIN,
|
).result()
|
||||||
{http.DOMAIN: {http.CONF_SERVER_PORT: HTTP_SERVER_PORT}})
|
|
||||||
|
bootstrap.setup_component(
|
||||||
bootstrap.setup_component(hass, emulated_hue.DOMAIN, emulated_hue_config)
|
hass, http.DOMAIN,
|
||||||
|
{http.DOMAIN: {http.CONF_SERVER_PORT: HTTP_SERVER_PORT}})
|
||||||
return hass
|
|
||||||
|
bootstrap.setup_component(hass, emulated_hue.DOMAIN, emulated_hue_config)
|
||||||
|
|
||||||
def start_hass_instance(hass):
|
return hass
|
||||||
"""Start the Home Assistant instance to test."""
|
|
||||||
hass.start()
|
|
||||||
time.sleep(0.05)
|
def start_hass_instance(hass):
|
||||||
|
"""Start the Home Assistant instance to test."""
|
||||||
|
hass.start()
|
||||||
class TestEmulatedHue(unittest.TestCase):
|
time.sleep(0.05)
|
||||||
"""Test the emulated Hue component."""
|
|
||||||
|
|
||||||
hass = None
|
class TestEmulatedHue(unittest.TestCase):
|
||||||
|
"""Test the emulated Hue component."""
|
||||||
@classmethod
|
|
||||||
def setUpClass(cls):
|
hass = None
|
||||||
"""Setup the class."""
|
|
||||||
cls.hass = setup_hass_instance({
|
@classmethod
|
||||||
emulated_hue.DOMAIN: {
|
def setUpClass(cls):
|
||||||
emulated_hue.CONF_LISTEN_PORT: BRIDGE_SERVER_PORT
|
"""Setup the class."""
|
||||||
}})
|
cls.hass = setup_hass_instance({
|
||||||
|
emulated_hue.DOMAIN: {
|
||||||
start_hass_instance(cls.hass)
|
emulated_hue.CONF_LISTEN_PORT: BRIDGE_SERVER_PORT
|
||||||
|
}})
|
||||||
@classmethod
|
|
||||||
def tearDownClass(cls):
|
start_hass_instance(cls.hass)
|
||||||
"""Stop the class."""
|
|
||||||
cls.hass.stop()
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
def test_description_xml(self):
|
"""Stop the class."""
|
||||||
"""Test the description."""
|
cls.hass.stop()
|
||||||
import xml.etree.ElementTree as ET
|
|
||||||
|
def test_description_xml(self):
|
||||||
result = requests.get(
|
"""Test the description."""
|
||||||
BRIDGE_URL_BASE.format('/description.xml'), timeout=5)
|
import xml.etree.ElementTree as ET
|
||||||
|
|
||||||
self.assertEqual(result.status_code, 200)
|
result = requests.get(
|
||||||
self.assertTrue('text/xml' in result.headers['content-type'])
|
BRIDGE_URL_BASE.format('/description.xml'), timeout=5)
|
||||||
|
|
||||||
# Make sure the XML is parsable
|
self.assertEqual(result.status_code, 200)
|
||||||
try:
|
self.assertTrue('text/xml' in result.headers['content-type'])
|
||||||
ET.fromstring(result.text)
|
|
||||||
except:
|
# Make sure the XML is parsable
|
||||||
self.fail('description.xml is not valid XML!')
|
try:
|
||||||
|
ET.fromstring(result.text)
|
||||||
def test_create_username(self):
|
except:
|
||||||
"""Test the creation of an username."""
|
self.fail('description.xml is not valid XML!')
|
||||||
request_json = {'devicetype': 'my_device'}
|
|
||||||
|
def test_create_username(self):
|
||||||
result = requests.post(
|
"""Test the creation of an username."""
|
||||||
BRIDGE_URL_BASE.format('/api'), data=json.dumps(request_json),
|
request_json = {'devicetype': 'my_device'}
|
||||||
timeout=5)
|
|
||||||
|
result = requests.post(
|
||||||
self.assertEqual(result.status_code, 200)
|
BRIDGE_URL_BASE.format('/api'), data=json.dumps(request_json),
|
||||||
self.assertTrue('application/json' in result.headers['content-type'])
|
timeout=5)
|
||||||
|
|
||||||
resp_json = result.json()
|
self.assertEqual(result.status_code, 200)
|
||||||
success_json = resp_json[0]
|
self.assertTrue('application/json' in result.headers['content-type'])
|
||||||
|
|
||||||
self.assertTrue('success' in success_json)
|
resp_json = result.json()
|
||||||
self.assertTrue('username' in success_json['success'])
|
success_json = resp_json[0]
|
||||||
|
|
||||||
def test_valid_username_request(self):
|
self.assertTrue('success' in success_json)
|
||||||
"""Test request with a valid username."""
|
self.assertTrue('username' in success_json['success'])
|
||||||
request_json = {'invalid_key': 'my_device'}
|
|
||||||
|
def test_valid_username_request(self):
|
||||||
result = requests.post(
|
"""Test request with a valid username."""
|
||||||
BRIDGE_URL_BASE.format('/api'), data=json.dumps(request_json),
|
request_json = {'invalid_key': 'my_device'}
|
||||||
timeout=5)
|
|
||||||
|
result = requests.post(
|
||||||
self.assertEqual(result.status_code, 400)
|
BRIDGE_URL_BASE.format('/api'), data=json.dumps(request_json),
|
||||||
|
timeout=5)
|
||||||
|
|
||||||
class TestEmulatedHueExposedByDefault(unittest.TestCase):
|
self.assertEqual(result.status_code, 400)
|
||||||
"""Test class for emulated hue component."""
|
|
||||||
|
|
||||||
@classmethod
|
class TestEmulatedHueExposedByDefault(unittest.TestCase):
|
||||||
def setUpClass(cls):
|
"""Test class for emulated hue component."""
|
||||||
"""Setup the class."""
|
|
||||||
cls.hass = setup_hass_instance({
|
@classmethod
|
||||||
emulated_hue.DOMAIN: {
|
def setUpClass(cls):
|
||||||
emulated_hue.CONF_LISTEN_PORT: BRIDGE_SERVER_PORT,
|
"""Setup the class."""
|
||||||
emulated_hue.CONF_EXPOSE_BY_DEFAULT: True
|
cls.hass = setup_hass_instance({
|
||||||
}
|
emulated_hue.DOMAIN: {
|
||||||
})
|
emulated_hue.CONF_LISTEN_PORT: BRIDGE_SERVER_PORT,
|
||||||
|
emulated_hue.CONF_EXPOSE_BY_DEFAULT: True
|
||||||
bootstrap.setup_component(cls.hass, light.DOMAIN, {
|
}
|
||||||
'light': [
|
})
|
||||||
{
|
|
||||||
'platform': 'demo',
|
bootstrap.setup_component(cls.hass, light.DOMAIN, {
|
||||||
}
|
'light': [
|
||||||
]
|
{
|
||||||
})
|
'platform': 'demo',
|
||||||
|
}
|
||||||
start_hass_instance(cls.hass)
|
]
|
||||||
|
})
|
||||||
# Kitchen light is explicitly excluded from being exposed
|
|
||||||
kitchen_light_entity = cls.hass.states.get('light.kitchen_lights')
|
start_hass_instance(cls.hass)
|
||||||
attrs = dict(kitchen_light_entity.attributes)
|
|
||||||
attrs[emulated_hue.ATTR_EMULATED_HUE] = False
|
# Kitchen light is explicitly excluded from being exposed
|
||||||
cls.hass.states.set(
|
kitchen_light_entity = cls.hass.states.get('light.kitchen_lights')
|
||||||
kitchen_light_entity.entity_id, kitchen_light_entity.state,
|
attrs = dict(kitchen_light_entity.attributes)
|
||||||
attributes=attrs)
|
attrs[emulated_hue.ATTR_EMULATED_HUE] = False
|
||||||
|
cls.hass.states.set(
|
||||||
@classmethod
|
kitchen_light_entity.entity_id, kitchen_light_entity.state,
|
||||||
def tearDownClass(cls):
|
attributes=attrs)
|
||||||
"""Stop the class."""
|
|
||||||
cls.hass.stop()
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
def test_discover_lights(self):
|
"""Stop the class."""
|
||||||
"""Test the discovery of lights."""
|
cls.hass.stop()
|
||||||
result = requests.get(
|
|
||||||
BRIDGE_URL_BASE.format('/api/username/lights'), timeout=5)
|
def test_discover_lights(self):
|
||||||
|
"""Test the discovery of lights."""
|
||||||
self.assertEqual(result.status_code, 200)
|
result = requests.get(
|
||||||
self.assertTrue('application/json' in result.headers['content-type'])
|
BRIDGE_URL_BASE.format('/api/username/lights'), timeout=5)
|
||||||
|
|
||||||
result_json = result.json()
|
self.assertEqual(result.status_code, 200)
|
||||||
|
self.assertTrue('application/json' in result.headers['content-type'])
|
||||||
# Make sure the lights we added to the config are there
|
|
||||||
self.assertTrue('light.ceiling_lights' in result_json)
|
result_json = result.json()
|
||||||
self.assertTrue('light.bed_light' in result_json)
|
|
||||||
self.assertTrue('light.kitchen_lights' not in result_json)
|
# Make sure the lights we added to the config are there
|
||||||
|
self.assertTrue('light.ceiling_lights' in result_json)
|
||||||
def test_get_light_state(self):
|
self.assertTrue('light.bed_light' in result_json)
|
||||||
"""Test the getting of light state."""
|
self.assertTrue('light.kitchen_lights' not in result_json)
|
||||||
# Turn office light on and set to 127 brightness
|
|
||||||
self.hass.services.call(
|
def test_get_light_state(self):
|
||||||
light.DOMAIN, const.SERVICE_TURN_ON,
|
"""Test the getting of light state."""
|
||||||
{
|
# Turn office light on and set to 127 brightness
|
||||||
const.ATTR_ENTITY_ID: 'light.ceiling_lights',
|
self.hass.services.call(
|
||||||
light.ATTR_BRIGHTNESS: 127
|
light.DOMAIN, const.SERVICE_TURN_ON,
|
||||||
},
|
{
|
||||||
blocking=True)
|
const.ATTR_ENTITY_ID: 'light.ceiling_lights',
|
||||||
|
light.ATTR_BRIGHTNESS: 127
|
||||||
office_json = self.perform_get_light_state('light.ceiling_lights', 200)
|
},
|
||||||
|
blocking=True)
|
||||||
self.assertEqual(office_json['state'][HUE_API_STATE_ON], True)
|
|
||||||
self.assertEqual(office_json['state'][HUE_API_STATE_BRI], 127)
|
office_json = self.perform_get_light_state('light.ceiling_lights', 200)
|
||||||
|
|
||||||
# Turn bedroom light off
|
self.assertEqual(office_json['state'][HUE_API_STATE_ON], True)
|
||||||
self.hass.services.call(
|
self.assertEqual(office_json['state'][HUE_API_STATE_BRI], 127)
|
||||||
light.DOMAIN, const.SERVICE_TURN_OFF,
|
|
||||||
{
|
# Turn bedroom light off
|
||||||
const.ATTR_ENTITY_ID: 'light.bed_light'
|
self.hass.services.call(
|
||||||
},
|
light.DOMAIN, const.SERVICE_TURN_OFF,
|
||||||
blocking=True)
|
{
|
||||||
|
const.ATTR_ENTITY_ID: 'light.bed_light'
|
||||||
bedroom_json = self.perform_get_light_state('light.bed_light', 200)
|
},
|
||||||
|
blocking=True)
|
||||||
self.assertEqual(bedroom_json['state'][HUE_API_STATE_ON], False)
|
|
||||||
self.assertEqual(bedroom_json['state'][HUE_API_STATE_BRI], 0)
|
bedroom_json = self.perform_get_light_state('light.bed_light', 200)
|
||||||
|
|
||||||
# Make sure kitchen light isn't accessible
|
self.assertEqual(bedroom_json['state'][HUE_API_STATE_ON], False)
|
||||||
kitchen_url = '/api/username/lights/{}'.format('light.kitchen_lights')
|
self.assertEqual(bedroom_json['state'][HUE_API_STATE_BRI], 0)
|
||||||
kitchen_result = requests.get(
|
|
||||||
BRIDGE_URL_BASE.format(kitchen_url), timeout=5)
|
# Make sure kitchen light isn't accessible
|
||||||
|
kitchen_url = '/api/username/lights/{}'.format('light.kitchen_lights')
|
||||||
self.assertEqual(kitchen_result.status_code, 404)
|
kitchen_result = requests.get(
|
||||||
|
BRIDGE_URL_BASE.format(kitchen_url), timeout=5)
|
||||||
def test_put_light_state(self):
|
|
||||||
"""Test the seeting of light states."""
|
self.assertEqual(kitchen_result.status_code, 404)
|
||||||
self.perform_put_test_on_ceiling_lights()
|
|
||||||
|
def test_put_light_state(self):
|
||||||
# Turn the bedroom light on first
|
"""Test the seeting of light states."""
|
||||||
self.hass.services.call(
|
self.perform_put_test_on_ceiling_lights()
|
||||||
light.DOMAIN, const.SERVICE_TURN_ON,
|
|
||||||
{const.ATTR_ENTITY_ID: 'light.bed_light',
|
# Turn the bedroom light on first
|
||||||
light.ATTR_BRIGHTNESS: 153},
|
self.hass.services.call(
|
||||||
blocking=True)
|
light.DOMAIN, const.SERVICE_TURN_ON,
|
||||||
|
{const.ATTR_ENTITY_ID: 'light.bed_light',
|
||||||
bed_light = self.hass.states.get('light.bed_light')
|
light.ATTR_BRIGHTNESS: 153},
|
||||||
self.assertEqual(bed_light.state, STATE_ON)
|
blocking=True)
|
||||||
self.assertEqual(bed_light.attributes[light.ATTR_BRIGHTNESS], 153)
|
|
||||||
|
bed_light = self.hass.states.get('light.bed_light')
|
||||||
# Go through the API to turn it off
|
self.assertEqual(bed_light.state, STATE_ON)
|
||||||
bedroom_result = self.perform_put_light_state(
|
self.assertEqual(bed_light.attributes[light.ATTR_BRIGHTNESS], 153)
|
||||||
'light.bed_light', False)
|
|
||||||
|
# Go through the API to turn it off
|
||||||
bedroom_result_json = bedroom_result.json()
|
bedroom_result = self.perform_put_light_state(
|
||||||
|
'light.bed_light', False)
|
||||||
self.assertEqual(bedroom_result.status_code, 200)
|
|
||||||
self.assertTrue(
|
bedroom_result_json = bedroom_result.json()
|
||||||
'application/json' in bedroom_result.headers['content-type'])
|
|
||||||
|
self.assertEqual(bedroom_result.status_code, 200)
|
||||||
self.assertEqual(len(bedroom_result_json), 1)
|
self.assertTrue(
|
||||||
|
'application/json' in bedroom_result.headers['content-type'])
|
||||||
# Check to make sure the state changed
|
|
||||||
bed_light = self.hass.states.get('light.bed_light')
|
self.assertEqual(len(bedroom_result_json), 1)
|
||||||
self.assertEqual(bed_light.state, STATE_OFF)
|
|
||||||
|
# Check to make sure the state changed
|
||||||
# Make sure we can't change the kitchen light state
|
bed_light = self.hass.states.get('light.bed_light')
|
||||||
kitchen_result = self.perform_put_light_state(
|
self.assertEqual(bed_light.state, STATE_OFF)
|
||||||
'light.kitchen_light', True)
|
|
||||||
self.assertEqual(kitchen_result.status_code, 404)
|
# Make sure we can't change the kitchen light state
|
||||||
|
kitchen_result = self.perform_put_light_state(
|
||||||
def test_put_with_form_urlencoded_content_type(self):
|
'light.kitchen_light', True)
|
||||||
"""Test the form with urlencoded content."""
|
self.assertEqual(kitchen_result.status_code, 404)
|
||||||
# Needed for Alexa
|
|
||||||
self.perform_put_test_on_ceiling_lights(
|
def test_put_with_form_urlencoded_content_type(self):
|
||||||
'application/x-www-form-urlencoded')
|
"""Test the form with urlencoded content."""
|
||||||
|
# Needed for Alexa
|
||||||
# Make sure we fail gracefully when we can't parse the data
|
self.perform_put_test_on_ceiling_lights(
|
||||||
data = {'key1': 'value1', 'key2': 'value2'}
|
'application/x-www-form-urlencoded')
|
||||||
result = requests.put(
|
|
||||||
BRIDGE_URL_BASE.format(
|
# Make sure we fail gracefully when we can't parse the data
|
||||||
'/api/username/lights/{}/state'.format(
|
data = {'key1': 'value1', 'key2': 'value2'}
|
||||||
"light.ceiling_lights")), data=data)
|
result = requests.put(
|
||||||
|
BRIDGE_URL_BASE.format(
|
||||||
self.assertEqual(result.status_code, 400)
|
'/api/username/lights/{}/state'.format(
|
||||||
|
"light.ceiling_lights")), data=data)
|
||||||
def test_entity_not_found(self):
|
|
||||||
"""Test for entity which are not found."""
|
self.assertEqual(result.status_code, 400)
|
||||||
result = requests.get(
|
|
||||||
BRIDGE_URL_BASE.format(
|
def test_entity_not_found(self):
|
||||||
'/api/username/lights/{}'.format("not.existant_entity")),
|
"""Test for entity which are not found."""
|
||||||
timeout=5)
|
result = requests.get(
|
||||||
|
BRIDGE_URL_BASE.format(
|
||||||
self.assertEqual(result.status_code, 404)
|
'/api/username/lights/{}'.format("not.existant_entity")),
|
||||||
|
timeout=5)
|
||||||
result = requests.put(
|
|
||||||
BRIDGE_URL_BASE.format(
|
self.assertEqual(result.status_code, 404)
|
||||||
'/api/username/lights/{}/state'.format("non.existant_entity")),
|
|
||||||
timeout=5)
|
result = requests.put(
|
||||||
|
BRIDGE_URL_BASE.format(
|
||||||
self.assertEqual(result.status_code, 404)
|
'/api/username/lights/{}/state'.format("non.existant_entity")),
|
||||||
|
timeout=5)
|
||||||
def test_allowed_methods(self):
|
|
||||||
"""Test the allowed methods."""
|
self.assertEqual(result.status_code, 404)
|
||||||
result = requests.get(
|
|
||||||
BRIDGE_URL_BASE.format(
|
def test_allowed_methods(self):
|
||||||
'/api/username/lights/{}/state'.format(
|
"""Test the allowed methods."""
|
||||||
"light.ceiling_lights")))
|
result = requests.get(
|
||||||
|
BRIDGE_URL_BASE.format(
|
||||||
self.assertEqual(result.status_code, 405)
|
'/api/username/lights/{}/state'.format(
|
||||||
|
"light.ceiling_lights")))
|
||||||
result = requests.put(
|
|
||||||
BRIDGE_URL_BASE.format(
|
self.assertEqual(result.status_code, 405)
|
||||||
'/api/username/lights/{}'.format("light.ceiling_lights")),
|
|
||||||
data={'key1': 'value1'})
|
result = requests.put(
|
||||||
|
BRIDGE_URL_BASE.format(
|
||||||
self.assertEqual(result.status_code, 405)
|
'/api/username/lights/{}'.format("light.ceiling_lights")),
|
||||||
|
data={'key1': 'value1'})
|
||||||
result = requests.put(
|
|
||||||
BRIDGE_URL_BASE.format('/api/username/lights'),
|
self.assertEqual(result.status_code, 405)
|
||||||
data={'key1': 'value1'})
|
|
||||||
|
result = requests.put(
|
||||||
self.assertEqual(result.status_code, 405)
|
BRIDGE_URL_BASE.format('/api/username/lights'),
|
||||||
|
data={'key1': 'value1'})
|
||||||
def test_proper_put_state_request(self):
|
|
||||||
"""Test the request to set the state."""
|
self.assertEqual(result.status_code, 405)
|
||||||
# Test proper on value parsing
|
|
||||||
result = requests.put(
|
def test_proper_put_state_request(self):
|
||||||
BRIDGE_URL_BASE.format(
|
"""Test the request to set the state."""
|
||||||
'/api/username/lights/{}/state'.format(
|
# Test proper on value parsing
|
||||||
"light.ceiling_lights")),
|
result = requests.put(
|
||||||
data=json.dumps({HUE_API_STATE_ON: 1234}))
|
BRIDGE_URL_BASE.format(
|
||||||
|
'/api/username/lights/{}/state'.format(
|
||||||
self.assertEqual(result.status_code, 400)
|
"light.ceiling_lights")),
|
||||||
|
data=json.dumps({HUE_API_STATE_ON: 1234}))
|
||||||
# Test proper brightness value parsing
|
|
||||||
result = requests.put(
|
self.assertEqual(result.status_code, 400)
|
||||||
BRIDGE_URL_BASE.format(
|
|
||||||
'/api/username/lights/{}/state'.format(
|
# Test proper brightness value parsing
|
||||||
"light.ceiling_lights")), data=json.dumps({
|
result = requests.put(
|
||||||
HUE_API_STATE_ON: True,
|
BRIDGE_URL_BASE.format(
|
||||||
HUE_API_STATE_BRI: 'Hello world!'
|
'/api/username/lights/{}/state'.format(
|
||||||
}))
|
"light.ceiling_lights")), data=json.dumps({
|
||||||
|
HUE_API_STATE_ON: True,
|
||||||
self.assertEqual(result.status_code, 400)
|
HUE_API_STATE_BRI: 'Hello world!'
|
||||||
|
}))
|
||||||
def perform_put_test_on_ceiling_lights(self,
|
|
||||||
content_type='application/json'):
|
self.assertEqual(result.status_code, 400)
|
||||||
"""Test the setting of a light."""
|
|
||||||
# Turn the office light off first
|
def perform_put_test_on_ceiling_lights(self,
|
||||||
self.hass.services.call(
|
content_type='application/json'):
|
||||||
light.DOMAIN, const.SERVICE_TURN_OFF,
|
"""Test the setting of a light."""
|
||||||
{const.ATTR_ENTITY_ID: 'light.ceiling_lights'},
|
# Turn the office light off first
|
||||||
blocking=True)
|
self.hass.services.call(
|
||||||
|
light.DOMAIN, const.SERVICE_TURN_OFF,
|
||||||
ceiling_lights = self.hass.states.get('light.ceiling_lights')
|
{const.ATTR_ENTITY_ID: 'light.ceiling_lights'},
|
||||||
self.assertEqual(ceiling_lights.state, STATE_OFF)
|
blocking=True)
|
||||||
|
|
||||||
# Go through the API to turn it on
|
ceiling_lights = self.hass.states.get('light.ceiling_lights')
|
||||||
office_result = self.perform_put_light_state(
|
self.assertEqual(ceiling_lights.state, STATE_OFF)
|
||||||
'light.ceiling_lights', True, 56, content_type)
|
|
||||||
|
# Go through the API to turn it on
|
||||||
office_result_json = office_result.json()
|
office_result = self.perform_put_light_state(
|
||||||
|
'light.ceiling_lights', True, 56, content_type)
|
||||||
self.assertEqual(office_result.status_code, 200)
|
|
||||||
self.assertTrue(
|
office_result_json = office_result.json()
|
||||||
'application/json' in office_result.headers['content-type'])
|
|
||||||
|
self.assertEqual(office_result.status_code, 200)
|
||||||
self.assertEqual(len(office_result_json), 2)
|
self.assertTrue(
|
||||||
|
'application/json' in office_result.headers['content-type'])
|
||||||
# Check to make sure the state changed
|
|
||||||
ceiling_lights = self.hass.states.get('light.ceiling_lights')
|
self.assertEqual(len(office_result_json), 2)
|
||||||
self.assertEqual(ceiling_lights.state, STATE_ON)
|
|
||||||
self.assertEqual(ceiling_lights.attributes[light.ATTR_BRIGHTNESS], 56)
|
# Check to make sure the state changed
|
||||||
|
ceiling_lights = self.hass.states.get('light.ceiling_lights')
|
||||||
def perform_get_light_state(self, entity_id, expected_status):
|
self.assertEqual(ceiling_lights.state, STATE_ON)
|
||||||
"""Test the gettting of a light state."""
|
self.assertEqual(ceiling_lights.attributes[light.ATTR_BRIGHTNESS], 56)
|
||||||
result = requests.get(
|
|
||||||
BRIDGE_URL_BASE.format(
|
def perform_get_light_state(self, entity_id, expected_status):
|
||||||
'/api/username/lights/{}'.format(entity_id)), timeout=5)
|
"""Test the gettting of a light state."""
|
||||||
|
result = requests.get(
|
||||||
self.assertEqual(result.status_code, expected_status)
|
BRIDGE_URL_BASE.format(
|
||||||
|
'/api/username/lights/{}'.format(entity_id)), timeout=5)
|
||||||
if expected_status == 200:
|
|
||||||
self.assertTrue(
|
self.assertEqual(result.status_code, expected_status)
|
||||||
'application/json' in result.headers['content-type'])
|
|
||||||
|
if expected_status == 200:
|
||||||
return result.json()
|
self.assertTrue(
|
||||||
|
'application/json' in result.headers['content-type'])
|
||||||
return None
|
|
||||||
|
return result.json()
|
||||||
def perform_put_light_state(self, entity_id, is_on, brightness=None,
|
|
||||||
content_type='application/json'):
|
return None
|
||||||
"""Test the setting of a light state."""
|
|
||||||
url = BRIDGE_URL_BASE.format(
|
def perform_put_light_state(self, entity_id, is_on, brightness=None,
|
||||||
'/api/username/lights/{}/state'.format(entity_id))
|
content_type='application/json'):
|
||||||
|
"""Test the setting of a light state."""
|
||||||
req_headers = {'Content-Type': content_type}
|
url = BRIDGE_URL_BASE.format(
|
||||||
|
'/api/username/lights/{}/state'.format(entity_id))
|
||||||
data = {HUE_API_STATE_ON: is_on}
|
|
||||||
|
req_headers = {'Content-Type': content_type}
|
||||||
if brightness is not None:
|
|
||||||
data[HUE_API_STATE_BRI] = brightness
|
data = {HUE_API_STATE_ON: is_on}
|
||||||
|
|
||||||
result = requests.put(
|
if brightness is not None:
|
||||||
url, data=json.dumps(data), timeout=5, headers=req_headers)
|
data[HUE_API_STATE_BRI] = brightness
|
||||||
return result
|
|
||||||
|
result = requests.put(
|
||||||
|
url, data=json.dumps(data), timeout=5, headers=req_headers)
|
||||||
class MQTTBroker(object):
|
|
||||||
"""Encapsulates an embedded MQTT broker."""
|
return result
|
||||||
|
|
||||||
def __init__(self, host, port):
|
|
||||||
"""Initialize a new instance."""
|
class MQTTBroker(object):
|
||||||
from hbmqtt.broker import Broker
|
"""Encapsulates an embedded MQTT broker."""
|
||||||
|
|
||||||
self._loop = asyncio.new_event_loop()
|
def __init__(self, host, port):
|
||||||
|
"""Initialize a new instance."""
|
||||||
hbmqtt_config = {
|
from hbmqtt.broker import Broker
|
||||||
'listeners': {
|
|
||||||
'default': {
|
self._loop = asyncio.new_event_loop()
|
||||||
'max-connections': 50000,
|
|
||||||
'type': 'tcp',
|
hbmqtt_config = {
|
||||||
'bind': '{}:{}'.format(host, port)
|
'listeners': {
|
||||||
}
|
'default': {
|
||||||
},
|
'max-connections': 50000,
|
||||||
'auth': {
|
'type': 'tcp',
|
||||||
'plugins': ['auth.anonymous'],
|
'bind': '{}:{}'.format(host, port)
|
||||||
'allow-anonymous': True
|
}
|
||||||
}
|
},
|
||||||
}
|
'auth': {
|
||||||
|
'plugins': ['auth.anonymous'],
|
||||||
self._broker = Broker(config=hbmqtt_config, loop=self._loop)
|
'allow-anonymous': True
|
||||||
|
}
|
||||||
self._thread = threading.Thread(target=self._run_loop)
|
}
|
||||||
self._started_ev = threading.Event()
|
|
||||||
|
self._broker = Broker(config=hbmqtt_config, loop=self._loop)
|
||||||
def start(self):
|
|
||||||
"""Start the broker."""
|
self._thread = threading.Thread(target=self._run_loop)
|
||||||
self._thread.start()
|
self._started_ev = threading.Event()
|
||||||
self._started_ev.wait()
|
|
||||||
|
def start(self):
|
||||||
def stop(self):
|
"""Start the broker."""
|
||||||
"""Stop the broker."""
|
self._thread.start()
|
||||||
self._loop.call_soon_threadsafe(asyncio.async, self._broker.shutdown())
|
self._started_ev.wait()
|
||||||
self._loop.call_soon_threadsafe(self._loop.stop)
|
|
||||||
self._thread.join()
|
def stop(self):
|
||||||
|
"""Stop the broker."""
|
||||||
def _run_loop(self):
|
self._loop.call_soon_threadsafe(asyncio.async, self._broker.shutdown())
|
||||||
"""Run the loop."""
|
self._loop.call_soon_threadsafe(self._loop.stop)
|
||||||
asyncio.set_event_loop(self._loop)
|
self._thread.join()
|
||||||
self._loop.run_until_complete(self._broker_coroutine())
|
|
||||||
|
def _run_loop(self):
|
||||||
self._started_ev.set()
|
"""Run the loop."""
|
||||||
|
asyncio.set_event_loop(self._loop)
|
||||||
self._loop.run_forever()
|
self._loop.run_until_complete(self._broker_coroutine())
|
||||||
self._loop.close()
|
|
||||||
|
self._started_ev.set()
|
||||||
@asyncio.coroutine
|
|
||||||
def _broker_coroutine(self):
|
self._loop.run_forever()
|
||||||
"""The Broker coroutine."""
|
self._loop.close()
|
||||||
yield from self._broker.start()
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def _broker_coroutine(self):
|
||||||
|
"""The Broker coroutine."""
|
||||||
|
yield from self._broker.start()
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
"""The tests for the InfluxDB component."""
|
"""The tests for the InfluxDB component."""
|
||||||
import unittest
|
import unittest
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
from unittest.mock import patch
|
|
||||||
|
|
||||||
import influxdb as influx_client
|
import influxdb as influx_client
|
||||||
|
|
||||||
@ -9,6 +8,8 @@ from homeassistant.bootstrap import setup_component
|
|||||||
import homeassistant.components.influxdb as influxdb
|
import homeassistant.components.influxdb as influxdb
|
||||||
from homeassistant.const import EVENT_STATE_CHANGED, STATE_OFF, STATE_ON
|
from homeassistant.const import EVENT_STATE_CHANGED, STATE_OFF, STATE_ON
|
||||||
|
|
||||||
|
from tests.common import get_test_home_assistant
|
||||||
|
|
||||||
|
|
||||||
@mock.patch('influxdb.InfluxDBClient')
|
@mock.patch('influxdb.InfluxDBClient')
|
||||||
class TestInfluxDB(unittest.TestCase):
|
class TestInfluxDB(unittest.TestCase):
|
||||||
@ -16,9 +17,13 @@ class TestInfluxDB(unittest.TestCase):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""Setup things to be run when tests are started."""
|
"""Setup things to be run when tests are started."""
|
||||||
self.hass = mock.MagicMock()
|
self.hass = get_test_home_assistant(2)
|
||||||
self.hass.pool.worker_count = 2
|
|
||||||
self.handler_method = None
|
self.handler_method = None
|
||||||
|
self.hass.bus.listen = mock.Mock()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
"""Clear data."""
|
||||||
|
self.hass.stop()
|
||||||
|
|
||||||
def test_setup_config_full(self, mock_client):
|
def test_setup_config_full(self, mock_client):
|
||||||
"""Test the setup with full configuration."""
|
"""Test the setup with full configuration."""
|
||||||
@ -61,8 +66,6 @@ class TestInfluxDB(unittest.TestCase):
|
|||||||
|
|
||||||
assert setup_component(self.hass, influxdb.DOMAIN, config)
|
assert setup_component(self.hass, influxdb.DOMAIN, config)
|
||||||
|
|
||||||
@patch('homeassistant.components.persistent_notification.create',
|
|
||||||
mock.MagicMock())
|
|
||||||
def test_setup_missing_password(self, mock_client):
|
def test_setup_missing_password(self, mock_client):
|
||||||
"""Test the setup with existing username and missing password."""
|
"""Test the setup with existing username and missing password."""
|
||||||
config = {
|
config = {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
"""The testd for Core components."""
|
"""The testd for Core components."""
|
||||||
# pylint: disable=protected-access,too-many-public-methods
|
# pylint: disable=protected-access,too-many-public-methods
|
||||||
|
import asyncio
|
||||||
import unittest
|
import unittest
|
||||||
from unittest.mock import patch, Mock
|
from unittest.mock import patch, Mock
|
||||||
|
|
||||||
@ -11,6 +12,7 @@ from homeassistant.const import (
|
|||||||
STATE_ON, STATE_OFF, SERVICE_TURN_ON, SERVICE_TURN_OFF, SERVICE_TOGGLE)
|
STATE_ON, STATE_OFF, SERVICE_TURN_ON, SERVICE_TURN_OFF, SERVICE_TOGGLE)
|
||||||
import homeassistant.components as comps
|
import homeassistant.components as comps
|
||||||
from homeassistant.helpers import entity
|
from homeassistant.helpers import entity
|
||||||
|
from homeassistant.util.async import run_coroutine_threadsafe
|
||||||
|
|
||||||
from tests.common import (
|
from tests.common import (
|
||||||
get_test_home_assistant, mock_service, patch_yaml_files)
|
get_test_home_assistant, mock_service, patch_yaml_files)
|
||||||
@ -22,7 +24,9 @@ class TestComponentsCore(unittest.TestCase):
|
|||||||
def setUp(self): # pylint: disable=invalid-name
|
def setUp(self): # pylint: disable=invalid-name
|
||||||
"""Setup things to be run when tests are started."""
|
"""Setup things to be run when tests are started."""
|
||||||
self.hass = get_test_home_assistant()
|
self.hass = get_test_home_assistant()
|
||||||
self.assertTrue(comps.setup(self.hass, {}))
|
self.assertTrue(run_coroutine_threadsafe(
|
||||||
|
comps.async_setup(self.hass, {}), self.hass.loop
|
||||||
|
).result())
|
||||||
|
|
||||||
self.hass.states.set('light.Bowl', STATE_ON)
|
self.hass.states.set('light.Bowl', STATE_ON)
|
||||||
self.hass.states.set('light.Ceiling', STATE_OFF)
|
self.hass.states.set('light.Ceiling', STATE_OFF)
|
||||||
@ -66,6 +70,7 @@ class TestComponentsCore(unittest.TestCase):
|
|||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
self.assertEqual(1, len(calls))
|
self.assertEqual(1, len(calls))
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
@patch('homeassistant.core.ServiceRegistry.call')
|
@patch('homeassistant.core.ServiceRegistry.call')
|
||||||
def test_turn_on_to_not_block_for_domains_without_service(self, mock_call):
|
def test_turn_on_to_not_block_for_domains_without_service(self, mock_call):
|
||||||
"""Test if turn_on is blocking domain with no service."""
|
"""Test if turn_on is blocking domain with no service."""
|
||||||
@ -78,7 +83,7 @@ class TestComponentsCore(unittest.TestCase):
|
|||||||
'entity_id': ['light.test', 'sensor.bla', 'light.bla']
|
'entity_id': ['light.test', 'sensor.bla', 'light.bla']
|
||||||
})
|
})
|
||||||
service = self.hass.services._services['homeassistant']['turn_on']
|
service = self.hass.services._services['homeassistant']['turn_on']
|
||||||
service.func(service_call)
|
yield from service.func(service_call)
|
||||||
|
|
||||||
self.assertEqual(2, mock_call.call_count)
|
self.assertEqual(2, mock_call.call_count)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
@ -131,7 +136,7 @@ class TestComponentsCore(unittest.TestCase):
|
|||||||
|
|
||||||
@patch('homeassistant.config.os.path.isfile', Mock(return_value=True))
|
@patch('homeassistant.config.os.path.isfile', Mock(return_value=True))
|
||||||
@patch('homeassistant.components._LOGGER.error')
|
@patch('homeassistant.components._LOGGER.error')
|
||||||
@patch('homeassistant.config.process_ha_core_config')
|
@patch('homeassistant.config.async_process_ha_core_config')
|
||||||
def test_reload_core_with_wrong_conf(self, mock_process, mock_error):
|
def test_reload_core_with_wrong_conf(self, mock_process, mock_error):
|
||||||
"""Test reload core conf service."""
|
"""Test reload core conf service."""
|
||||||
files = {
|
files = {
|
||||||
|
@ -7,10 +7,20 @@ from homeassistant.bootstrap import setup_component
|
|||||||
import homeassistant.components.logentries as logentries
|
import homeassistant.components.logentries as logentries
|
||||||
from homeassistant.const import STATE_ON, STATE_OFF, EVENT_STATE_CHANGED
|
from homeassistant.const import STATE_ON, STATE_OFF, EVENT_STATE_CHANGED
|
||||||
|
|
||||||
|
from tests.common import get_test_home_assistant
|
||||||
|
|
||||||
|
|
||||||
class TestLogentries(unittest.TestCase):
|
class TestLogentries(unittest.TestCase):
|
||||||
"""Test the Logentries component."""
|
"""Test the Logentries component."""
|
||||||
|
|
||||||
|
def setUp(self): # pylint: disable=invalid-name
|
||||||
|
"""Setup things to be run when tests are started."""
|
||||||
|
self.hass = get_test_home_assistant(2)
|
||||||
|
|
||||||
|
def tearDown(self): # pylint: disable=invalid-name
|
||||||
|
"""Stop everything that was started."""
|
||||||
|
self.hass.stop()
|
||||||
|
|
||||||
def test_setup_config_full(self):
|
def test_setup_config_full(self):
|
||||||
"""Test setup with all data."""
|
"""Test setup with all data."""
|
||||||
config = {
|
config = {
|
||||||
@ -18,12 +28,11 @@ class TestLogentries(unittest.TestCase):
|
|||||||
'token': 'secret',
|
'token': 'secret',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hass = mock.MagicMock()
|
self.hass.bus.listen = mock.MagicMock()
|
||||||
hass.pool.worker_count = 2
|
self.assertTrue(setup_component(self.hass, logentries.DOMAIN, config))
|
||||||
self.assertTrue(setup_component(hass, logentries.DOMAIN, config))
|
self.assertTrue(self.hass.bus.listen.called)
|
||||||
self.assertTrue(hass.bus.listen.called)
|
|
||||||
self.assertEqual(EVENT_STATE_CHANGED,
|
self.assertEqual(EVENT_STATE_CHANGED,
|
||||||
hass.bus.listen.call_args_list[0][0][0])
|
self.hass.bus.listen.call_args_list[0][0][0])
|
||||||
|
|
||||||
def test_setup_config_defaults(self):
|
def test_setup_config_defaults(self):
|
||||||
"""Test setup with defaults."""
|
"""Test setup with defaults."""
|
||||||
@ -32,12 +41,11 @@ class TestLogentries(unittest.TestCase):
|
|||||||
'token': 'token',
|
'token': 'token',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hass = mock.MagicMock()
|
self.hass.bus.listen = mock.MagicMock()
|
||||||
hass.pool.worker_count = 2
|
self.assertTrue(setup_component(self.hass, logentries.DOMAIN, config))
|
||||||
self.assertTrue(setup_component(hass, logentries.DOMAIN, config))
|
self.assertTrue(self.hass.bus.listen.called)
|
||||||
self.assertTrue(hass.bus.listen.called)
|
|
||||||
self.assertEqual(EVENT_STATE_CHANGED,
|
self.assertEqual(EVENT_STATE_CHANGED,
|
||||||
hass.bus.listen.call_args_list[0][0][0])
|
self.hass.bus.listen.call_args_list[0][0][0])
|
||||||
|
|
||||||
def _setup(self, mock_requests):
|
def _setup(self, mock_requests):
|
||||||
"""Test the setup."""
|
"""Test the setup."""
|
||||||
@ -49,8 +57,7 @@ class TestLogentries(unittest.TestCase):
|
|||||||
'token': 'token'
|
'token': 'token'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.hass = mock.MagicMock()
|
self.hass.bus.listen = mock.MagicMock()
|
||||||
self.hass.pool.worker_count = 2
|
|
||||||
setup_component(self.hass, logentries.DOMAIN, config)
|
setup_component(self.hass, logentries.DOMAIN, config)
|
||||||
self.handler_method = self.hass.bus.listen.call_args_list[0][0][1]
|
self.handler_method = self.hass.bus.listen.call_args_list[0][0][1]
|
||||||
|
|
||||||
|
@ -2,11 +2,12 @@
|
|||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
import logging
|
import logging
|
||||||
import unittest
|
import unittest
|
||||||
from unittest.mock import MagicMock
|
|
||||||
|
|
||||||
from homeassistant.bootstrap import setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
from homeassistant.components import logger
|
from homeassistant.components import logger
|
||||||
|
|
||||||
|
from tests.common import get_test_home_assistant
|
||||||
|
|
||||||
RECORD = namedtuple('record', ('name', 'levelno'))
|
RECORD = namedtuple('record', ('name', 'levelno'))
|
||||||
|
|
||||||
|
|
||||||
@ -15,18 +16,18 @@ class TestUpdater(unittest.TestCase):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""Setup things to be run when tests are started."""
|
"""Setup things to be run when tests are started."""
|
||||||
|
self.hass = get_test_home_assistant(2)
|
||||||
self.log_config = {'logger':
|
self.log_config = {'logger':
|
||||||
{'default': 'warning', 'logs': {'test': 'info'}}}
|
{'default': 'warning', 'logs': {'test': 'info'}}}
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
"""Stop everything that was started."""
|
"""Stop everything that was started."""
|
||||||
del logging.root.handlers[-1]
|
del logging.root.handlers[-1]
|
||||||
|
self.hass.stop()
|
||||||
|
|
||||||
def test_logger_setup(self):
|
def test_logger_setup(self):
|
||||||
"""Use logger to create a logging filter."""
|
"""Use logger to create a logging filter."""
|
||||||
hass = MagicMock()
|
setup_component(self.hass, logger.DOMAIN, self.log_config)
|
||||||
hass.pool.worker_count = 2
|
|
||||||
setup_component(hass, logger.DOMAIN, self.log_config)
|
|
||||||
|
|
||||||
self.assertTrue(len(logging.root.handlers) > 0)
|
self.assertTrue(len(logging.root.handlers) > 0)
|
||||||
handler = logging.root.handlers[-1]
|
handler = logging.root.handlers[-1]
|
||||||
@ -39,9 +40,7 @@ class TestUpdater(unittest.TestCase):
|
|||||||
|
|
||||||
def test_logger_test_filters(self):
|
def test_logger_test_filters(self):
|
||||||
"""Test resulting filter operation."""
|
"""Test resulting filter operation."""
|
||||||
hass = MagicMock()
|
setup_component(self.hass, logger.DOMAIN, self.log_config)
|
||||||
hass.pool.worker_count = 2
|
|
||||||
setup_component(hass, logger.DOMAIN, self.log_config)
|
|
||||||
|
|
||||||
log_filter = logging.root.handlers[-1].filters[0]
|
log_filter = logging.root.handlers[-1].filters[0]
|
||||||
|
|
||||||
|
@ -10,7 +10,8 @@ from homeassistant.components import panel_custom
|
|||||||
from tests.common import get_test_home_assistant
|
from tests.common import get_test_home_assistant
|
||||||
|
|
||||||
|
|
||||||
@patch('homeassistant.components.frontend.setup', return_value=True)
|
@patch('homeassistant.components.frontend.setup',
|
||||||
|
autospec=True, return_value=True)
|
||||||
class TestPanelCustom(unittest.TestCase):
|
class TestPanelCustom(unittest.TestCase):
|
||||||
"""Test the panel_custom component."""
|
"""Test the panel_custom component."""
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import unittest
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant.bootstrap import _setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
from homeassistant.components import rfxtrx as rfxtrx
|
from homeassistant.components import rfxtrx as rfxtrx
|
||||||
from tests.common import get_test_home_assistant
|
from tests.common import get_test_home_assistant
|
||||||
|
|
||||||
@ -27,14 +27,14 @@ class TestRFXTRX(unittest.TestCase):
|
|||||||
|
|
||||||
def test_default_config(self):
|
def test_default_config(self):
|
||||||
"""Test configuration."""
|
"""Test configuration."""
|
||||||
self.assertTrue(_setup_component(self.hass, 'rfxtrx', {
|
self.assertTrue(setup_component(self.hass, 'rfxtrx', {
|
||||||
'rfxtrx': {
|
'rfxtrx': {
|
||||||
'device': '/dev/serial/by-id/usb' +
|
'device': '/dev/serial/by-id/usb' +
|
||||||
'-RFXCOM_RFXtrx433_A1Y0NJGR-if00-port0',
|
'-RFXCOM_RFXtrx433_A1Y0NJGR-if00-port0',
|
||||||
'dummy': True}
|
'dummy': True}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
self.assertTrue(_setup_component(self.hass, 'sensor', {
|
self.assertTrue(setup_component(self.hass, 'sensor', {
|
||||||
'sensor': {'platform': 'rfxtrx',
|
'sensor': {'platform': 'rfxtrx',
|
||||||
'automatic_add': True,
|
'automatic_add': True,
|
||||||
'devices': {}}}))
|
'devices': {}}}))
|
||||||
@ -43,7 +43,7 @@ class TestRFXTRX(unittest.TestCase):
|
|||||||
|
|
||||||
def test_valid_config(self):
|
def test_valid_config(self):
|
||||||
"""Test configuration."""
|
"""Test configuration."""
|
||||||
self.assertTrue(_setup_component(self.hass, 'rfxtrx', {
|
self.assertTrue(setup_component(self.hass, 'rfxtrx', {
|
||||||
'rfxtrx': {
|
'rfxtrx': {
|
||||||
'device': '/dev/serial/by-id/usb' +
|
'device': '/dev/serial/by-id/usb' +
|
||||||
'-RFXCOM_RFXtrx433_A1Y0NJGR-if00-port0',
|
'-RFXCOM_RFXtrx433_A1Y0NJGR-if00-port0',
|
||||||
@ -51,7 +51,7 @@ class TestRFXTRX(unittest.TestCase):
|
|||||||
|
|
||||||
self.hass.config.components.remove('rfxtrx')
|
self.hass.config.components.remove('rfxtrx')
|
||||||
|
|
||||||
self.assertTrue(_setup_component(self.hass, 'rfxtrx', {
|
self.assertTrue(setup_component(self.hass, 'rfxtrx', {
|
||||||
'rfxtrx': {
|
'rfxtrx': {
|
||||||
'device': '/dev/serial/by-id/usb' +
|
'device': '/dev/serial/by-id/usb' +
|
||||||
'-RFXCOM_RFXtrx433_A1Y0NJGR-if00-port0',
|
'-RFXCOM_RFXtrx433_A1Y0NJGR-if00-port0',
|
||||||
@ -60,11 +60,11 @@ class TestRFXTRX(unittest.TestCase):
|
|||||||
|
|
||||||
def test_invalid_config(self):
|
def test_invalid_config(self):
|
||||||
"""Test configuration."""
|
"""Test configuration."""
|
||||||
self.assertFalse(_setup_component(self.hass, 'rfxtrx', {
|
self.assertFalse(setup_component(self.hass, 'rfxtrx', {
|
||||||
'rfxtrx': {}
|
'rfxtrx': {}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
self.assertFalse(_setup_component(self.hass, 'rfxtrx', {
|
self.assertFalse(setup_component(self.hass, 'rfxtrx', {
|
||||||
'rfxtrx': {
|
'rfxtrx': {
|
||||||
'device': '/dev/serial/by-id/usb' +
|
'device': '/dev/serial/by-id/usb' +
|
||||||
'-RFXCOM_RFXtrx433_A1Y0NJGR-if00-port0',
|
'-RFXCOM_RFXtrx433_A1Y0NJGR-if00-port0',
|
||||||
@ -72,13 +72,13 @@ class TestRFXTRX(unittest.TestCase):
|
|||||||
|
|
||||||
def test_fire_event(self):
|
def test_fire_event(self):
|
||||||
"""Test fire event."""
|
"""Test fire event."""
|
||||||
self.assertTrue(_setup_component(self.hass, 'rfxtrx', {
|
self.assertTrue(setup_component(self.hass, 'rfxtrx', {
|
||||||
'rfxtrx': {
|
'rfxtrx': {
|
||||||
'device': '/dev/serial/by-id/usb' +
|
'device': '/dev/serial/by-id/usb' +
|
||||||
'-RFXCOM_RFXtrx433_A1Y0NJGR-if00-port0',
|
'-RFXCOM_RFXtrx433_A1Y0NJGR-if00-port0',
|
||||||
'dummy': True}
|
'dummy': True}
|
||||||
}))
|
}))
|
||||||
self.assertTrue(_setup_component(self.hass, 'switch', {
|
self.assertTrue(setup_component(self.hass, 'switch', {
|
||||||
'switch': {'platform': 'rfxtrx',
|
'switch': {'platform': 'rfxtrx',
|
||||||
'automatic_add': True,
|
'automatic_add': True,
|
||||||
'devices':
|
'devices':
|
||||||
@ -116,13 +116,13 @@ class TestRFXTRX(unittest.TestCase):
|
|||||||
|
|
||||||
def test_fire_event_sensor(self):
|
def test_fire_event_sensor(self):
|
||||||
"""Test fire event."""
|
"""Test fire event."""
|
||||||
self.assertTrue(_setup_component(self.hass, 'rfxtrx', {
|
self.assertTrue(setup_component(self.hass, 'rfxtrx', {
|
||||||
'rfxtrx': {
|
'rfxtrx': {
|
||||||
'device': '/dev/serial/by-id/usb' +
|
'device': '/dev/serial/by-id/usb' +
|
||||||
'-RFXCOM_RFXtrx433_A1Y0NJGR-if00-port0',
|
'-RFXCOM_RFXtrx433_A1Y0NJGR-if00-port0',
|
||||||
'dummy': True}
|
'dummy': True}
|
||||||
}))
|
}))
|
||||||
self.assertTrue(_setup_component(self.hass, 'sensor', {
|
self.assertTrue(setup_component(self.hass, 'sensor', {
|
||||||
'sensor': {'platform': 'rfxtrx',
|
'sensor': {'platform': 'rfxtrx',
|
||||||
'automatic_add': True,
|
'automatic_add': True,
|
||||||
'devices':
|
'devices':
|
||||||
|
@ -65,11 +65,11 @@ class TestSleepIQ(unittest.TestCase):
|
|||||||
"""Test the setup when no login is configured."""
|
"""Test the setup when no login is configured."""
|
||||||
conf = self.config.copy()
|
conf = self.config.copy()
|
||||||
del conf['sleepiq']['username']
|
del conf['sleepiq']['username']
|
||||||
assert not bootstrap._setup_component(self.hass, sleepiq.DOMAIN, conf)
|
assert not bootstrap.setup_component(self.hass, sleepiq.DOMAIN, conf)
|
||||||
|
|
||||||
def test_setup_component_no_password(self):
|
def test_setup_component_no_password(self):
|
||||||
"""Test the setup when no password is configured."""
|
"""Test the setup when no password is configured."""
|
||||||
conf = self.config.copy()
|
conf = self.config.copy()
|
||||||
del conf['sleepiq']['password']
|
del conf['sleepiq']['password']
|
||||||
|
|
||||||
assert not bootstrap._setup_component(self.hass, sleepiq.DOMAIN, conf)
|
assert not bootstrap.setup_component(self.hass, sleepiq.DOMAIN, conf)
|
||||||
|
@ -6,10 +6,20 @@ from homeassistant.bootstrap import setup_component
|
|||||||
import homeassistant.components.splunk as splunk
|
import homeassistant.components.splunk as splunk
|
||||||
from homeassistant.const import STATE_ON, STATE_OFF, EVENT_STATE_CHANGED
|
from homeassistant.const import STATE_ON, STATE_OFF, EVENT_STATE_CHANGED
|
||||||
|
|
||||||
|
from tests.common import get_test_home_assistant
|
||||||
|
|
||||||
|
|
||||||
class TestSplunk(unittest.TestCase):
|
class TestSplunk(unittest.TestCase):
|
||||||
"""Test the Splunk component."""
|
"""Test the Splunk component."""
|
||||||
|
|
||||||
|
def setUp(self): # pylint: disable=invalid-name
|
||||||
|
"""Setup things to be run when tests are started."""
|
||||||
|
self.hass = get_test_home_assistant(2)
|
||||||
|
|
||||||
|
def tearDown(self): # pylint: disable=invalid-name
|
||||||
|
"""Stop everything that was started."""
|
||||||
|
self.hass.stop()
|
||||||
|
|
||||||
def test_setup_config_full(self):
|
def test_setup_config_full(self):
|
||||||
"""Test setup with all data."""
|
"""Test setup with all data."""
|
||||||
config = {
|
config = {
|
||||||
@ -21,12 +31,11 @@ class TestSplunk(unittest.TestCase):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hass = mock.MagicMock()
|
self.hass.bus.listen = mock.MagicMock()
|
||||||
hass.pool.worker_count = 2
|
self.assertTrue(setup_component(self.hass, splunk.DOMAIN, config))
|
||||||
self.assertTrue(setup_component(hass, splunk.DOMAIN, config))
|
self.assertTrue(self.hass.bus.listen.called)
|
||||||
self.assertTrue(hass.bus.listen.called)
|
|
||||||
self.assertEqual(EVENT_STATE_CHANGED,
|
self.assertEqual(EVENT_STATE_CHANGED,
|
||||||
hass.bus.listen.call_args_list[0][0][0])
|
self.hass.bus.listen.call_args_list[0][0][0])
|
||||||
|
|
||||||
def test_setup_config_defaults(self):
|
def test_setup_config_defaults(self):
|
||||||
"""Test setup with defaults."""
|
"""Test setup with defaults."""
|
||||||
@ -37,12 +46,11 @@ class TestSplunk(unittest.TestCase):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hass = mock.MagicMock()
|
self.hass.bus.listen = mock.MagicMock()
|
||||||
hass.pool.worker_count = 2
|
self.assertTrue(setup_component(self.hass, splunk.DOMAIN, config))
|
||||||
self.assertTrue(setup_component(hass, splunk.DOMAIN, config))
|
self.assertTrue(self.hass.bus.listen.called)
|
||||||
self.assertTrue(hass.bus.listen.called)
|
|
||||||
self.assertEqual(EVENT_STATE_CHANGED,
|
self.assertEqual(EVENT_STATE_CHANGED,
|
||||||
hass.bus.listen.call_args_list[0][0][0])
|
self.hass.bus.listen.call_args_list[0][0][0])
|
||||||
|
|
||||||
def _setup(self, mock_requests):
|
def _setup(self, mock_requests):
|
||||||
"""Test the setup."""
|
"""Test the setup."""
|
||||||
@ -57,8 +65,7 @@ class TestSplunk(unittest.TestCase):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.hass = mock.MagicMock()
|
self.hass.bus.listen = mock.MagicMock()
|
||||||
self.hass.pool.worker_count = 2
|
|
||||||
setup_component(self.hass, splunk.DOMAIN, config)
|
setup_component(self.hass, splunk.DOMAIN, config)
|
||||||
self.handler_method = self.hass.bus.listen.call_args_list[0][0][1]
|
self.handler_method = self.hass.bus.listen.call_args_list[0][0][1]
|
||||||
|
|
||||||
|
@ -9,10 +9,20 @@ import homeassistant.core as ha
|
|||||||
import homeassistant.components.statsd as statsd
|
import homeassistant.components.statsd as statsd
|
||||||
from homeassistant.const import (STATE_ON, STATE_OFF, EVENT_STATE_CHANGED)
|
from homeassistant.const import (STATE_ON, STATE_OFF, EVENT_STATE_CHANGED)
|
||||||
|
|
||||||
|
from tests.common import get_test_home_assistant
|
||||||
|
|
||||||
|
|
||||||
class TestStatsd(unittest.TestCase):
|
class TestStatsd(unittest.TestCase):
|
||||||
"""Test the StatsD component."""
|
"""Test the StatsD component."""
|
||||||
|
|
||||||
|
def setUp(self): # pylint: disable=invalid-name
|
||||||
|
"""Setup things to be run when tests are started."""
|
||||||
|
self.hass = get_test_home_assistant(2)
|
||||||
|
|
||||||
|
def tearDown(self): # pylint: disable=invalid-name
|
||||||
|
"""Stop everything that was started."""
|
||||||
|
self.hass.stop()
|
||||||
|
|
||||||
def test_invalid_config(self):
|
def test_invalid_config(self):
|
||||||
"""Test configuration with defaults."""
|
"""Test configuration with defaults."""
|
||||||
config = {
|
config = {
|
||||||
@ -37,18 +47,17 @@ class TestStatsd(unittest.TestCase):
|
|||||||
'prefix': 'foo',
|
'prefix': 'foo',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hass = mock.MagicMock()
|
self.hass.bus.listen = mock.MagicMock()
|
||||||
hass.pool.worker_count = 2
|
self.assertTrue(setup_component(self.hass, statsd.DOMAIN, config))
|
||||||
self.assertTrue(setup_component(hass, statsd.DOMAIN, config))
|
|
||||||
self.assertEqual(mock_connection.call_count, 1)
|
self.assertEqual(mock_connection.call_count, 1)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
mock_connection.call_args,
|
mock_connection.call_args,
|
||||||
mock.call(host='host', port=123, prefix='foo')
|
mock.call(host='host', port=123, prefix='foo')
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertTrue(hass.bus.listen.called)
|
self.assertTrue(self.hass.bus.listen.called)
|
||||||
self.assertEqual(EVENT_STATE_CHANGED,
|
self.assertEqual(EVENT_STATE_CHANGED,
|
||||||
hass.bus.listen.call_args_list[0][0][0])
|
self.hass.bus.listen.call_args_list[0][0][0])
|
||||||
|
|
||||||
@mock.patch('statsd.StatsClient')
|
@mock.patch('statsd.StatsClient')
|
||||||
def test_statsd_setup_defaults(self, mock_connection):
|
def test_statsd_setup_defaults(self, mock_connection):
|
||||||
@ -62,15 +71,14 @@ class TestStatsd(unittest.TestCase):
|
|||||||
config['statsd'][statsd.CONF_PORT] = statsd.DEFAULT_PORT
|
config['statsd'][statsd.CONF_PORT] = statsd.DEFAULT_PORT
|
||||||
config['statsd'][statsd.CONF_PREFIX] = statsd.DEFAULT_PREFIX
|
config['statsd'][statsd.CONF_PREFIX] = statsd.DEFAULT_PREFIX
|
||||||
|
|
||||||
hass = mock.MagicMock()
|
self.hass.bus.listen = mock.MagicMock()
|
||||||
hass.pool.worker_count = 2
|
self.assertTrue(setup_component(self.hass, statsd.DOMAIN, config))
|
||||||
self.assertTrue(setup_component(hass, statsd.DOMAIN, config))
|
|
||||||
self.assertEqual(mock_connection.call_count, 1)
|
self.assertEqual(mock_connection.call_count, 1)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
mock_connection.call_args,
|
mock_connection.call_args,
|
||||||
mock.call(host='host', port=8125, prefix='hass')
|
mock.call(host='host', port=8125, prefix='hass')
|
||||||
)
|
)
|
||||||
self.assertTrue(hass.bus.listen.called)
|
self.assertTrue(self.hass.bus.listen.called)
|
||||||
|
|
||||||
@mock.patch('statsd.StatsClient')
|
@mock.patch('statsd.StatsClient')
|
||||||
def test_event_listener_defaults(self, mock_client):
|
def test_event_listener_defaults(self, mock_client):
|
||||||
@ -83,11 +91,10 @@ class TestStatsd(unittest.TestCase):
|
|||||||
|
|
||||||
config['statsd'][statsd.CONF_RATE] = statsd.DEFAULT_RATE
|
config['statsd'][statsd.CONF_RATE] = statsd.DEFAULT_RATE
|
||||||
|
|
||||||
hass = mock.MagicMock()
|
self.hass.bus.listen = mock.MagicMock()
|
||||||
hass.pool.worker_count = 2
|
setup_component(self.hass, statsd.DOMAIN, config)
|
||||||
setup_component(hass, statsd.DOMAIN, config)
|
self.assertTrue(self.hass.bus.listen.called)
|
||||||
self.assertTrue(hass.bus.listen.called)
|
handler_method = self.hass.bus.listen.call_args_list[0][0][1]
|
||||||
handler_method = hass.bus.listen.call_args_list[0][0][1]
|
|
||||||
|
|
||||||
valid = {'1': 1,
|
valid = {'1': 1,
|
||||||
'1.0': 1.0,
|
'1.0': 1.0,
|
||||||
@ -128,11 +135,10 @@ class TestStatsd(unittest.TestCase):
|
|||||||
|
|
||||||
config['statsd'][statsd.CONF_RATE] = statsd.DEFAULT_RATE
|
config['statsd'][statsd.CONF_RATE] = statsd.DEFAULT_RATE
|
||||||
|
|
||||||
hass = mock.MagicMock()
|
self.hass.bus.listen = mock.MagicMock()
|
||||||
hass.pool.worker_count = 2
|
setup_component(self.hass, statsd.DOMAIN, config)
|
||||||
setup_component(hass, statsd.DOMAIN, config)
|
self.assertTrue(self.hass.bus.listen.called)
|
||||||
self.assertTrue(hass.bus.listen.called)
|
handler_method = self.hass.bus.listen.call_args_list[0][0][1]
|
||||||
handler_method = hass.bus.listen.call_args_list[0][0][1]
|
|
||||||
|
|
||||||
valid = {'1': 1,
|
valid = {'1': 1,
|
||||||
'1.0': 1.0,
|
'1.0': 1.0,
|
||||||
|
@ -127,4 +127,4 @@ class TestHelpersDiscovery:
|
|||||||
assert 'test_component' in self.hass.config.components
|
assert 'test_component' in self.hass.config.components
|
||||||
assert 'switch' in self.hass.config.components
|
assert 'switch' in self.hass.config.components
|
||||||
assert len(component_calls) == 1
|
assert len(component_calls) == 1
|
||||||
assert len(platform_calls) == 2
|
assert len(platform_calls) == 1
|
||||||
|
@ -7,6 +7,7 @@ from unittest.mock import patch
|
|||||||
import homeassistant.core as ha
|
import homeassistant.core as ha
|
||||||
import homeassistant.components as core_components
|
import homeassistant.components as core_components
|
||||||
from homeassistant.const import (SERVICE_TURN_ON, SERVICE_TURN_OFF)
|
from homeassistant.const import (SERVICE_TURN_ON, SERVICE_TURN_OFF)
|
||||||
|
from homeassistant.util.async import run_coroutine_threadsafe
|
||||||
from homeassistant.util import dt as dt_util
|
from homeassistant.util import dt as dt_util
|
||||||
from homeassistant.helpers import state
|
from homeassistant.helpers import state
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
@ -63,7 +64,8 @@ class TestStateHelpers(unittest.TestCase):
|
|||||||
def setUp(self): # pylint: disable=invalid-name
|
def setUp(self): # pylint: disable=invalid-name
|
||||||
"""Run when tests are started."""
|
"""Run when tests are started."""
|
||||||
self.hass = get_test_home_assistant()
|
self.hass = get_test_home_assistant()
|
||||||
core_components.setup(self.hass, {})
|
run_coroutine_threadsafe(core_components.async_setup(
|
||||||
|
self.hass, {}), self.hass.loop).result()
|
||||||
|
|
||||||
def tearDown(self): # pylint: disable=invalid-name
|
def tearDown(self): # pylint: disable=invalid-name
|
||||||
"""Stop when tests are finished."""
|
"""Stop when tests are finished."""
|
||||||
|
@ -3,7 +3,6 @@ import asyncio
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import unittest
|
import unittest
|
||||||
from unittest.mock import patch
|
|
||||||
|
|
||||||
import homeassistant.scripts.check_config as check_config
|
import homeassistant.scripts.check_config as check_config
|
||||||
from tests.common import patch_yaml_files, get_test_config_dir
|
from tests.common import patch_yaml_files, get_test_config_dir
|
||||||
@ -45,12 +44,22 @@ def tearDownModule(self): # pylint: disable=invalid-name
|
|||||||
os.remove(path)
|
os.remove(path)
|
||||||
|
|
||||||
|
|
||||||
@patch('asyncio.get_event_loop', return_value=asyncio.new_event_loop())
|
|
||||||
class TestCheckConfig(unittest.TestCase):
|
class TestCheckConfig(unittest.TestCase):
|
||||||
"""Tests for the homeassistant.scripts.check_config module."""
|
"""Tests for the homeassistant.scripts.check_config module."""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""Prepare the test."""
|
||||||
|
# Somewhere in the tests our event loop gets killed,
|
||||||
|
# this ensures we have one.
|
||||||
|
try:
|
||||||
|
asyncio.get_event_loop()
|
||||||
|
except (RuntimeError, AssertionError):
|
||||||
|
# Py35: RuntimeError
|
||||||
|
# Py34: AssertionError
|
||||||
|
asyncio.set_event_loop(asyncio.new_event_loop())
|
||||||
|
|
||||||
# pylint: disable=no-self-use,invalid-name
|
# pylint: disable=no-self-use,invalid-name
|
||||||
def test_config_platform_valid(self, mock_get_loop):
|
def test_config_platform_valid(self):
|
||||||
"""Test a valid platform setup."""
|
"""Test a valid platform setup."""
|
||||||
files = {
|
files = {
|
||||||
'light.yaml': BASE_CONFIG + 'light:\n platform: demo',
|
'light.yaml': BASE_CONFIG + 'light:\n platform: demo',
|
||||||
@ -66,7 +75,7 @@ class TestCheckConfig(unittest.TestCase):
|
|||||||
'yaml_files': ['.../light.yaml']
|
'yaml_files': ['.../light.yaml']
|
||||||
}, res)
|
}, res)
|
||||||
|
|
||||||
def test_config_component_platform_fail_validation(self, mock_get_loop):
|
def test_config_component_platform_fail_validation(self):
|
||||||
"""Test errors if component & platform not found."""
|
"""Test errors if component & platform not found."""
|
||||||
files = {
|
files = {
|
||||||
'component.yaml': BASE_CONFIG + 'http:\n password: err123',
|
'component.yaml': BASE_CONFIG + 'http:\n password: err123',
|
||||||
@ -104,7 +113,7 @@ class TestCheckConfig(unittest.TestCase):
|
|||||||
self.assertDictEqual({}, res['secrets'])
|
self.assertDictEqual({}, res['secrets'])
|
||||||
self.assertListEqual(['.../platform.yaml'], res['yaml_files'])
|
self.assertListEqual(['.../platform.yaml'], res['yaml_files'])
|
||||||
|
|
||||||
def test_component_platform_not_found(self, mock_get_loop):
|
def test_component_platform_not_found(self):
|
||||||
"""Test errors if component or platform not found."""
|
"""Test errors if component or platform not found."""
|
||||||
files = {
|
files = {
|
||||||
'badcomponent.yaml': BASE_CONFIG + 'beer:',
|
'badcomponent.yaml': BASE_CONFIG + 'beer:',
|
||||||
@ -131,7 +140,7 @@ class TestCheckConfig(unittest.TestCase):
|
|||||||
self.assertDictEqual({}, res['secrets'])
|
self.assertDictEqual({}, res['secrets'])
|
||||||
self.assertListEqual(['.../badplatform.yaml'], res['yaml_files'])
|
self.assertListEqual(['.../badplatform.yaml'], res['yaml_files'])
|
||||||
|
|
||||||
def test_secrets(self, mock_get_loop):
|
def test_secrets(self):
|
||||||
"""Test secrets config checking method."""
|
"""Test secrets config checking method."""
|
||||||
files = {
|
files = {
|
||||||
get_test_config_dir('secret.yaml'): (
|
get_test_config_dir('secret.yaml'): (
|
||||||
|
@ -48,11 +48,10 @@ class TestBootstrap:
|
|||||||
@mock.patch(
|
@mock.patch(
|
||||||
# prevent .HA_VERISON file from being written
|
# prevent .HA_VERISON file from being written
|
||||||
'homeassistant.bootstrap.conf_util.process_ha_config_upgrade',
|
'homeassistant.bootstrap.conf_util.process_ha_config_upgrade',
|
||||||
mock.Mock()
|
autospec=True)
|
||||||
)
|
|
||||||
@mock.patch('homeassistant.util.location.detect_location_info',
|
@mock.patch('homeassistant.util.location.detect_location_info',
|
||||||
return_value=None)
|
autospec=True, return_value=None)
|
||||||
def test_from_config_file(self, mock_detect):
|
def test_from_config_file(self, mock_upgrade, mock_detect):
|
||||||
"""Test with configuration file."""
|
"""Test with configuration file."""
|
||||||
components = ['browser', 'conversation', 'script']
|
components = ['browser', 'conversation', 'script']
|
||||||
files = {
|
files = {
|
||||||
@ -94,28 +93,33 @@ class TestBootstrap:
|
|||||||
loader.set_component(
|
loader.set_component(
|
||||||
'comp_conf', MockModule('comp_conf', config_schema=config_schema))
|
'comp_conf', MockModule('comp_conf', config_schema=config_schema))
|
||||||
|
|
||||||
assert not bootstrap._setup_component(self.hass, 'comp_conf', {})
|
with assert_setup_component(0):
|
||||||
|
assert not bootstrap.setup_component(self.hass, 'comp_conf', {})
|
||||||
|
|
||||||
assert not bootstrap._setup_component(self.hass, 'comp_conf', {
|
with assert_setup_component(0):
|
||||||
'comp_conf': None
|
assert not bootstrap.setup_component(self.hass, 'comp_conf', {
|
||||||
})
|
'comp_conf': None
|
||||||
|
})
|
||||||
|
|
||||||
assert not bootstrap._setup_component(self.hass, 'comp_conf', {
|
with assert_setup_component(0):
|
||||||
'comp_conf': {}
|
assert not bootstrap.setup_component(self.hass, 'comp_conf', {
|
||||||
})
|
'comp_conf': {}
|
||||||
|
})
|
||||||
|
|
||||||
assert not bootstrap._setup_component(self.hass, 'comp_conf', {
|
with assert_setup_component(0):
|
||||||
'comp_conf': {
|
assert not bootstrap.setup_component(self.hass, 'comp_conf', {
|
||||||
'hello': 'world',
|
'comp_conf': {
|
||||||
'invalid': 'extra',
|
'hello': 'world',
|
||||||
}
|
'invalid': 'extra',
|
||||||
})
|
}
|
||||||
|
})
|
||||||
|
|
||||||
assert bootstrap._setup_component(self.hass, 'comp_conf', {
|
with assert_setup_component(1):
|
||||||
'comp_conf': {
|
assert bootstrap.setup_component(self.hass, 'comp_conf', {
|
||||||
'hello': 'world',
|
'comp_conf': {
|
||||||
}
|
'hello': 'world',
|
||||||
})
|
}
|
||||||
|
})
|
||||||
|
|
||||||
def test_validate_platform_config(self):
|
def test_validate_platform_config(self):
|
||||||
"""Test validating platform configuration."""
|
"""Test validating platform configuration."""
|
||||||
@ -130,7 +134,7 @@ class TestBootstrap:
|
|||||||
'platform_conf.whatever', MockPlatform('whatever'))
|
'platform_conf.whatever', MockPlatform('whatever'))
|
||||||
|
|
||||||
with assert_setup_component(0):
|
with assert_setup_component(0):
|
||||||
assert bootstrap._setup_component(self.hass, 'platform_conf', {
|
assert bootstrap.setup_component(self.hass, 'platform_conf', {
|
||||||
'platform_conf': {
|
'platform_conf': {
|
||||||
'hello': 'world',
|
'hello': 'world',
|
||||||
'invalid': 'extra',
|
'invalid': 'extra',
|
||||||
@ -140,7 +144,7 @@ class TestBootstrap:
|
|||||||
self.hass.config.components.remove('platform_conf')
|
self.hass.config.components.remove('platform_conf')
|
||||||
|
|
||||||
with assert_setup_component(1):
|
with assert_setup_component(1):
|
||||||
assert bootstrap._setup_component(self.hass, 'platform_conf', {
|
assert bootstrap.setup_component(self.hass, 'platform_conf', {
|
||||||
'platform_conf': {
|
'platform_conf': {
|
||||||
'platform': 'whatever',
|
'platform': 'whatever',
|
||||||
'hello': 'world',
|
'hello': 'world',
|
||||||
@ -153,7 +157,7 @@ class TestBootstrap:
|
|||||||
self.hass.config.components.remove('platform_conf')
|
self.hass.config.components.remove('platform_conf')
|
||||||
|
|
||||||
with assert_setup_component(0):
|
with assert_setup_component(0):
|
||||||
assert bootstrap._setup_component(self.hass, 'platform_conf', {
|
assert bootstrap.setup_component(self.hass, 'platform_conf', {
|
||||||
'platform_conf': {
|
'platform_conf': {
|
||||||
'platform': 'not_existing',
|
'platform': 'not_existing',
|
||||||
'hello': 'world',
|
'hello': 'world',
|
||||||
@ -163,7 +167,7 @@ class TestBootstrap:
|
|||||||
self.hass.config.components.remove('platform_conf')
|
self.hass.config.components.remove('platform_conf')
|
||||||
|
|
||||||
with assert_setup_component(1):
|
with assert_setup_component(1):
|
||||||
assert bootstrap._setup_component(self.hass, 'platform_conf', {
|
assert bootstrap.setup_component(self.hass, 'platform_conf', {
|
||||||
'platform_conf': {
|
'platform_conf': {
|
||||||
'platform': 'whatever',
|
'platform': 'whatever',
|
||||||
'hello': 'world',
|
'hello': 'world',
|
||||||
@ -173,7 +177,7 @@ class TestBootstrap:
|
|||||||
self.hass.config.components.remove('platform_conf')
|
self.hass.config.components.remove('platform_conf')
|
||||||
|
|
||||||
with assert_setup_component(1):
|
with assert_setup_component(1):
|
||||||
assert bootstrap._setup_component(self.hass, 'platform_conf', {
|
assert bootstrap.setup_component(self.hass, 'platform_conf', {
|
||||||
'platform_conf': [{
|
'platform_conf': [{
|
||||||
'platform': 'whatever',
|
'platform': 'whatever',
|
||||||
'hello': 'world',
|
'hello': 'world',
|
||||||
@ -184,13 +188,13 @@ class TestBootstrap:
|
|||||||
|
|
||||||
# Any falsey platform config will be ignored (None, {}, etc)
|
# Any falsey platform config will be ignored (None, {}, etc)
|
||||||
with assert_setup_component(0) as config:
|
with assert_setup_component(0) as config:
|
||||||
assert bootstrap._setup_component(self.hass, 'platform_conf', {
|
assert bootstrap.setup_component(self.hass, 'platform_conf', {
|
||||||
'platform_conf': None
|
'platform_conf': None
|
||||||
})
|
})
|
||||||
assert 'platform_conf' in self.hass.config.components
|
assert 'platform_conf' in self.hass.config.components
|
||||||
assert not config['platform_conf'] # empty
|
assert not config['platform_conf'] # empty
|
||||||
|
|
||||||
assert bootstrap._setup_component(self.hass, 'platform_conf', {
|
assert bootstrap.setup_component(self.hass, 'platform_conf', {
|
||||||
'platform_conf': {}
|
'platform_conf': {}
|
||||||
})
|
})
|
||||||
assert 'platform_conf' in self.hass.config.components
|
assert 'platform_conf' in self.hass.config.components
|
||||||
@ -235,10 +239,9 @@ class TestBootstrap:
|
|||||||
"""Setup the component."""
|
"""Setup the component."""
|
||||||
result.append(bootstrap.setup_component(self.hass, 'comp'))
|
result.append(bootstrap.setup_component(self.hass, 'comp'))
|
||||||
|
|
||||||
with bootstrap._SETUP_LOCK:
|
thread = threading.Thread(target=setup_component)
|
||||||
thread = threading.Thread(target=setup_component)
|
thread.start()
|
||||||
thread.start()
|
self.hass.config.components.append('comp')
|
||||||
self.hass.config.components.append('comp')
|
|
||||||
|
|
||||||
thread.join()
|
thread.join()
|
||||||
|
|
||||||
@ -250,19 +253,19 @@ class TestBootstrap:
|
|||||||
deps = ['non_existing']
|
deps = ['non_existing']
|
||||||
loader.set_component('comp', MockModule('comp', dependencies=deps))
|
loader.set_component('comp', MockModule('comp', dependencies=deps))
|
||||||
|
|
||||||
assert not bootstrap._setup_component(self.hass, 'comp', {})
|
assert not bootstrap.setup_component(self.hass, 'comp', {})
|
||||||
assert 'comp' not in self.hass.config.components
|
assert 'comp' not in self.hass.config.components
|
||||||
|
|
||||||
self.hass.config.components.append('non_existing')
|
loader.set_component('non_existing', MockModule('non_existing'))
|
||||||
|
|
||||||
assert bootstrap._setup_component(self.hass, 'comp', {})
|
assert bootstrap.setup_component(self.hass, 'comp', {})
|
||||||
|
|
||||||
def test_component_failing_setup(self):
|
def test_component_failing_setup(self):
|
||||||
"""Test component that fails setup."""
|
"""Test component that fails setup."""
|
||||||
loader.set_component(
|
loader.set_component(
|
||||||
'comp', MockModule('comp', setup=lambda hass, config: False))
|
'comp', MockModule('comp', setup=lambda hass, config: False))
|
||||||
|
|
||||||
assert not bootstrap._setup_component(self.hass, 'comp', {})
|
assert not bootstrap.setup_component(self.hass, 'comp', {})
|
||||||
assert 'comp' not in self.hass.config.components
|
assert 'comp' not in self.hass.config.components
|
||||||
|
|
||||||
def test_component_exception_setup(self):
|
def test_component_exception_setup(self):
|
||||||
@ -273,18 +276,17 @@ class TestBootstrap:
|
|||||||
|
|
||||||
loader.set_component('comp', MockModule('comp', setup=exception_setup))
|
loader.set_component('comp', MockModule('comp', setup=exception_setup))
|
||||||
|
|
||||||
assert not bootstrap._setup_component(self.hass, 'comp', {})
|
assert not bootstrap.setup_component(self.hass, 'comp', {})
|
||||||
assert 'comp' not in self.hass.config.components
|
assert 'comp' not in self.hass.config.components
|
||||||
|
|
||||||
def test_home_assistant_core_config_validation(self):
|
def test_home_assistant_core_config_validation(self):
|
||||||
"""Test if we pass in wrong information for HA conf."""
|
"""Test if we pass in wrong information for HA conf."""
|
||||||
# Extensive HA conf validation testing is done in test_config.py
|
# Extensive HA conf validation testing is done in test_config.py
|
||||||
hass = get_test_home_assistant()
|
|
||||||
assert None is bootstrap.from_config_dict({
|
assert None is bootstrap.from_config_dict({
|
||||||
'homeassistant': {
|
'homeassistant': {
|
||||||
'latitude': 'some string'
|
'latitude': 'some string'
|
||||||
}
|
}
|
||||||
}, hass=hass)
|
})
|
||||||
|
|
||||||
def test_component_setup_with_validation_and_dependency(self):
|
def test_component_setup_with_validation_and_dependency(self):
|
||||||
"""Test all config is passed to dependencies."""
|
"""Test all config is passed to dependencies."""
|
||||||
@ -316,7 +318,7 @@ class TestBootstrap:
|
|||||||
'valid': True,
|
'valid': True,
|
||||||
}, extra=vol.PREVENT_EXTRA)
|
}, extra=vol.PREVENT_EXTRA)
|
||||||
|
|
||||||
mock_setup = mock.MagicMock()
|
mock_setup = mock.MagicMock(spec_set=True)
|
||||||
|
|
||||||
loader.set_component(
|
loader.set_component(
|
||||||
'switch.platform_a',
|
'switch.platform_a',
|
||||||
|
@ -14,6 +14,7 @@ from homeassistant.const import (
|
|||||||
CONF_TIME_ZONE, CONF_ELEVATION, CONF_CUSTOMIZE, __version__,
|
CONF_TIME_ZONE, CONF_ELEVATION, CONF_CUSTOMIZE, __version__,
|
||||||
CONF_UNIT_SYSTEM_METRIC, CONF_UNIT_SYSTEM_IMPERIAL, CONF_TEMPERATURE_UNIT)
|
CONF_UNIT_SYSTEM_METRIC, CONF_UNIT_SYSTEM_IMPERIAL, CONF_TEMPERATURE_UNIT)
|
||||||
from homeassistant.util import location as location_util, dt as dt_util
|
from homeassistant.util import location as location_util, dt as dt_util
|
||||||
|
from homeassistant.util.async import run_coroutine_threadsafe
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
|
|
||||||
from tests.common import (
|
from tests.common import (
|
||||||
@ -34,6 +35,10 @@ def create_file(path):
|
|||||||
class TestConfig(unittest.TestCase):
|
class TestConfig(unittest.TestCase):
|
||||||
"""Test the configutils."""
|
"""Test the configutils."""
|
||||||
|
|
||||||
|
def setUp(self): # pylint: disable=invalid-name
|
||||||
|
"""Initialize a test Home Assistant instance."""
|
||||||
|
self.hass = get_test_home_assistant()
|
||||||
|
|
||||||
def tearDown(self): # pylint: disable=invalid-name
|
def tearDown(self): # pylint: disable=invalid-name
|
||||||
"""Clean up."""
|
"""Clean up."""
|
||||||
dt_util.DEFAULT_TIME_ZONE = ORIG_TIMEZONE
|
dt_util.DEFAULT_TIME_ZONE = ORIG_TIMEZONE
|
||||||
@ -44,8 +49,7 @@ class TestConfig(unittest.TestCase):
|
|||||||
if os.path.isfile(VERSION_PATH):
|
if os.path.isfile(VERSION_PATH):
|
||||||
os.remove(VERSION_PATH)
|
os.remove(VERSION_PATH)
|
||||||
|
|
||||||
if hasattr(self, 'hass'):
|
self.hass.stop()
|
||||||
self.hass.stop()
|
|
||||||
|
|
||||||
def test_create_default_config(self):
|
def test_create_default_config(self):
|
||||||
"""Test creation of default config."""
|
"""Test creation of default config."""
|
||||||
@ -165,6 +169,7 @@ class TestConfig(unittest.TestCase):
|
|||||||
self.assertTrue(mock_print.called)
|
self.assertTrue(mock_print.called)
|
||||||
|
|
||||||
def test_core_config_schema(self):
|
def test_core_config_schema(self):
|
||||||
|
"""Test core config schema."""
|
||||||
for value in (
|
for value in (
|
||||||
{CONF_UNIT_SYSTEM: 'K'},
|
{CONF_UNIT_SYSTEM: 'K'},
|
||||||
{'time_zone': 'non-exist'},
|
{'time_zone': 'non-exist'},
|
||||||
@ -191,14 +196,14 @@ class TestConfig(unittest.TestCase):
|
|||||||
|
|
||||||
def test_entity_customization(self):
|
def test_entity_customization(self):
|
||||||
"""Test entity customization through configuration."""
|
"""Test entity customization through configuration."""
|
||||||
self.hass = get_test_home_assistant()
|
|
||||||
|
|
||||||
config = {CONF_LATITUDE: 50,
|
config = {CONF_LATITUDE: 50,
|
||||||
CONF_LONGITUDE: 50,
|
CONF_LONGITUDE: 50,
|
||||||
CONF_NAME: 'Test',
|
CONF_NAME: 'Test',
|
||||||
CONF_CUSTOMIZE: {'test.test': {'hidden': True}}}
|
CONF_CUSTOMIZE: {'test.test': {'hidden': True}}}
|
||||||
|
|
||||||
config_util.process_ha_core_config(self.hass, config)
|
run_coroutine_threadsafe(
|
||||||
|
config_util.async_process_ha_core_config(self.hass, config),
|
||||||
|
self.hass.loop).result()
|
||||||
|
|
||||||
entity = Entity()
|
entity = Entity()
|
||||||
entity.entity_id = 'test.test'
|
entity.entity_id = 'test.test'
|
||||||
@ -224,7 +229,6 @@ class TestConfig(unittest.TestCase):
|
|||||||
opened_file = mock_open.return_value
|
opened_file = mock_open.return_value
|
||||||
opened_file.readline.return_value = ha_version
|
opened_file.readline.return_value = ha_version
|
||||||
|
|
||||||
self.hass = get_test_home_assistant()
|
|
||||||
self.hass.config.path = mock.Mock()
|
self.hass.config.path = mock.Mock()
|
||||||
|
|
||||||
config_util.process_ha_config_upgrade(self.hass)
|
config_util.process_ha_config_upgrade(self.hass)
|
||||||
@ -254,7 +258,6 @@ class TestConfig(unittest.TestCase):
|
|||||||
opened_file = mock_open.return_value
|
opened_file = mock_open.return_value
|
||||||
opened_file.readline.return_value = ha_version
|
opened_file.readline.return_value = ha_version
|
||||||
|
|
||||||
self.hass = get_test_home_assistant()
|
|
||||||
self.hass.config.path = mock.Mock()
|
self.hass.config.path = mock.Mock()
|
||||||
|
|
||||||
config_util.process_ha_config_upgrade(self.hass)
|
config_util.process_ha_config_upgrade(self.hass)
|
||||||
@ -264,82 +267,91 @@ class TestConfig(unittest.TestCase):
|
|||||||
|
|
||||||
def test_loading_configuration(self):
|
def test_loading_configuration(self):
|
||||||
"""Test loading core config onto hass object."""
|
"""Test loading core config onto hass object."""
|
||||||
config = Config()
|
self.hass.config = mock.Mock()
|
||||||
hass = mock.Mock(config=config)
|
|
||||||
|
|
||||||
config_util.process_ha_core_config(hass, {
|
run_coroutine_threadsafe(
|
||||||
'latitude': 60,
|
config_util.async_process_ha_core_config(self.hass, {
|
||||||
'longitude': 50,
|
'latitude': 60,
|
||||||
'elevation': 25,
|
'longitude': 50,
|
||||||
'name': 'Huis',
|
'elevation': 25,
|
||||||
CONF_UNIT_SYSTEM: CONF_UNIT_SYSTEM_IMPERIAL,
|
'name': 'Huis',
|
||||||
'time_zone': 'America/New_York',
|
CONF_UNIT_SYSTEM: CONF_UNIT_SYSTEM_IMPERIAL,
|
||||||
})
|
'time_zone': 'America/New_York',
|
||||||
|
}), self.hass.loop).result()
|
||||||
|
|
||||||
assert config.latitude == 60
|
assert self.hass.config.latitude == 60
|
||||||
assert config.longitude == 50
|
assert self.hass.config.longitude == 50
|
||||||
assert config.elevation == 25
|
assert self.hass.config.elevation == 25
|
||||||
assert config.location_name == 'Huis'
|
assert self.hass.config.location_name == 'Huis'
|
||||||
assert config.units.name == CONF_UNIT_SYSTEM_IMPERIAL
|
assert self.hass.config.units.name == CONF_UNIT_SYSTEM_IMPERIAL
|
||||||
assert config.time_zone.zone == 'America/New_York'
|
assert self.hass.config.time_zone.zone == 'America/New_York'
|
||||||
|
|
||||||
def test_loading_configuration_temperature_unit(self):
|
def test_loading_configuration_temperature_unit(self):
|
||||||
"""Test backward compatibility when loading core config."""
|
"""Test backward compatibility when loading core config."""
|
||||||
config = Config()
|
self.hass.config = mock.Mock()
|
||||||
hass = mock.Mock(config=config)
|
|
||||||
|
|
||||||
config_util.process_ha_core_config(hass, {
|
run_coroutine_threadsafe(
|
||||||
'latitude': 60,
|
config_util.async_process_ha_core_config(self.hass, {
|
||||||
'longitude': 50,
|
'latitude': 60,
|
||||||
'elevation': 25,
|
'longitude': 50,
|
||||||
'name': 'Huis',
|
'elevation': 25,
|
||||||
CONF_TEMPERATURE_UNIT: 'C',
|
'name': 'Huis',
|
||||||
'time_zone': 'America/New_York',
|
CONF_TEMPERATURE_UNIT: 'C',
|
||||||
})
|
'time_zone': 'America/New_York',
|
||||||
|
}), self.hass.loop).result()
|
||||||
|
|
||||||
assert config.latitude == 60
|
assert self.hass.config.latitude == 60
|
||||||
assert config.longitude == 50
|
assert self.hass.config.longitude == 50
|
||||||
assert config.elevation == 25
|
assert self.hass.config.elevation == 25
|
||||||
assert config.location_name == 'Huis'
|
assert self.hass.config.location_name == 'Huis'
|
||||||
assert config.units.name == CONF_UNIT_SYSTEM_METRIC
|
assert self.hass.config.units.name == CONF_UNIT_SYSTEM_METRIC
|
||||||
assert config.time_zone.zone == 'America/New_York'
|
assert self.hass.config.time_zone.zone == 'America/New_York'
|
||||||
|
|
||||||
@mock.patch('homeassistant.util.location.detect_location_info',
|
@mock.patch('homeassistant.util.location.detect_location_info',
|
||||||
return_value=location_util.LocationInfo(
|
autospec=True, return_value=location_util.LocationInfo(
|
||||||
'0.0.0.0', 'US', 'United States', 'CA', 'California',
|
'0.0.0.0', 'US', 'United States', 'CA', 'California',
|
||||||
'San Diego', '92122', 'America/Los_Angeles', 32.8594,
|
'San Diego', '92122', 'America/Los_Angeles', 32.8594,
|
||||||
-117.2073, True))
|
-117.2073, True))
|
||||||
@mock.patch('homeassistant.util.location.elevation', return_value=101)
|
@mock.patch('homeassistant.util.location.elevation',
|
||||||
|
autospec=True, return_value=101)
|
||||||
def test_discovering_configuration(self, mock_detect, mock_elevation):
|
def test_discovering_configuration(self, mock_detect, mock_elevation):
|
||||||
"""Test auto discovery for missing core configs."""
|
"""Test auto discovery for missing core configs."""
|
||||||
config = Config()
|
self.hass.config.latitude = None
|
||||||
hass = mock.Mock(config=config)
|
self.hass.config.longitude = None
|
||||||
|
self.hass.config.elevation = None
|
||||||
|
self.hass.config.location_name = None
|
||||||
|
self.hass.config.time_zone = None
|
||||||
|
|
||||||
config_util.process_ha_core_config(hass, {})
|
run_coroutine_threadsafe(
|
||||||
|
config_util.async_process_ha_core_config(
|
||||||
|
self.hass, {}), self.hass.loop
|
||||||
|
).result()
|
||||||
|
|
||||||
assert config.latitude == 32.8594
|
assert self.hass.config.latitude == 32.8594
|
||||||
assert config.longitude == -117.2073
|
assert self.hass.config.longitude == -117.2073
|
||||||
assert config.elevation == 101
|
assert self.hass.config.elevation == 101
|
||||||
assert config.location_name == 'San Diego'
|
assert self.hass.config.location_name == 'San Diego'
|
||||||
assert config.units.name == CONF_UNIT_SYSTEM_METRIC
|
assert self.hass.config.units.name == CONF_UNIT_SYSTEM_METRIC
|
||||||
assert config.units.is_metric
|
assert self.hass.config.units.is_metric
|
||||||
assert config.time_zone.zone == 'America/Los_Angeles'
|
assert self.hass.config.time_zone.zone == 'America/Los_Angeles'
|
||||||
|
|
||||||
@mock.patch('homeassistant.util.location.detect_location_info',
|
@mock.patch('homeassistant.util.location.detect_location_info',
|
||||||
return_value=None)
|
autospec=True, return_value=None)
|
||||||
@mock.patch('homeassistant.util.location.elevation', return_value=0)
|
@mock.patch('homeassistant.util.location.elevation', return_value=0)
|
||||||
def test_discovering_configuration_auto_detect_fails(self, mock_detect,
|
def test_discovering_configuration_auto_detect_fails(self, mock_detect,
|
||||||
mock_elevation):
|
mock_elevation):
|
||||||
"""Test config remains unchanged if discovery fails."""
|
"""Test config remains unchanged if discovery fails."""
|
||||||
config = Config()
|
self.hass.config = Config()
|
||||||
hass = mock.Mock(config=config)
|
|
||||||
|
|
||||||
config_util.process_ha_core_config(hass, {})
|
run_coroutine_threadsafe(
|
||||||
|
config_util.async_process_ha_core_config(
|
||||||
|
self.hass, {}), self.hass.loop
|
||||||
|
).result()
|
||||||
|
|
||||||
blankConfig = Config()
|
blankConfig = Config()
|
||||||
assert config.latitude == blankConfig.latitude
|
assert self.hass.config.latitude == blankConfig.latitude
|
||||||
assert config.longitude == blankConfig.longitude
|
assert self.hass.config.longitude == blankConfig.longitude
|
||||||
assert config.elevation == blankConfig.elevation
|
assert self.hass.config.elevation == blankConfig.elevation
|
||||||
assert config.location_name == blankConfig.location_name
|
assert self.hass.config.location_name == blankConfig.location_name
|
||||||
assert config.units == blankConfig.units
|
assert self.hass.config.units == blankConfig.units
|
||||||
assert config.time_zone == blankConfig.time_zone
|
assert self.hass.config.time_zone == blankConfig.time_zone
|
||||||
|
Loading…
x
Reference in New Issue
Block a user