Migrate tests to pytest (#23544)

* Migrate tests to pytest

* Fixup

* Use loop fixture in test_check_config

* Lint
pull/23584/head
Erik Montnemery 2019-04-30 18:20:38 +02:00 committed by Paulus Schoutsen
parent d71424f285
commit 407e0c58f9
25 changed files with 4744 additions and 4910 deletions

View File

@ -1,25 +1,24 @@
"""The tests for the Entity component helper."""
# pylint: disable=protected-access
import asyncio
from collections import OrderedDict
import logging
import unittest
from unittest.mock import patch, Mock
from datetime import timedelta
import asynctest
import pytest
import homeassistant.core as ha
from homeassistant.exceptions import PlatformNotReady
from homeassistant.components import group
from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.setup import setup_component, async_setup_component
from homeassistant.setup import async_setup_component
from homeassistant.helpers import discovery
import homeassistant.util.dt as dt_util
from tests.common import (
get_test_home_assistant, MockPlatform, MockModule, mock_coro,
MockPlatform, MockModule, mock_coro,
async_fire_time_changed, MockEntity, MockConfigEntry,
mock_entity_platform, mock_integration)
@ -27,178 +26,169 @@ _LOGGER = logging.getLogger(__name__)
DOMAIN = "test_domain"
class TestHelpersEntityComponent(unittest.TestCase):
"""Test homeassistant.helpers.entity_component module."""
async def test_setting_up_group(hass):
"""Set up the setting of a group."""
assert await async_setup_component(hass, 'group', {'group': {}})
component = EntityComponent(_LOGGER, DOMAIN, hass,
group_name='everyone')
def setUp(self): # pylint: disable=invalid-name
"""Initialize a test Home Assistant instance."""
self.hass = get_test_home_assistant()
# No group after setup
assert len(hass.states.async_entity_ids()) == 0
def tearDown(self): # pylint: disable=invalid-name
"""Clean up the test Home Assistant instance."""
self.hass.stop()
await component.async_add_entities([MockEntity()])
await hass.async_block_till_done()
def test_setting_up_group(self):
"""Set up the setting of a group."""
setup_component(self.hass, 'group', {'group': {}})
component = EntityComponent(_LOGGER, DOMAIN, self.hass,
group_name='everyone')
# group exists
assert len(hass.states.async_entity_ids()) == 2
assert hass.states.async_entity_ids('group') == ['group.everyone']
# No group after setup
assert len(self.hass.states.entity_ids()) == 0
grp = hass.states.get('group.everyone')
component.add_entities([MockEntity()])
self.hass.block_till_done()
assert grp.attributes.get('entity_id') == \
('test_domain.unnamed_device',)
# group exists
assert len(self.hass.states.entity_ids()) == 2
assert self.hass.states.entity_ids('group') == ['group.everyone']
# group extended
await component.async_add_entities([MockEntity(name='goodbye')])
await hass.async_block_till_done()
group = self.hass.states.get('group.everyone')
assert len(hass.states.async_entity_ids()) == 3
grp = hass.states.get('group.everyone')
assert group.attributes.get('entity_id') == \
('test_domain.unnamed_device',)
# group extended
component.add_entities([MockEntity(name='goodbye')])
self.hass.block_till_done()
assert len(self.hass.states.entity_ids()) == 3
group = self.hass.states.get('group.everyone')
# Ordered in order of added to the group
assert group.attributes.get('entity_id') == \
('test_domain.goodbye', 'test_domain.unnamed_device')
def test_setup_loads_platforms(self):
"""Test the loading of the platforms."""
component_setup = Mock(return_value=True)
platform_setup = Mock(return_value=None)
mock_integration(self.hass,
MockModule('test_component', setup=component_setup))
# mock the dependencies
mock_integration(self.hass,
MockModule('mod2', dependencies=['test_component']))
mock_entity_platform(self.hass, 'test_domain.mod2',
MockPlatform(platform_setup))
component = EntityComponent(_LOGGER, DOMAIN, self.hass)
assert not component_setup.called
assert not platform_setup.called
component.setup({
DOMAIN: {
'platform': 'mod2',
}
})
self.hass.block_till_done()
assert component_setup.called
assert platform_setup.called
def test_setup_recovers_when_setup_raises(self):
"""Test the setup if exceptions are happening."""
platform1_setup = Mock(side_effect=Exception('Broken'))
platform2_setup = Mock(return_value=None)
mock_entity_platform(self.hass, 'test_domain.mod1',
MockPlatform(platform1_setup))
mock_entity_platform(self.hass, 'test_domain.mod2',
MockPlatform(platform2_setup))
component = EntityComponent(_LOGGER, DOMAIN, self.hass)
assert not platform1_setup.called
assert not platform2_setup.called
component.setup(OrderedDict([
(DOMAIN, {'platform': 'mod1'}),
("{} 2".format(DOMAIN), {'platform': 'non_exist'}),
("{} 3".format(DOMAIN), {'platform': 'mod2'}),
]))
self.hass.block_till_done()
assert platform1_setup.called
assert platform2_setup.called
@patch('homeassistant.helpers.entity_component.EntityComponent'
'._async_setup_platform', return_value=mock_coro())
@patch('homeassistant.setup.async_setup_component',
return_value=mock_coro(True))
def test_setup_does_discovery(self, mock_setup_component, mock_setup):
"""Test setup for discovery."""
component = EntityComponent(_LOGGER, DOMAIN, self.hass)
component.setup({})
discovery.load_platform(self.hass, DOMAIN, 'platform_test',
{'msg': 'discovery_info'}, {DOMAIN: {}})
self.hass.block_till_done()
assert mock_setup.called
assert ('platform_test', {}, {'msg': 'discovery_info'}) == \
mock_setup.call_args[0]
@patch('homeassistant.helpers.entity_platform.'
'async_track_time_interval')
def test_set_scan_interval_via_config(self, mock_track):
"""Test the setting of the scan interval via configuration."""
def platform_setup(hass, config, add_entities, discovery_info=None):
"""Test the platform setup."""
add_entities([MockEntity(should_poll=True)])
mock_entity_platform(self.hass, 'test_domain.platform',
MockPlatform(platform_setup))
component = EntityComponent(_LOGGER, DOMAIN, self.hass)
component.setup({
DOMAIN: {
'platform': 'platform',
'scan_interval': timedelta(seconds=30),
}
})
self.hass.block_till_done()
assert mock_track.called
assert timedelta(seconds=30) == mock_track.call_args[0][2]
def test_set_entity_namespace_via_config(self):
"""Test setting an entity namespace."""
def platform_setup(hass, config, add_entities, discovery_info=None):
"""Test the platform setup."""
add_entities([
MockEntity(name='beer'),
MockEntity(name=None),
])
platform = MockPlatform(platform_setup)
mock_entity_platform(self.hass, 'test_domain.platform', platform)
component = EntityComponent(_LOGGER, DOMAIN, self.hass)
component.setup({
DOMAIN: {
'platform': 'platform',
'entity_namespace': 'yummy'
}
})
self.hass.block_till_done()
assert sorted(self.hass.states.entity_ids()) == \
['test_domain.yummy_beer', 'test_domain.yummy_unnamed_device']
# Ordered in order of added to the group
assert grp.attributes.get('entity_id') == \
('test_domain.goodbye', 'test_domain.unnamed_device')
@asyncio.coroutine
def test_extract_from_service_available_device(hass):
async def test_setup_loads_platforms(hass):
"""Test the loading of the platforms."""
component_setup = Mock(return_value=True)
platform_setup = Mock(return_value=None)
mock_integration(hass, MockModule('test_component', setup=component_setup))
# mock the dependencies
mock_integration(hass, MockModule('mod2', dependencies=['test_component']))
mock_entity_platform(hass, 'test_domain.mod2',
MockPlatform(platform_setup))
component = EntityComponent(_LOGGER, DOMAIN, hass)
assert not component_setup.called
assert not platform_setup.called
component.setup({
DOMAIN: {
'platform': 'mod2',
}
})
await hass.async_block_till_done()
assert component_setup.called
assert platform_setup.called
async def test_setup_recovers_when_setup_raises(hass):
"""Test the setup if exceptions are happening."""
platform1_setup = Mock(side_effect=Exception('Broken'))
platform2_setup = Mock(return_value=None)
mock_entity_platform(hass, 'test_domain.mod1',
MockPlatform(platform1_setup))
mock_entity_platform(hass, 'test_domain.mod2',
MockPlatform(platform2_setup))
component = EntityComponent(_LOGGER, DOMAIN, hass)
assert not platform1_setup.called
assert not platform2_setup.called
component.setup(OrderedDict([
(DOMAIN, {'platform': 'mod1'}),
("{} 2".format(DOMAIN), {'platform': 'non_exist'}),
("{} 3".format(DOMAIN), {'platform': 'mod2'}),
]))
await hass.async_block_till_done()
assert platform1_setup.called
assert platform2_setup.called
@asynctest.patch('homeassistant.helpers.entity_component.EntityComponent'
'._async_setup_platform', return_value=mock_coro())
@asynctest.patch('homeassistant.setup.async_setup_component',
return_value=mock_coro(True))
async def test_setup_does_discovery(mock_setup_component, mock_setup, hass):
"""Test setup for discovery."""
component = EntityComponent(_LOGGER, DOMAIN, hass)
component.setup({})
discovery.load_platform(hass, DOMAIN, 'platform_test',
{'msg': 'discovery_info'}, {DOMAIN: {}})
await hass.async_block_till_done()
assert mock_setup.called
assert ('platform_test', {}, {'msg': 'discovery_info'}) == \
mock_setup.call_args[0]
@asynctest.patch('homeassistant.helpers.entity_platform.'
'async_track_time_interval')
async def test_set_scan_interval_via_config(mock_track, hass):
"""Test the setting of the scan interval via configuration."""
def platform_setup(hass, config, add_entities, discovery_info=None):
"""Test the platform setup."""
add_entities([MockEntity(should_poll=True)])
mock_entity_platform(hass, 'test_domain.platform',
MockPlatform(platform_setup))
component = EntityComponent(_LOGGER, DOMAIN, hass)
component.setup({
DOMAIN: {
'platform': 'platform',
'scan_interval': timedelta(seconds=30),
}
})
await hass.async_block_till_done()
assert mock_track.called
assert timedelta(seconds=30) == mock_track.call_args[0][2]
async def test_set_entity_namespace_via_config(hass):
"""Test setting an entity namespace."""
def platform_setup(hass, config, add_entities, discovery_info=None):
"""Test the platform setup."""
add_entities([
MockEntity(name='beer'),
MockEntity(name=None),
])
platform = MockPlatform(platform_setup)
mock_entity_platform(hass, 'test_domain.platform', platform)
component = EntityComponent(_LOGGER, DOMAIN, hass)
component.setup({
DOMAIN: {
'platform': 'platform',
'entity_namespace': 'yummy'
}
})
await hass.async_block_till_done()
assert sorted(hass.states.async_entity_ids()) == \
['test_domain.yummy_beer', 'test_domain.yummy_unnamed_device']
async def test_extract_from_service_available_device(hass):
"""Test the extraction of entity from service and device is available."""
component = EntityComponent(_LOGGER, DOMAIN, hass)
yield from component.async_add_entities([
await component.async_add_entities([
MockEntity(name='test_1'),
MockEntity(name='test_2', available=False),
MockEntity(name='test_3'),
@ -209,7 +199,7 @@ def test_extract_from_service_available_device(hass):
assert ['test_domain.test_1', 'test_domain.test_3'] == \
sorted(ent.entity_id for ent in
(yield from component.async_extract_from_service(call_1)))
(await component.async_extract_from_service(call_1)))
call_2 = ha.ServiceCall('test', 'service', data={
'entity_id': ['test_domain.test_3', 'test_domain.test_4'],
@ -217,11 +207,10 @@ def test_extract_from_service_available_device(hass):
assert ['test_domain.test_3'] == \
sorted(ent.entity_id for ent in
(yield from component.async_extract_from_service(call_2)))
(await component.async_extract_from_service(call_2)))
@asyncio.coroutine
def test_platform_not_ready(hass):
async def test_platform_not_ready(hass):
"""Test that we retry when platform not ready."""
platform1_setup = Mock(side_effect=[PlatformNotReady, PlatformNotReady,
None])
@ -231,7 +220,7 @@ def test_platform_not_ready(hass):
component = EntityComponent(_LOGGER, DOMAIN, hass)
yield from component.async_setup({
await component.async_setup({
DOMAIN: {
'platform': 'mod1'
}
@ -245,32 +234,31 @@ def test_platform_not_ready(hass):
with patch('homeassistant.util.dt.utcnow', return_value=utcnow):
# Should not trigger attempt 2
async_fire_time_changed(hass, utcnow + timedelta(seconds=29))
yield from hass.async_block_till_done()
await hass.async_block_till_done()
assert len(platform1_setup.mock_calls) == 1
# Should trigger attempt 2
async_fire_time_changed(hass, utcnow + timedelta(seconds=30))
yield from hass.async_block_till_done()
await hass.async_block_till_done()
assert len(platform1_setup.mock_calls) == 2
assert 'test_domain.mod1' not in hass.config.components
# This should not trigger attempt 3
async_fire_time_changed(hass, utcnow + timedelta(seconds=59))
yield from hass.async_block_till_done()
await hass.async_block_till_done()
assert len(platform1_setup.mock_calls) == 2
# Trigger attempt 3, which succeeds
async_fire_time_changed(hass, utcnow + timedelta(seconds=60))
yield from hass.async_block_till_done()
await hass.async_block_till_done()
assert len(platform1_setup.mock_calls) == 3
assert 'test_domain.mod1' in hass.config.components
@asyncio.coroutine
def test_extract_from_service_returns_all_if_no_entity_id(hass):
async def test_extract_from_service_returns_all_if_no_entity_id(hass):
"""Test the extraction of everything from service."""
component = EntityComponent(_LOGGER, DOMAIN, hass)
yield from component.async_add_entities([
await component.async_add_entities([
MockEntity(name='test_1'),
MockEntity(name='test_2'),
])
@ -279,14 +267,13 @@ def test_extract_from_service_returns_all_if_no_entity_id(hass):
assert ['test_domain.test_1', 'test_domain.test_2'] == \
sorted(ent.entity_id for ent in
(yield from component.async_extract_from_service(call)))
(await component.async_extract_from_service(call)))
@asyncio.coroutine
def test_extract_from_service_filter_out_non_existing_entities(hass):
async def test_extract_from_service_filter_out_non_existing_entities(hass):
"""Test the extraction of non existing entities from service."""
component = EntityComponent(_LOGGER, DOMAIN, hass)
yield from component.async_add_entities([
await component.async_add_entities([
MockEntity(name='test_1'),
MockEntity(name='test_2'),
])
@ -297,28 +284,26 @@ def test_extract_from_service_filter_out_non_existing_entities(hass):
assert ['test_domain.test_2'] == \
[ent.entity_id for ent
in (yield from component.async_extract_from_service(call))]
in await component.async_extract_from_service(call)]
@asyncio.coroutine
def test_extract_from_service_no_group_expand(hass):
async def test_extract_from_service_no_group_expand(hass):
"""Test not expanding a group."""
component = EntityComponent(_LOGGER, DOMAIN, hass)
test_group = yield from group.Group.async_create_group(
test_group = await group.Group.async_create_group(
hass, 'test_group', ['light.Ceiling', 'light.Kitchen'])
yield from component.async_add_entities([test_group])
await component.async_add_entities([test_group])
call = ha.ServiceCall('test', 'service', {
'entity_id': ['group.test_group']
})
extracted = yield from component.async_extract_from_service(
extracted = await component.async_extract_from_service(
call, expand_group=False)
assert extracted == [test_group]
@asyncio.coroutine
def test_setup_dependencies_platform(hass):
async def test_setup_dependencies_platform(hass):
"""Test we setup the dependencies of a platform.
We're explictely testing that we process dependencies even if a component
@ -331,7 +316,7 @@ def test_setup_dependencies_platform(hass):
component = EntityComponent(_LOGGER, DOMAIN, hass)
yield from component.async_setup({
await component.async_setup({
DOMAIN: {
'platform': 'test_component',
}
@ -355,7 +340,7 @@ async def test_setup_entry(hass):
assert await component.async_setup_entry(entry)
assert len(mock_setup_entry.mock_calls) == 1
p_hass, p_entry, p_add_entities = mock_setup_entry.mock_calls[0][1]
p_hass, p_entry, _ = mock_setup_entry.mock_calls[0][1]
assert p_hass is hass
assert p_entry is entry
@ -448,7 +433,7 @@ async def test_set_service_race(hass):
await async_setup_component(hass, 'group', {})
component = EntityComponent(_LOGGER, DOMAIN, hass, group_name='yo')
for i in range(2):
for _ in range(2):
hass.async_create_task(component.async_add_entities([MockEntity()]))
await hass.async_block_till_done()

View File

@ -1,14 +1,14 @@
"""Tests for the EntityPlatform helper."""
import asyncio
import logging
import unittest
from unittest.mock import patch, Mock, MagicMock
from datetime import timedelta
import asynctest
import pytest
from homeassistant.exceptions import PlatformNotReady
from homeassistant.helpers.entity import generate_entity_id
from homeassistant.helpers.entity import async_generate_entity_id
from homeassistant.helpers.entity_component import (
EntityComponent, DEFAULT_SCAN_INTERVAL)
from homeassistant.helpers import entity_platform, entity_registry
@ -16,7 +16,7 @@ from homeassistant.helpers import entity_platform, entity_registry
import homeassistant.util.dt as dt_util
from tests.common import (
get_test_home_assistant, MockPlatform, fire_time_changed, mock_registry,
MockPlatform, async_fire_time_changed, mock_registry,
MockEntity, MockEntityPlatform, MockConfigEntry, mock_entity_platform)
_LOGGER = logging.getLogger(__name__)
@ -24,164 +24,158 @@ DOMAIN = "test_domain"
PLATFORM = 'test_platform'
class TestHelpersEntityPlatform(unittest.TestCase):
"""Test homeassistant.helpers.entity_component module."""
async def test_polling_only_updates_entities_it_should_poll(hass):
"""Test the polling of only updated entities."""
component = EntityComponent(
_LOGGER, DOMAIN, hass, timedelta(seconds=20))
def setUp(self): # pylint: disable=invalid-name
"""Initialize a test Home Assistant instance."""
self.hass = get_test_home_assistant()
no_poll_ent = MockEntity(should_poll=False)
no_poll_ent.async_update = Mock()
poll_ent = MockEntity(should_poll=True)
poll_ent.async_update = Mock()
def tearDown(self): # pylint: disable=invalid-name
"""Clean up the test Home Assistant instance."""
self.hass.stop()
await component.async_add_entities([no_poll_ent, poll_ent])
def test_polling_only_updates_entities_it_should_poll(self):
"""Test the polling of only updated entities."""
component = EntityComponent(
_LOGGER, DOMAIN, self.hass, timedelta(seconds=20))
no_poll_ent.async_update.reset_mock()
poll_ent.async_update.reset_mock()
no_poll_ent = MockEntity(should_poll=False)
no_poll_ent.async_update = Mock()
poll_ent = MockEntity(should_poll=True)
poll_ent.async_update = Mock()
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=20))
await hass.async_block_till_done()
component.add_entities([no_poll_ent, poll_ent])
no_poll_ent.async_update.reset_mock()
poll_ent.async_update.reset_mock()
fire_time_changed(self.hass, dt_util.utcnow() + timedelta(seconds=20))
self.hass.block_till_done()
assert not no_poll_ent.async_update.called
assert poll_ent.async_update.called
def test_polling_updates_entities_with_exception(self):
"""Test the updated entities that not break with an exception."""
component = EntityComponent(
_LOGGER, DOMAIN, self.hass, timedelta(seconds=20))
update_ok = []
update_err = []
def update_mock():
"""Mock normal update."""
update_ok.append(None)
def update_mock_err():
"""Mock error update."""
update_err.append(None)
raise AssertionError("Fake error update")
ent1 = MockEntity(should_poll=True)
ent1.update = update_mock_err
ent2 = MockEntity(should_poll=True)
ent2.update = update_mock
ent3 = MockEntity(should_poll=True)
ent3.update = update_mock
ent4 = MockEntity(should_poll=True)
ent4.update = update_mock
component.add_entities([ent1, ent2, ent3, ent4])
update_ok.clear()
update_err.clear()
fire_time_changed(self.hass, dt_util.utcnow() + timedelta(seconds=20))
self.hass.block_till_done()
assert len(update_ok) == 3
assert len(update_err) == 1
def test_update_state_adds_entities(self):
"""Test if updating poll entities cause an entity to be added works."""
component = EntityComponent(_LOGGER, DOMAIN, self.hass)
ent1 = MockEntity()
ent2 = MockEntity(should_poll=True)
component.add_entities([ent2])
assert 1 == len(self.hass.states.entity_ids())
ent2.update = lambda *_: component.add_entities([ent1])
fire_time_changed(
self.hass, dt_util.utcnow() + DEFAULT_SCAN_INTERVAL
)
self.hass.block_till_done()
assert 2 == len(self.hass.states.entity_ids())
def test_update_state_adds_entities_with_update_before_add_true(self):
"""Test if call update before add to state machine."""
component = EntityComponent(_LOGGER, DOMAIN, self.hass)
ent = MockEntity()
ent.update = Mock(spec_set=True)
component.add_entities([ent], True)
self.hass.block_till_done()
assert 1 == len(self.hass.states.entity_ids())
assert ent.update.called
def test_update_state_adds_entities_with_update_before_add_false(self):
"""Test if not call update before add to state machine."""
component = EntityComponent(_LOGGER, DOMAIN, self.hass)
ent = MockEntity()
ent.update = Mock(spec_set=True)
component.add_entities([ent], False)
self.hass.block_till_done()
assert 1 == len(self.hass.states.entity_ids())
assert not ent.update.called
@patch('homeassistant.helpers.entity_platform.'
'async_track_time_interval')
def test_set_scan_interval_via_platform(self, mock_track):
"""Test the setting of the scan interval via platform."""
def platform_setup(hass, config, add_entities, discovery_info=None):
"""Test the platform setup."""
add_entities([MockEntity(should_poll=True)])
platform = MockPlatform(platform_setup)
platform.SCAN_INTERVAL = timedelta(seconds=30)
mock_entity_platform(self.hass, 'test_domain.platform', platform)
component = EntityComponent(_LOGGER, DOMAIN, self.hass)
component.setup({
DOMAIN: {
'platform': 'platform',
}
})
self.hass.block_till_done()
assert mock_track.called
assert timedelta(seconds=30) == mock_track.call_args[0][2]
def test_adding_entities_with_generator_and_thread_callback(self):
"""Test generator in add_entities that calls thread method.
We should make sure we resolve the generator to a list before passing
it into an async context.
"""
component = EntityComponent(_LOGGER, DOMAIN, self.hass)
def create_entity(number):
"""Create entity helper."""
entity = MockEntity()
entity.entity_id = generate_entity_id(DOMAIN + '.{}',
'Number', hass=self.hass)
return entity
component.add_entities(create_entity(i) for i in range(2))
assert not no_poll_ent.async_update.called
assert poll_ent.async_update.called
@asyncio.coroutine
def test_platform_warn_slow_setup(hass):
async def test_polling_updates_entities_with_exception(hass):
"""Test the updated entities that not break with an exception."""
component = EntityComponent(
_LOGGER, DOMAIN, hass, timedelta(seconds=20))
update_ok = []
update_err = []
def update_mock():
"""Mock normal update."""
update_ok.append(None)
def update_mock_err():
"""Mock error update."""
update_err.append(None)
raise AssertionError("Fake error update")
ent1 = MockEntity(should_poll=True)
ent1.update = update_mock_err
ent2 = MockEntity(should_poll=True)
ent2.update = update_mock
ent3 = MockEntity(should_poll=True)
ent3.update = update_mock
ent4 = MockEntity(should_poll=True)
ent4.update = update_mock
await component.async_add_entities([ent1, ent2, ent3, ent4])
update_ok.clear()
update_err.clear()
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=20))
await hass.async_block_till_done()
assert len(update_ok) == 3
assert len(update_err) == 1
async def test_update_state_adds_entities(hass):
"""Test if updating poll entities cause an entity to be added works."""
component = EntityComponent(_LOGGER, DOMAIN, hass)
ent1 = MockEntity()
ent2 = MockEntity(should_poll=True)
await component.async_add_entities([ent2])
assert len(hass.states.async_entity_ids()) == 1
ent2.update = lambda *_: component.add_entities([ent1])
async_fire_time_changed(
hass, dt_util.utcnow() + DEFAULT_SCAN_INTERVAL
)
await hass.async_block_till_done()
assert len(hass.states.async_entity_ids()) == 2
async def test_update_state_adds_entities_with_update_before_add_true(hass):
"""Test if call update before add to state machine."""
component = EntityComponent(_LOGGER, DOMAIN, hass)
ent = MockEntity()
ent.update = Mock(spec_set=True)
await component.async_add_entities([ent], True)
await hass.async_block_till_done()
assert len(hass.states.async_entity_ids()) == 1
assert ent.update.called
async def test_update_state_adds_entities_with_update_before_add_false(hass):
"""Test if not call update before add to state machine."""
component = EntityComponent(_LOGGER, DOMAIN, hass)
ent = MockEntity()
ent.update = Mock(spec_set=True)
await component.async_add_entities([ent], False)
await hass.async_block_till_done()
assert len(hass.states.async_entity_ids()) == 1
assert not ent.update.called
@asynctest.patch('homeassistant.helpers.entity_platform.'
'async_track_time_interval')
async def test_set_scan_interval_via_platform(mock_track, hass):
"""Test the setting of the scan interval via platform."""
def platform_setup(hass, config, add_entities, discovery_info=None):
"""Test the platform setup."""
add_entities([MockEntity(should_poll=True)])
platform = MockPlatform(platform_setup)
platform.SCAN_INTERVAL = timedelta(seconds=30)
mock_entity_platform(hass, 'test_domain.platform', platform)
component = EntityComponent(_LOGGER, DOMAIN, hass)
component.setup({
DOMAIN: {
'platform': 'platform',
}
})
await hass.async_block_till_done()
assert mock_track.called
assert timedelta(seconds=30) == mock_track.call_args[0][2]
async def test_adding_entities_with_generator_and_thread_callback(hass):
"""Test generator in add_entities that calls thread method.
We should make sure we resolve the generator to a list before passing
it into an async context.
"""
component = EntityComponent(_LOGGER, DOMAIN, hass)
def create_entity(number):
"""Create entity helper."""
entity = MockEntity()
entity.entity_id = async_generate_entity_id(DOMAIN + '.{}',
'Number', hass=hass)
return entity
await component.async_add_entities(create_entity(i) for i in range(2))
async def test_platform_warn_slow_setup(hass):
"""Warn we log when platform setup takes a long time."""
platform = MockPlatform()
@ -191,7 +185,7 @@ def test_platform_warn_slow_setup(hass):
with patch.object(hass.loop, 'call_later', MagicMock()) \
as mock_call:
yield from component.async_setup({
await component.async_setup({
DOMAIN: {
'platform': 'platform',
}
@ -208,21 +202,19 @@ def test_platform_warn_slow_setup(hass):
assert mock_call().cancel.called
@asyncio.coroutine
def test_platform_error_slow_setup(hass, caplog):
async def test_platform_error_slow_setup(hass, caplog):
"""Don't block startup more than SLOW_SETUP_MAX_WAIT."""
with patch.object(entity_platform, 'SLOW_SETUP_MAX_WAIT', 0):
called = []
@asyncio.coroutine
def setup_platform(*args):
async def setup_platform(*args):
called.append(1)
yield from asyncio.sleep(1, loop=hass.loop)
await asyncio.sleep(1, loop=hass.loop)
platform = MockPlatform(async_setup_platform=setup_platform)
component = EntityComponent(_LOGGER, DOMAIN, hass)
mock_entity_platform(hass, 'test_domain.test_platform', platform)
yield from component.async_setup({
await component.async_setup({
DOMAIN: {
'platform': 'test_platform',
}
@ -232,23 +224,21 @@ def test_platform_error_slow_setup(hass, caplog):
assert 'test_platform is taking longer than 0 seconds' in caplog.text
@asyncio.coroutine
def test_updated_state_used_for_entity_id(hass):
async def test_updated_state_used_for_entity_id(hass):
"""Test that first update results used for entity ID generation."""
component = EntityComponent(_LOGGER, DOMAIN, hass)
class MockEntityNameFetcher(MockEntity):
"""Mock entity that fetches a friendly name."""
@asyncio.coroutine
def async_update(self):
async def async_update(self):
"""Mock update that assigns a name."""
self._values['name'] = "Living Room"
yield from component.async_add_entities([MockEntityNameFetcher()], True)
await component.async_add_entities([MockEntityNameFetcher()], True)
entity_ids = hass.states.async_entity_ids()
assert 1 == len(entity_ids)
assert len(entity_ids) == 1
assert entity_ids[0] == "test_domain.living_room"
@ -374,8 +364,7 @@ async def test_parallel_updates_sync_platform_with_constant(hass):
assert entity.parallel_updates._value == 2
@asyncio.coroutine
def test_raise_error_on_update(hass):
async def test_raise_error_on_update(hass):
"""Test the add entity if they raise an error on update."""
updates = []
component = EntityComponent(_LOGGER, DOMAIN, hass)
@ -389,63 +378,58 @@ def test_raise_error_on_update(hass):
entity1.update = _raise
entity2.update = lambda: updates.append(1)
yield from component.async_add_entities([entity1, entity2], True)
await component.async_add_entities([entity1, entity2], True)
assert len(updates) == 1
assert 1 in updates
@asyncio.coroutine
def test_async_remove_with_platform(hass):
async def test_async_remove_with_platform(hass):
"""Remove an entity from a platform."""
component = EntityComponent(_LOGGER, DOMAIN, hass)
entity1 = MockEntity(name='test_1')
yield from component.async_add_entities([entity1])
await component.async_add_entities([entity1])
assert len(hass.states.async_entity_ids()) == 1
yield from entity1.async_remove()
await entity1.async_remove()
assert len(hass.states.async_entity_ids()) == 0
@asyncio.coroutine
def test_not_adding_duplicate_entities_with_unique_id(hass):
async def test_not_adding_duplicate_entities_with_unique_id(hass):
"""Test for not adding duplicate entities."""
component = EntityComponent(_LOGGER, DOMAIN, hass)
yield from component.async_add_entities([
await component.async_add_entities([
MockEntity(name='test1', unique_id='not_very_unique')])
assert len(hass.states.async_entity_ids()) == 1
yield from component.async_add_entities([
await component.async_add_entities([
MockEntity(name='test2', unique_id='not_very_unique')])
assert len(hass.states.async_entity_ids()) == 1
@asyncio.coroutine
def test_using_prescribed_entity_id(hass):
async def test_using_prescribed_entity_id(hass):
"""Test for using predefined entity ID."""
component = EntityComponent(_LOGGER, DOMAIN, hass)
yield from component.async_add_entities([
await component.async_add_entities([
MockEntity(name='bla', entity_id='hello.world')])
assert 'hello.world' in hass.states.async_entity_ids()
@asyncio.coroutine
def test_using_prescribed_entity_id_with_unique_id(hass):
async def test_using_prescribed_entity_id_with_unique_id(hass):
"""Test for ammending predefined entity ID because currently exists."""
component = EntityComponent(_LOGGER, DOMAIN, hass)
yield from component.async_add_entities([
await component.async_add_entities([
MockEntity(entity_id='test_domain.world')])
yield from component.async_add_entities([
await component.async_add_entities([
MockEntity(entity_id='test_domain.world', unique_id='bla')])
assert 'test_domain.world_2' in hass.states.async_entity_ids()
@asyncio.coroutine
def test_using_prescribed_entity_id_which_is_registered(hass):
async def test_using_prescribed_entity_id_which_is_registered(hass):
"""Test not allowing predefined entity ID that already registered."""
component = EntityComponent(_LOGGER, DOMAIN, hass)
registry = mock_registry(hass)
@ -454,14 +438,13 @@ def test_using_prescribed_entity_id_which_is_registered(hass):
DOMAIN, 'test', '1234', suggested_object_id='world')
# This entity_id will be rewritten
yield from component.async_add_entities([
await component.async_add_entities([
MockEntity(entity_id='test_domain.world')])
assert 'test_domain.world_2' in hass.states.async_entity_ids()
@asyncio.coroutine
def test_name_which_conflict_with_registered(hass):
async def test_name_which_conflict_with_registered(hass):
"""Test not generating conflicting entity ID based on name."""
component = EntityComponent(_LOGGER, DOMAIN, hass)
registry = mock_registry(hass)
@ -470,24 +453,22 @@ def test_name_which_conflict_with_registered(hass):
registry.async_get_or_create(
DOMAIN, 'test', '1234', suggested_object_id='world')
yield from component.async_add_entities([
await component.async_add_entities([
MockEntity(name='world')])
assert 'test_domain.world_2' in hass.states.async_entity_ids()
@asyncio.coroutine
def test_entity_with_name_and_entity_id_getting_registered(hass):
async def test_entity_with_name_and_entity_id_getting_registered(hass):
"""Ensure that entity ID is used for registration."""
component = EntityComponent(_LOGGER, DOMAIN, hass)
yield from component.async_add_entities([
await component.async_add_entities([
MockEntity(unique_id='1234', name='bla',
entity_id='test_domain.world')])
assert 'test_domain.world' in hass.states.async_entity_ids()
@asyncio.coroutine
def test_overriding_name_from_registry(hass):
async def test_overriding_name_from_registry(hass):
"""Test that we can override a name via the Entity Registry."""
component = EntityComponent(_LOGGER, DOMAIN, hass)
mock_registry(hass, {
@ -499,7 +480,7 @@ def test_overriding_name_from_registry(hass):
name='Overridden'
)
})
yield from component.async_add_entities([
await component.async_add_entities([
MockEntity(unique_id='1234', name='Device Name')])
state = hass.states.get('test_domain.world')
@ -507,18 +488,16 @@ def test_overriding_name_from_registry(hass):
assert state.name == 'Overridden'
@asyncio.coroutine
def test_registry_respect_entity_namespace(hass):
async def test_registry_respect_entity_namespace(hass):
"""Test that the registry respects entity namespace."""
mock_registry(hass)
platform = MockEntityPlatform(hass, entity_namespace='ns')
entity = MockEntity(unique_id='1234', name='Device Name')
yield from platform.async_add_entities([entity])
await platform.async_add_entities([entity])
assert entity.entity_id == 'test_domain.ns_device_name'
@asyncio.coroutine
def test_registry_respect_entity_disabled(hass):
async def test_registry_respect_entity_disabled(hass):
"""Test that the registry respects entity disabled."""
mock_registry(hass, {
'test_domain.world': entity_registry.RegistryEntry(
@ -531,7 +510,7 @@ def test_registry_respect_entity_disabled(hass):
})
platform = MockEntityPlatform(hass)
entity = MockEntity(unique_id='1234')
yield from platform.async_add_entities([entity])
await platform.async_add_entities([entity])
assert entity.entity_id is None
assert hass.states.async_entity_ids() == []
@ -643,12 +622,11 @@ async def test_reset_cancels_retry_setup(hass):
assert ent_platform._async_cancel_retry_setup is None
@asyncio.coroutine
def test_not_fails_with_adding_empty_entities_(hass):
async def test_not_fails_with_adding_empty_entities_(hass):
"""Test for not fails on empty entities list."""
component = EntityComponent(_LOGGER, DOMAIN, hass)
yield from component.async_add_entities([])
await component.async_add_entities([])
assert len(hass.states.async_entity_ids()) == 0

File diff suppressed because it is too large Load Diff

View File

@ -1,53 +1,43 @@
"""Test Home Assistant icon util methods."""
import unittest
class TestIconUtil(unittest.TestCase):
"""Test icon util methods."""
def test_battery_icon():
"""Test icon generator for battery sensor."""
from homeassistant.helpers.icon import icon_for_battery_level
def test_battery_icon(self):
"""Test icon generator for battery sensor."""
from homeassistant.helpers.icon import icon_for_battery_level
assert icon_for_battery_level(None, True) == 'mdi:battery-unknown'
assert icon_for_battery_level(None, False) == 'mdi:battery-unknown'
assert 'mdi:battery-unknown' == \
icon_for_battery_level(None, True)
assert 'mdi:battery-unknown' == \
icon_for_battery_level(None, False)
assert icon_for_battery_level(5, True) == 'mdi:battery-outline'
assert icon_for_battery_level(5, False) == 'mdi:battery-alert'
assert 'mdi:battery-outline' == \
icon_for_battery_level(5, True)
assert 'mdi:battery-alert' == \
icon_for_battery_level(5, False)
assert icon_for_battery_level(100, True) == 'mdi:battery-charging-100'
assert icon_for_battery_level(100, False) == 'mdi:battery'
assert 'mdi:battery-charging-100' == \
icon_for_battery_level(100, True)
assert 'mdi:battery' == \
icon_for_battery_level(100, False)
iconbase = 'mdi:battery'
for level in range(0, 100, 5):
print('Level: %d. icon: %s, charging: %s'
% (level, icon_for_battery_level(level, False),
icon_for_battery_level(level, True)))
if level <= 10:
postfix_charging = '-outline'
elif level <= 30:
postfix_charging = '-charging-20'
elif level <= 50:
postfix_charging = '-charging-40'
elif level <= 70:
postfix_charging = '-charging-60'
elif level <= 90:
postfix_charging = '-charging-80'
else:
postfix_charging = '-charging-100'
if 5 < level < 95:
postfix = '-{}'.format(int(round(level / 10 - .01)) * 10)
elif level <= 5:
postfix = '-alert'
else:
postfix = ''
assert iconbase + postfix == \
icon_for_battery_level(level, False)
assert iconbase + postfix_charging == \
icon_for_battery_level(level, True)
iconbase = 'mdi:battery'
for level in range(0, 100, 5):
print('Level: %d. icon: %s, charging: %s'
% (level, icon_for_battery_level(level, False),
icon_for_battery_level(level, True)))
if level <= 10:
postfix_charging = '-outline'
elif level <= 30:
postfix_charging = '-charging-20'
elif level <= 50:
postfix_charging = '-charging-40'
elif level <= 70:
postfix_charging = '-charging-60'
elif level <= 90:
postfix_charging = '-charging-80'
else:
postfix_charging = '-charging-100'
if 5 < level < 95:
postfix = '-{}'.format(int(round(level / 10 - .01)) * 10)
elif level <= 5:
postfix = '-alert'
else:
postfix = ''
assert iconbase + postfix == \
icon_for_battery_level(level, False)
assert iconbase + postfix_charging == \
icon_for_battery_level(level, True)

View File

@ -1,50 +1,35 @@
"""Test component helpers."""
# pylint: disable=protected-access
from collections import OrderedDict
import unittest
from homeassistant import helpers
from tests.common import get_test_home_assistant
def test_extract_domain_configs():
"""Test the extraction of domain configuration."""
config = {
'zone': None,
'zoner': None,
'zone ': None,
'zone Hallo': None,
'zone 100': None,
}
assert set(['zone', 'zone Hallo', 'zone 100']) == \
set(helpers.extract_domain_configs(config, 'zone'))
class TestHelpers(unittest.TestCase):
"""Tests homeassistant.helpers module."""
def test_config_per_platform():
"""Test config per platform method."""
config = OrderedDict([
('zone', {'platform': 'hello'}),
('zoner', None),
('zone Hallo', [1, {'platform': 'hello 2'}]),
('zone 100', None),
])
# pylint: disable=invalid-name
def setUp(self):
"""Init needed objects."""
self.hass = get_test_home_assistant()
# pylint: disable=invalid-name
def tearDown(self):
"""Stop everything that was started."""
self.hass.stop()
def test_extract_domain_configs(self):
"""Test the extraction of domain configuration."""
config = {
'zone': None,
'zoner': None,
'zone ': None,
'zone Hallo': None,
'zone 100': None,
}
assert set(['zone', 'zone Hallo', 'zone 100']) == \
set(helpers.extract_domain_configs(config, 'zone'))
def test_config_per_platform(self):
"""Test config per platform method."""
config = OrderedDict([
('zone', {'platform': 'hello'}),
('zoner', None),
('zone Hallo', [1, {'platform': 'hello 2'}]),
('zone 100', None),
])
assert [
('hello', config['zone']),
(None, 1),
('hello 2', config['zone Hallo'][1]),
] == list(helpers.config_per_platform(config, 'zone'))
assert [
('hello', config['zone']),
(None, 1),
('hello 2', config['zone Hallo'][1]),
] == list(helpers.config_per_platform(config, 'zone'))

View File

@ -1,11 +1,11 @@
"""Tests for the intent helpers."""
import unittest
import voluptuous as vol
import pytest
from homeassistant.core import State
from homeassistant.helpers import (intent, config_validation as cv)
import pytest
class MockIntentHandler(intent.IntentHandler):
@ -25,23 +25,20 @@ def test_async_match_state():
assert state is state1
class TestIntentHandler(unittest.TestCase):
"""Test the Home Assistant event helpers."""
def test_async_validate_slots():
"""Test async_validate_slots of IntentHandler."""
handler1 = MockIntentHandler({
vol.Required('name'): cv.string,
})
def test_async_validate_slots(self):
"""Test async_validate_slots of IntentHandler."""
handler1 = MockIntentHandler({
vol.Required('name'): cv.string,
})
with pytest.raises(vol.error.MultipleInvalid):
handler1.async_validate_slots({})
with pytest.raises(vol.error.MultipleInvalid):
handler1.async_validate_slots({'name': 1})
with pytest.raises(vol.error.MultipleInvalid):
handler1.async_validate_slots({'name': 'kitchen'})
handler1.async_validate_slots({'name': {'value': 'kitchen'}})
handler1.async_validate_slots({
'name': {'value': 'kitchen'},
'probability': {'value': '0.5'}
})
with pytest.raises(vol.error.MultipleInvalid):
handler1.async_validate_slots({})
with pytest.raises(vol.error.MultipleInvalid):
handler1.async_validate_slots({'name': 1})
with pytest.raises(vol.error.MultipleInvalid):
handler1.async_validate_slots({'name': 'kitchen'})
handler1.async_validate_slots({'name': {'value': 'kitchen'}})
handler1.async_validate_slots({
'name': {'value': 'kitchen'},
'probability': {'value': '0.5'}
})

View File

@ -1,58 +1,57 @@
"""Tests Home Assistant location helpers."""
import unittest
from homeassistant.const import ATTR_LATITUDE, ATTR_LONGITUDE
from homeassistant.core import State
from homeassistant.helpers import location
class TestHelpersLocation(unittest.TestCase):
def test_has_location_with_invalid_states():
"""Set up the tests."""
def test_has_location_with_invalid_states(self):
"""Set up the tests."""
for state in (None, 1, "hello", object):
assert not location.has_location(state)
def test_has_location_with_states_with_invalid_locations(self):
"""Set up the tests."""
state = State('hello.world', 'invalid', {
ATTR_LATITUDE: 'no number',
ATTR_LONGITUDE: 123.12
})
for state in (None, 1, "hello", object):
assert not location.has_location(state)
def test_has_location_with_states_with_valid_location(self):
"""Set up the tests."""
state = State('hello.world', 'invalid', {
ATTR_LATITUDE: 123.12,
ATTR_LONGITUDE: 123.12
})
assert location.has_location(state)
def test_closest_with_no_states_with_location(self):
"""Set up the tests."""
state = State('light.test', 'on')
state2 = State('light.test', 'on', {
ATTR_LATITUDE: 'invalid',
ATTR_LONGITUDE: 123.45,
})
state3 = State('light.test', 'on', {
ATTR_LONGITUDE: 123.45,
})
def test_has_location_with_states_with_invalid_locations():
"""Set up the tests."""
state = State('hello.world', 'invalid', {
ATTR_LATITUDE: 'no number',
ATTR_LONGITUDE: 123.12
})
assert not location.has_location(state)
assert \
location.closest(123.45, 123.45, [state, state2, state3]) is None
def test_closest_returns_closest(self):
"""Test ."""
state = State('light.test', 'on', {
ATTR_LATITUDE: 124.45,
ATTR_LONGITUDE: 124.45,
})
state2 = State('light.test', 'on', {
ATTR_LATITUDE: 125.45,
ATTR_LONGITUDE: 125.45,
})
def test_has_location_with_states_with_valid_location():
"""Set up the tests."""
state = State('hello.world', 'invalid', {
ATTR_LATITUDE: 123.12,
ATTR_LONGITUDE: 123.12
})
assert location.has_location(state)
assert state == location.closest(123.45, 123.45, [state, state2])
def test_closest_with_no_states_with_location():
"""Set up the tests."""
state = State('light.test', 'on')
state2 = State('light.test', 'on', {
ATTR_LATITUDE: 'invalid',
ATTR_LONGITUDE: 123.45,
})
state3 = State('light.test', 'on', {
ATTR_LONGITUDE: 123.45,
})
assert \
location.closest(123.45, 123.45, [state, state2, state3]) is None
def test_closest_returns_closest():
"""Test ."""
state = State('light.test', 'on', {
ATTR_LATITUDE: 124.45,
ATTR_LONGITUDE: 124.45,
})
state2 = State('light.test', 'on', {
ATTR_LATITUDE: 125.45,
ATTR_LONGITUDE: 125.45,
})
assert state == location.closest(123.45, 123.45, [state, state2])

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +1,12 @@
"""Test state helpers."""
import asyncio
from datetime import timedelta
import unittest
from unittest.mock import patch
import pytest
import homeassistant.core as ha
from homeassistant.setup import async_setup_component
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.helpers import state
from homeassistant.const import (
@ -18,8 +17,7 @@ from homeassistant.const import (
from homeassistant.components.sun import (STATE_ABOVE_HORIZON,
STATE_BELOW_HORIZON)
from tests.common import get_test_home_assistant, mock_service
import pytest
from tests.common import async_mock_service
@asyncio.coroutine
@ -82,141 +80,134 @@ def test_call_to_component(hass):
context=context)
class TestStateHelpers(unittest.TestCase):
"""Test the Home Assistant event helpers."""
async def test_get_changed_since(hass):
"""Test get_changed_since."""
point1 = dt_util.utcnow()
point2 = point1 + timedelta(seconds=5)
point3 = point2 + timedelta(seconds=5)
def setUp(self): # pylint: disable=invalid-name
"""Run when tests are started."""
self.hass = get_test_home_assistant()
run_coroutine_threadsafe(async_setup_component(
self.hass, 'homeassistant', {}), self.hass.loop).result()
with patch('homeassistant.core.dt_util.utcnow', return_value=point1):
hass.states.async_set('light.test', 'on')
state1 = hass.states.get('light.test')
def tearDown(self): # pylint: disable=invalid-name
"""Stop when tests are finished."""
self.hass.stop()
with patch('homeassistant.core.dt_util.utcnow', return_value=point2):
hass.states.async_set('light.test2', 'on')
state2 = hass.states.get('light.test2')
def test_get_changed_since(self):
"""Test get_changed_since."""
point1 = dt_util.utcnow()
point2 = point1 + timedelta(seconds=5)
point3 = point2 + timedelta(seconds=5)
with patch('homeassistant.core.dt_util.utcnow', return_value=point3):
hass.states.async_set('light.test3', 'on')
state3 = hass.states.get('light.test3')
with patch('homeassistant.core.dt_util.utcnow', return_value=point1):
self.hass.states.set('light.test', 'on')
state1 = self.hass.states.get('light.test')
assert [state2, state3] == \
state.get_changed_since([state1, state2, state3], point2)
with patch('homeassistant.core.dt_util.utcnow', return_value=point2):
self.hass.states.set('light.test2', 'on')
state2 = self.hass.states.get('light.test2')
with patch('homeassistant.core.dt_util.utcnow', return_value=point3):
self.hass.states.set('light.test3', 'on')
state3 = self.hass.states.get('light.test3')
async def test_reproduce_with_no_entity(hass):
"""Test reproduce_state with no entity."""
calls = async_mock_service(hass, 'light', SERVICE_TURN_ON)
assert [state2, state3] == \
state.get_changed_since([state1, state2, state3], point2)
await state.async_reproduce_state(hass, ha.State('light.test', 'on'))
def test_reproduce_with_no_entity(self):
"""Test reproduce_state with no entity."""
calls = mock_service(self.hass, 'light', SERVICE_TURN_ON)
await hass.async_block_till_done()
state.reproduce_state(self.hass, ha.State('light.test', 'on'))
assert len(calls) == 0
assert hass.states.get('light.test') is None
self.hass.block_till_done()
assert len(calls) == 0
assert self.hass.states.get('light.test') is None
async def test_reproduce_turn_on(hass):
"""Test reproduce_state with SERVICE_TURN_ON."""
calls = async_mock_service(hass, 'light', SERVICE_TURN_ON)
def test_reproduce_turn_on(self):
"""Test reproduce_state with SERVICE_TURN_ON."""
calls = mock_service(self.hass, 'light', SERVICE_TURN_ON)
hass.states.async_set('light.test', 'off')
self.hass.states.set('light.test', 'off')
await state.async_reproduce_state(hass, ha.State('light.test', 'on'))
state.reproduce_state(self.hass, ha.State('light.test', 'on'))
await hass.async_block_till_done()
self.hass.block_till_done()
assert len(calls) > 0
last_call = calls[-1]
assert last_call.domain == 'light'
assert SERVICE_TURN_ON == last_call.service
assert ['light.test'] == last_call.data.get('entity_id')
assert len(calls) > 0
last_call = calls[-1]
assert 'light' == last_call.domain
assert SERVICE_TURN_ON == last_call.service
assert ['light.test'] == last_call.data.get('entity_id')
def test_reproduce_turn_off(self):
"""Test reproduce_state with SERVICE_TURN_OFF."""
calls = mock_service(self.hass, 'light', SERVICE_TURN_OFF)
async def test_reproduce_turn_off(hass):
"""Test reproduce_state with SERVICE_TURN_OFF."""
calls = async_mock_service(hass, 'light', SERVICE_TURN_OFF)
self.hass.states.set('light.test', 'on')
hass.states.async_set('light.test', 'on')
state.reproduce_state(self.hass, ha.State('light.test', 'off'))
await state.async_reproduce_state(hass, ha.State('light.test', 'off'))
self.hass.block_till_done()
await hass.async_block_till_done()
assert len(calls) > 0
last_call = calls[-1]
assert 'light' == last_call.domain
assert SERVICE_TURN_OFF == last_call.service
assert ['light.test'] == last_call.data.get('entity_id')
assert len(calls) > 0
last_call = calls[-1]
assert last_call.domain == 'light'
assert SERVICE_TURN_OFF == last_call.service
assert ['light.test'] == last_call.data.get('entity_id')
def test_reproduce_complex_data(self):
"""Test reproduce_state with complex service data."""
calls = mock_service(self.hass, 'light', SERVICE_TURN_ON)
self.hass.states.set('light.test', 'off')
async def test_reproduce_complex_data(hass):
"""Test reproduce_state with complex service data."""
calls = async_mock_service(hass, 'light', SERVICE_TURN_ON)
complex_data = ['hello', {'11': '22'}]
hass.states.async_set('light.test', 'off')
state.reproduce_state(self.hass, ha.State('light.test', 'on', {
'complex': complex_data
}))
complex_data = ['hello', {'11': '22'}]
self.hass.block_till_done()
await state.async_reproduce_state(hass, ha.State('light.test', 'on', {
'complex': complex_data
}))
assert len(calls) > 0
last_call = calls[-1]
assert 'light' == last_call.domain
assert SERVICE_TURN_ON == last_call.service
assert complex_data == last_call.data.get('complex')
await hass.async_block_till_done()
def test_reproduce_bad_state(self):
"""Test reproduce_state with bad state."""
calls = mock_service(self.hass, 'light', SERVICE_TURN_ON)
assert len(calls) > 0
last_call = calls[-1]
assert last_call.domain == 'light'
assert SERVICE_TURN_ON == last_call.service
assert complex_data == last_call.data.get('complex')
self.hass.states.set('light.test', 'off')
state.reproduce_state(self.hass, ha.State('light.test', 'bad'))
async def test_reproduce_bad_state(hass):
"""Test reproduce_state with bad state."""
calls = async_mock_service(hass, 'light', SERVICE_TURN_ON)
self.hass.block_till_done()
hass.states.async_set('light.test', 'off')
assert len(calls) == 0
assert 'off' == self.hass.states.get('light.test').state
await state.async_reproduce_state(hass, ha.State('light.test', 'bad'))
def test_as_number_states(self):
"""Test state_as_number with states."""
zero_states = (STATE_OFF, STATE_CLOSED, STATE_UNLOCKED,
STATE_BELOW_HORIZON, STATE_NOT_HOME)
one_states = (STATE_ON, STATE_OPEN, STATE_LOCKED, STATE_ABOVE_HORIZON,
STATE_HOME)
for _state in zero_states:
assert 0 == state.state_as_number(
ha.State('domain.test', _state, {}))
for _state in one_states:
assert 1 == state.state_as_number(
ha.State('domain.test', _state, {}))
await hass.async_block_till_done()
def test_as_number_coercion(self):
"""Test state_as_number with number."""
for _state in ('0', '0.0', 0, 0.0):
assert 0.0 == state.state_as_number(
ha.State('domain.test', _state, {}))
for _state in ('1', '1.0', 1, 1.0):
assert 1.0 == state.state_as_number(
ha.State('domain.test', _state, {}))
assert len(calls) == 0
assert hass.states.get('light.test').state == 'off'
def test_as_number_invalid_cases(self):
"""Test state_as_number with invalid cases."""
for _state in ('', 'foo', 'foo.bar', None, False, True, object,
object()):
with pytest.raises(ValueError):
state.state_as_number(ha.State('domain.test', _state, {}))
async def test_as_number_states(hass):
"""Test state_as_number with states."""
zero_states = (STATE_OFF, STATE_CLOSED, STATE_UNLOCKED,
STATE_BELOW_HORIZON, STATE_NOT_HOME)
one_states = (STATE_ON, STATE_OPEN, STATE_LOCKED, STATE_ABOVE_HORIZON,
STATE_HOME)
for _state in zero_states:
assert state.state_as_number(ha.State('domain.test', _state, {})) == 0
for _state in one_states:
assert state.state_as_number(ha.State('domain.test', _state, {})) == 1
async def test_as_number_coercion(hass):
"""Test state_as_number with number."""
for _state in ('0', '0.0', 0, 0.0):
assert state.state_as_number(
ha.State('domain.test', _state, {})) == 0.0
for _state in ('1', '1.0', 1, 1.0):
assert state.state_as_number(
ha.State('domain.test', _state, {})) == 1.0
async def test_as_number_invalid_cases(hass):
"""Test state_as_number with invalid cases."""
for _state in ('', 'foo', 'foo.bar', None, False, True, object,
object()):
with pytest.raises(ValueError):
state.state_as_number(ha.State('domain.test', _state, {}))

View File

@ -1,6 +1,5 @@
"""The tests for the Sun helpers."""
# pylint: disable=protected-access
import unittest
from unittest.mock import patch
from datetime import timedelta, datetime
@ -8,223 +7,214 @@ from homeassistant.const import SUN_EVENT_SUNRISE, SUN_EVENT_SUNSET
import homeassistant.util.dt as dt_util
import homeassistant.helpers.sun as sun
from tests.common import get_test_home_assistant
def test_next_events(hass):
"""Test retrieving next sun events."""
utc_now = datetime(2016, 11, 1, 8, 0, 0, tzinfo=dt_util.UTC)
from astral import Astral
astral = Astral()
utc_today = utc_now.date()
latitude = hass.config.latitude
longitude = hass.config.longitude
mod = -1
while True:
next_dawn = (astral.dawn_utc(
utc_today + timedelta(days=mod), latitude, longitude))
if next_dawn > utc_now:
break
mod += 1
mod = -1
while True:
next_dusk = (astral.dusk_utc(
utc_today + timedelta(days=mod), latitude, longitude))
if next_dusk > utc_now:
break
mod += 1
mod = -1
while True:
next_midnight = (astral.solar_midnight_utc(
utc_today + timedelta(days=mod), longitude))
if next_midnight > utc_now:
break
mod += 1
mod = -1
while True:
next_noon = (astral.solar_noon_utc(
utc_today + timedelta(days=mod), longitude))
if next_noon > utc_now:
break
mod += 1
mod = -1
while True:
next_rising = (astral.sunrise_utc(
utc_today + timedelta(days=mod), latitude, longitude))
if next_rising > utc_now:
break
mod += 1
mod = -1
while True:
next_setting = (astral.sunset_utc(
utc_today + timedelta(days=mod), latitude, longitude))
if next_setting > utc_now:
break
mod += 1
with patch('homeassistant.helpers.condition.dt_util.utcnow',
return_value=utc_now):
assert next_dawn == sun.get_astral_event_next(
hass, 'dawn')
assert next_dusk == sun.get_astral_event_next(
hass, 'dusk')
assert next_midnight == sun.get_astral_event_next(
hass, 'solar_midnight')
assert next_noon == sun.get_astral_event_next(
hass, 'solar_noon')
assert next_rising == sun.get_astral_event_next(
hass, SUN_EVENT_SUNRISE)
assert next_setting == sun.get_astral_event_next(
hass, SUN_EVENT_SUNSET)
# pylint: disable=invalid-name
class TestSun(unittest.TestCase):
"""Test the sun helpers."""
def test_date_events(hass):
"""Test retrieving next sun events."""
utc_now = datetime(2016, 11, 1, 8, 0, 0, tzinfo=dt_util.UTC)
from astral import Astral
def setUp(self):
"""Set up things to be run when tests are started."""
self.hass = get_test_home_assistant()
astral = Astral()
utc_today = utc_now.date()
def tearDown(self):
"""Stop everything that was started."""
self.hass.stop()
latitude = hass.config.latitude
longitude = hass.config.longitude
def test_next_events(self):
"""Test retrieving next sun events."""
utc_now = datetime(2016, 11, 1, 8, 0, 0, tzinfo=dt_util.UTC)
from astral import Astral
dawn = astral.dawn_utc(utc_today, latitude, longitude)
dusk = astral.dusk_utc(utc_today, latitude, longitude)
midnight = astral.solar_midnight_utc(utc_today, longitude)
noon = astral.solar_noon_utc(utc_today, longitude)
sunrise = astral.sunrise_utc(utc_today, latitude, longitude)
sunset = astral.sunset_utc(utc_today, latitude, longitude)
astral = Astral()
utc_today = utc_now.date()
assert dawn == sun.get_astral_event_date(
hass, 'dawn', utc_today)
assert dusk == sun.get_astral_event_date(
hass, 'dusk', utc_today)
assert midnight == sun.get_astral_event_date(
hass, 'solar_midnight', utc_today)
assert noon == sun.get_astral_event_date(
hass, 'solar_noon', utc_today)
assert sunrise == sun.get_astral_event_date(
hass, SUN_EVENT_SUNRISE, utc_today)
assert sunset == sun.get_astral_event_date(
hass, SUN_EVENT_SUNSET, utc_today)
latitude = self.hass.config.latitude
longitude = self.hass.config.longitude
mod = -1
while True:
next_dawn = (astral.dawn_utc(
utc_today + timedelta(days=mod), latitude, longitude))
if next_dawn > utc_now:
break
mod += 1
def test_date_events_default_date(hass):
"""Test retrieving next sun events."""
utc_now = datetime(2016, 11, 1, 8, 0, 0, tzinfo=dt_util.UTC)
from astral import Astral
mod = -1
while True:
next_dusk = (astral.dusk_utc(
utc_today + timedelta(days=mod), latitude, longitude))
if next_dusk > utc_now:
break
mod += 1
astral = Astral()
utc_today = utc_now.date()
mod = -1
while True:
next_midnight = (astral.solar_midnight_utc(
utc_today + timedelta(days=mod), longitude))
if next_midnight > utc_now:
break
mod += 1
latitude = hass.config.latitude
longitude = hass.config.longitude
mod = -1
while True:
next_noon = (astral.solar_noon_utc(
utc_today + timedelta(days=mod), longitude))
if next_noon > utc_now:
break
mod += 1
mod = -1
while True:
next_rising = (astral.sunrise_utc(
utc_today + timedelta(days=mod), latitude, longitude))
if next_rising > utc_now:
break
mod += 1
mod = -1
while True:
next_setting = (astral.sunset_utc(
utc_today + timedelta(days=mod), latitude, longitude))
if next_setting > utc_now:
break
mod += 1
with patch('homeassistant.helpers.condition.dt_util.utcnow',
return_value=utc_now):
assert next_dawn == sun.get_astral_event_next(
self.hass, 'dawn')
assert next_dusk == sun.get_astral_event_next(
self.hass, 'dusk')
assert next_midnight == sun.get_astral_event_next(
self.hass, 'solar_midnight')
assert next_noon == sun.get_astral_event_next(
self.hass, 'solar_noon')
assert next_rising == sun.get_astral_event_next(
self.hass, SUN_EVENT_SUNRISE)
assert next_setting == sun.get_astral_event_next(
self.hass, SUN_EVENT_SUNSET)
def test_date_events(self):
"""Test retrieving next sun events."""
utc_now = datetime(2016, 11, 1, 8, 0, 0, tzinfo=dt_util.UTC)
from astral import Astral
astral = Astral()
utc_today = utc_now.date()
latitude = self.hass.config.latitude
longitude = self.hass.config.longitude
dawn = astral.dawn_utc(utc_today, latitude, longitude)
dusk = astral.dusk_utc(utc_today, latitude, longitude)
midnight = astral.solar_midnight_utc(utc_today, longitude)
noon = astral.solar_noon_utc(utc_today, longitude)
sunrise = astral.sunrise_utc(utc_today, latitude, longitude)
sunset = astral.sunset_utc(utc_today, latitude, longitude)
dawn = astral.dawn_utc(utc_today, latitude, longitude)
dusk = astral.dusk_utc(utc_today, latitude, longitude)
midnight = astral.solar_midnight_utc(utc_today, longitude)
noon = astral.solar_noon_utc(utc_today, longitude)
sunrise = astral.sunrise_utc(utc_today, latitude, longitude)
sunset = astral.sunset_utc(utc_today, latitude, longitude)
with patch('homeassistant.util.dt.now', return_value=utc_now):
assert dawn == sun.get_astral_event_date(
self.hass, 'dawn', utc_today)
hass, 'dawn', utc_today)
assert dusk == sun.get_astral_event_date(
self.hass, 'dusk', utc_today)
hass, 'dusk', utc_today)
assert midnight == sun.get_astral_event_date(
self.hass, 'solar_midnight', utc_today)
hass, 'solar_midnight', utc_today)
assert noon == sun.get_astral_event_date(
self.hass, 'solar_noon', utc_today)
hass, 'solar_noon', utc_today)
assert sunrise == sun.get_astral_event_date(
self.hass, SUN_EVENT_SUNRISE, utc_today)
hass, SUN_EVENT_SUNRISE, utc_today)
assert sunset == sun.get_astral_event_date(
self.hass, SUN_EVENT_SUNSET, utc_today)
hass, SUN_EVENT_SUNSET, utc_today)
def test_date_events_default_date(self):
"""Test retrieving next sun events."""
utc_now = datetime(2016, 11, 1, 8, 0, 0, tzinfo=dt_util.UTC)
from astral import Astral
astral = Astral()
utc_today = utc_now.date()
def test_date_events_accepts_datetime(hass):
"""Test retrieving next sun events."""
utc_now = datetime(2016, 11, 1, 8, 0, 0, tzinfo=dt_util.UTC)
from astral import Astral
latitude = self.hass.config.latitude
longitude = self.hass.config.longitude
astral = Astral()
utc_today = utc_now.date()
dawn = astral.dawn_utc(utc_today, latitude, longitude)
dusk = astral.dusk_utc(utc_today, latitude, longitude)
midnight = astral.solar_midnight_utc(utc_today, longitude)
noon = astral.solar_noon_utc(utc_today, longitude)
sunrise = astral.sunrise_utc(utc_today, latitude, longitude)
sunset = astral.sunset_utc(utc_today, latitude, longitude)
latitude = hass.config.latitude
longitude = hass.config.longitude
with patch('homeassistant.util.dt.now', return_value=utc_now):
assert dawn == sun.get_astral_event_date(
self.hass, 'dawn', utc_today)
assert dusk == sun.get_astral_event_date(
self.hass, 'dusk', utc_today)
assert midnight == sun.get_astral_event_date(
self.hass, 'solar_midnight', utc_today)
assert noon == sun.get_astral_event_date(
self.hass, 'solar_noon', utc_today)
assert sunrise == sun.get_astral_event_date(
self.hass, SUN_EVENT_SUNRISE, utc_today)
assert sunset == sun.get_astral_event_date(
self.hass, SUN_EVENT_SUNSET, utc_today)
dawn = astral.dawn_utc(utc_today, latitude, longitude)
dusk = astral.dusk_utc(utc_today, latitude, longitude)
midnight = astral.solar_midnight_utc(utc_today, longitude)
noon = astral.solar_noon_utc(utc_today, longitude)
sunrise = astral.sunrise_utc(utc_today, latitude, longitude)
sunset = astral.sunset_utc(utc_today, latitude, longitude)
def test_date_events_accepts_datetime(self):
"""Test retrieving next sun events."""
utc_now = datetime(2016, 11, 1, 8, 0, 0, tzinfo=dt_util.UTC)
from astral import Astral
assert dawn == sun.get_astral_event_date(
hass, 'dawn', utc_now)
assert dusk == sun.get_astral_event_date(
hass, 'dusk', utc_now)
assert midnight == sun.get_astral_event_date(
hass, 'solar_midnight', utc_now)
assert noon == sun.get_astral_event_date(
hass, 'solar_noon', utc_now)
assert sunrise == sun.get_astral_event_date(
hass, SUN_EVENT_SUNRISE, utc_now)
assert sunset == sun.get_astral_event_date(
hass, SUN_EVENT_SUNSET, utc_now)
astral = Astral()
utc_today = utc_now.date()
latitude = self.hass.config.latitude
longitude = self.hass.config.longitude
def test_is_up(hass):
"""Test retrieving next sun events."""
utc_now = datetime(2016, 11, 1, 12, 0, 0, tzinfo=dt_util.UTC)
with patch('homeassistant.helpers.condition.dt_util.utcnow',
return_value=utc_now):
assert not sun.is_up(hass)
dawn = astral.dawn_utc(utc_today, latitude, longitude)
dusk = astral.dusk_utc(utc_today, latitude, longitude)
midnight = astral.solar_midnight_utc(utc_today, longitude)
noon = astral.solar_noon_utc(utc_today, longitude)
sunrise = astral.sunrise_utc(utc_today, latitude, longitude)
sunset = astral.sunset_utc(utc_today, latitude, longitude)
utc_now = datetime(2016, 11, 1, 18, 0, 0, tzinfo=dt_util.UTC)
with patch('homeassistant.helpers.condition.dt_util.utcnow',
return_value=utc_now):
assert sun.is_up(hass)
assert dawn == sun.get_astral_event_date(
self.hass, 'dawn', utc_now)
assert dusk == sun.get_astral_event_date(
self.hass, 'dusk', utc_now)
assert midnight == sun.get_astral_event_date(
self.hass, 'solar_midnight', utc_now)
assert noon == sun.get_astral_event_date(
self.hass, 'solar_noon', utc_now)
assert sunrise == sun.get_astral_event_date(
self.hass, SUN_EVENT_SUNRISE, utc_now)
assert sunset == sun.get_astral_event_date(
self.hass, SUN_EVENT_SUNSET, utc_now)
def test_is_up(self):
"""Test retrieving next sun events."""
utc_now = datetime(2016, 11, 1, 12, 0, 0, tzinfo=dt_util.UTC)
with patch('homeassistant.helpers.condition.dt_util.utcnow',
return_value=utc_now):
assert not sun.is_up(self.hass)
def test_norway_in_june(hass):
"""Test location in Norway where the sun doesn't set in summer."""
hass.config.latitude = 69.6
hass.config.longitude = 18.8
utc_now = datetime(2016, 11, 1, 18, 0, 0, tzinfo=dt_util.UTC)
with patch('homeassistant.helpers.condition.dt_util.utcnow',
return_value=utc_now):
assert sun.is_up(self.hass)
june = datetime(2016, 6, 1, tzinfo=dt_util.UTC)
def test_norway_in_june(self):
"""Test location in Norway where the sun doesn't set in summer."""
self.hass.config.latitude = 69.6
self.hass.config.longitude = 18.8
print(sun.get_astral_event_date(hass, SUN_EVENT_SUNRISE,
datetime(2017, 7, 25)))
print(sun.get_astral_event_date(hass, SUN_EVENT_SUNSET,
datetime(2017, 7, 25)))
june = datetime(2016, 6, 1, tzinfo=dt_util.UTC)
print(sun.get_astral_event_date(hass, SUN_EVENT_SUNRISE,
datetime(2017, 7, 26)))
print(sun.get_astral_event_date(hass, SUN_EVENT_SUNSET,
datetime(2017, 7, 26)))
print(sun.get_astral_event_date(self.hass, SUN_EVENT_SUNRISE,
datetime(2017, 7, 25)))
print(sun.get_astral_event_date(self.hass, SUN_EVENT_SUNSET,
datetime(2017, 7, 25)))
print(sun.get_astral_event_date(self.hass, SUN_EVENT_SUNRISE,
datetime(2017, 7, 26)))
print(sun.get_astral_event_date(self.hass, SUN_EVENT_SUNSET,
datetime(2017, 7, 26)))
assert sun.get_astral_event_next(self.hass, SUN_EVENT_SUNRISE, june) \
== datetime(2016, 7, 25, 23, 23, 39, tzinfo=dt_util.UTC)
assert sun.get_astral_event_next(self.hass, SUN_EVENT_SUNSET, june) \
== datetime(2016, 7, 26, 22, 19, 1, tzinfo=dt_util.UTC)
assert sun.get_astral_event_date(self.hass, SUN_EVENT_SUNRISE, june) \
is None
assert sun.get_astral_event_date(self.hass, SUN_EVENT_SUNSET, june) \
is None
assert sun.get_astral_event_next(hass, SUN_EVENT_SUNRISE, june) \
== datetime(2016, 7, 25, 23, 23, 39, tzinfo=dt_util.UTC)
assert sun.get_astral_event_next(hass, SUN_EVENT_SUNSET, june) \
== datetime(2016, 7, 26, 22, 19, 1, tzinfo=dt_util.UTC)
assert sun.get_astral_event_date(hass, SUN_EVENT_SUNRISE, june) \
is None
assert sun.get_astral_event_date(hass, SUN_EVENT_SUNSET, june) \
is None

View File

@ -1,50 +1,34 @@
"""Tests Home Assistant temperature helpers."""
import unittest
from tests.common import get_test_home_assistant
import pytest
from homeassistant.const import (
TEMP_CELSIUS, PRECISION_WHOLE, TEMP_FAHRENHEIT, PRECISION_HALVES,
PRECISION_TENTHS)
from homeassistant.helpers.temperature import display_temp
from homeassistant.util.unit_system import METRIC_SYSTEM
import pytest
TEMP = 24.636626
class TestHelpersTemperature(unittest.TestCase):
"""Set up the temperature tests."""
def test_temperature_not_a_number(hass):
"""Test that temperature is a number."""
temp = "Temperature"
with pytest.raises(Exception) as exception:
display_temp(hass, temp, TEMP_CELSIUS, PRECISION_HALVES)
def setUp(self):
"""Set up the tests."""
self.hass = get_test_home_assistant()
self.hass.config.unit_system = METRIC_SYSTEM
assert "Temperature is not a number: {}".format(temp) \
in str(exception)
def tearDown(self):
"""Stop down stuff we started."""
self.hass.stop()
def test_temperature_not_a_number(self):
"""Test that temperature is a number."""
temp = "Temperature"
with pytest.raises(Exception) as exception:
display_temp(self.hass, temp, TEMP_CELSIUS, PRECISION_HALVES)
def test_celsius_halves(hass):
"""Test temperature to celsius rounding to halves."""
assert display_temp(hass, TEMP, TEMP_CELSIUS, PRECISION_HALVES) == 24.5
assert "Temperature is not a number: {}".format(temp) \
in str(exception)
def test_celsius_halves(self):
"""Test temperature to celsius rounding to halves."""
assert 24.5 == display_temp(
self.hass, TEMP, TEMP_CELSIUS, PRECISION_HALVES)
def test_celsius_tenths(hass):
"""Test temperature to celsius rounding to tenths."""
assert display_temp(hass, TEMP, TEMP_CELSIUS, PRECISION_TENTHS) == 24.6
def test_celsius_tenths(self):
"""Test temperature to celsius rounding to tenths."""
assert 24.6 == display_temp(
self.hass, TEMP, TEMP_CELSIUS, PRECISION_TENTHS)
def test_fahrenheit_wholes(self):
"""Test temperature to fahrenheit rounding to wholes."""
assert -4 == display_temp(
self.hass, TEMP, TEMP_FAHRENHEIT, PRECISION_WHOLE)
def test_fahrenheit_wholes(hass):
"""Test temperature to fahrenheit rounding to wholes."""
assert display_temp(hass, TEMP, TEMP_FAHRENHEIT, PRECISION_WHOLE) == -4

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,6 @@
"""Test check_config script."""
import asyncio
import logging
import os # noqa: F401 pylint: disable=unused-import
import unittest
from unittest.mock import patch
import homeassistant.scripts.check_config as check_config
@ -36,149 +34,138 @@ def normalize_yaml_files(check_dict):
for key in sorted(check_dict['yaml_files'].keys())]
# pylint: disable=unsubscriptable-object
class TestCheckConfig(unittest.TestCase):
"""Tests for the homeassistant.scripts.check_config module."""
# pylint: disable=no-self-use,invalid-name
@patch('os.path.isfile', return_value=True)
def test_bad_core_config(isfile_patch, loop):
"""Test a bad core config setup."""
files = {
YAML_CONFIG_FILE: BAD_CORE_CONFIG,
}
with patch_yaml_files(files):
res = check_config.check(get_test_config_dir())
assert res['except'].keys() == {'homeassistant'}
assert res['except']['homeassistant'][1] == {'unit_system': 'bad'}
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:
asyncio.set_event_loop(asyncio.new_event_loop())
# Will allow seeing full diff
self.maxDiff = None # pylint: disable=invalid-name
@patch('os.path.isfile', return_value=True)
def test_config_platform_valid(isfile_patch, loop):
"""Test a valid platform setup."""
files = {
YAML_CONFIG_FILE: BASE_CONFIG + 'light:\n platform: demo',
}
with patch_yaml_files(files):
res = check_config.check(get_test_config_dir())
assert res['components'].keys() == {'homeassistant', 'light'}
assert res['components']['light'] == [{'platform': 'demo'}]
assert res['except'] == {}
assert res['secret_cache'] == {}
assert res['secrets'] == {}
assert len(res['yaml_files']) == 1
# pylint: disable=no-self-use,invalid-name
@patch('os.path.isfile', return_value=True)
def test_bad_core_config(self, isfile_patch):
"""Test a bad core config setup."""
files = {
YAML_CONFIG_FILE: BAD_CORE_CONFIG,
@patch('os.path.isfile', return_value=True)
def test_component_platform_not_found(isfile_patch, loop):
"""Test errors if component or platform not found."""
# Make sure they don't exist
files = {
YAML_CONFIG_FILE: BASE_CONFIG + 'beer:',
}
with patch_yaml_files(files):
res = check_config.check(get_test_config_dir())
assert res['components'].keys() == {'homeassistant'}
assert res['except'] == {
check_config.ERROR_STR: ['Integration not found: beer']}
assert res['secret_cache'] == {}
assert res['secrets'] == {}
assert len(res['yaml_files']) == 1
files = {
YAML_CONFIG_FILE: BASE_CONFIG + 'light:\n platform: beer',
}
with patch_yaml_files(files):
res = check_config.check(get_test_config_dir())
assert res['components'].keys() == {'homeassistant', 'light'}
assert res['components']['light'] == []
assert res['except'] == {
check_config.ERROR_STR: [
'Integration beer not found when trying to verify its '
'light platform.',
]}
assert res['secret_cache'] == {}
assert res['secrets'] == {}
assert len(res['yaml_files']) == 1
@patch('os.path.isfile', return_value=True)
def test_secrets(isfile_patch, loop):
"""Test secrets config checking method."""
secrets_path = get_test_config_dir('secrets.yaml')
files = {
get_test_config_dir(YAML_CONFIG_FILE): BASE_CONFIG + (
'http:\n'
' api_password: !secret http_pw'),
secrets_path: (
'logger: debug\n'
'http_pw: abc123'),
}
with patch_yaml_files(files):
res = check_config.check(get_test_config_dir(), True)
assert res['except'] == {}
assert res['components'].keys() == {'homeassistant', 'http'}
assert res['components']['http'] == {
'api_password': 'abc123',
'cors_allowed_origins': [],
'ip_ban_enabled': True,
'login_attempts_threshold': -1,
'server_host': '0.0.0.0',
'server_port': 8123,
'trusted_networks': [],
'ssl_profile': 'modern',
}
with patch_yaml_files(files):
res = check_config.check(get_test_config_dir())
assert res['except'].keys() == {'homeassistant'}
assert res['except']['homeassistant'][1] == {'unit_system': 'bad'}
assert res['secret_cache'] == {secrets_path: {'http_pw': 'abc123'}}
assert res['secrets'] == {'http_pw': 'abc123'}
assert normalize_yaml_files(res) == [
'.../configuration.yaml', '.../secrets.yaml']
@patch('os.path.isfile', return_value=True)
def test_config_platform_valid(self, isfile_patch):
"""Test a valid platform setup."""
files = {
YAML_CONFIG_FILE: BASE_CONFIG + 'light:\n platform: demo',
}
with patch_yaml_files(files):
res = check_config.check(get_test_config_dir())
assert res['components'].keys() == {'homeassistant', 'light'}
assert res['components']['light'] == [{'platform': 'demo'}]
assert res['except'] == {}
assert res['secret_cache'] == {}
assert res['secrets'] == {}
assert len(res['yaml_files']) == 1
@patch('os.path.isfile', return_value=True)
def test_component_platform_not_found(self, isfile_patch):
"""Test errors if component or platform not found."""
# Make sure they don't exist
files = {
YAML_CONFIG_FILE: BASE_CONFIG + 'beer:',
}
with patch_yaml_files(files):
res = check_config.check(get_test_config_dir())
assert res['components'].keys() == {'homeassistant'}
assert res['except'] == {
check_config.ERROR_STR: ['Integration not found: beer']}
assert res['secret_cache'] == {}
assert res['secrets'] == {}
assert len(res['yaml_files']) == 1
@patch('os.path.isfile', return_value=True)
def test_package_invalid(isfile_patch, loop):
"""Test a valid platform setup."""
files = {
YAML_CONFIG_FILE: BASE_CONFIG + (
' packages:\n'
' p1:\n'
' group: ["a"]'),
}
with patch_yaml_files(files):
res = check_config.check(get_test_config_dir())
files = {
YAML_CONFIG_FILE: BASE_CONFIG + 'light:\n platform: beer',
}
with patch_yaml_files(files):
res = check_config.check(get_test_config_dir())
assert res['components'].keys() == {'homeassistant', 'light'}
assert res['components']['light'] == []
assert res['except'] == {
check_config.ERROR_STR: [
'Integration beer not found when trying to verify its '
'light platform.',
]}
assert res['secret_cache'] == {}
assert res['secrets'] == {}
assert len(res['yaml_files']) == 1
assert res['except'].keys() == {'homeassistant.packages.p1.group'}
assert res['except']['homeassistant.packages.p1.group'][1] == \
{'group': ['a']}
assert len(res['except']) == 1
assert res['components'].keys() == {'homeassistant'}
assert len(res['components']) == 1
assert res['secret_cache'] == {}
assert res['secrets'] == {}
assert len(res['yaml_files']) == 1
@patch('os.path.isfile', return_value=True)
def test_secrets(self, isfile_patch):
"""Test secrets config checking method."""
secrets_path = get_test_config_dir('secrets.yaml')
files = {
get_test_config_dir(YAML_CONFIG_FILE): BASE_CONFIG + (
'http:\n'
' api_password: !secret http_pw'),
secrets_path: (
'logger: debug\n'
'http_pw: abc123'),
}
with patch_yaml_files(files):
res = check_config.check(get_test_config_dir(), True)
assert res['except'] == {}
assert res['components'].keys() == {'homeassistant', 'http'}
assert res['components']['http'] == {
'api_password': 'abc123',
'cors_allowed_origins': [],
'ip_ban_enabled': True,
'login_attempts_threshold': -1,
'server_host': '0.0.0.0',
'server_port': 8123,
'trusted_networks': [],
'ssl_profile': 'modern',
}
assert res['secret_cache'] == {secrets_path: {'http_pw': 'abc123'}}
assert res['secrets'] == {'http_pw': 'abc123'}
assert normalize_yaml_files(res) == [
'.../configuration.yaml', '.../secrets.yaml']
@patch('os.path.isfile', return_value=True)
def test_package_invalid(self, isfile_patch):
"""Test a valid platform setup."""
files = {
YAML_CONFIG_FILE: BASE_CONFIG + (
' packages:\n'
' p1:\n'
' group: ["a"]'),
}
with patch_yaml_files(files):
res = check_config.check(get_test_config_dir())
assert res['except'].keys() == {'homeassistant.packages.p1.group'}
assert res['except']['homeassistant.packages.p1.group'][1] == \
{'group': ['a']}
assert len(res['except']) == 1
assert res['components'].keys() == {'homeassistant'}
assert len(res['components']) == 1
assert res['secret_cache'] == {}
assert res['secrets'] == {}
assert len(res['yaml_files']) == 1
def test_bootstrap_error(self):
"""Test a valid platform setup."""
files = {
YAML_CONFIG_FILE: BASE_CONFIG + 'automation: !include no.yaml',
}
with patch_yaml_files(files):
res = check_config.check(get_test_config_dir(YAML_CONFIG_FILE))
err = res['except'].pop(check_config.ERROR_STR)
assert len(err) == 1
assert res['except'] == {}
assert res['components'] == {} # No components, load failed
assert res['secret_cache'] == {}
assert res['secrets'] == {}
assert res['yaml_files'] == {}
def test_bootstrap_error(loop):
"""Test a valid platform setup."""
files = {
YAML_CONFIG_FILE: BASE_CONFIG + 'automation: !include no.yaml',
}
with patch_yaml_files(files):
res = check_config.check(get_test_config_dir(YAML_CONFIG_FILE))
err = res['except'].pop(check_config.ERROR_STR)
assert len(err) == 1
assert res['except'] == {}
assert res['components'] == {} # No components, load failed
assert res['secret_cache'] == {}
assert res['secrets'] == {}
assert res['yaml_files'] == {}

View File

@ -1,19 +1,15 @@
"""Test script init."""
import unittest
from unittest.mock import patch
import homeassistant.scripts as scripts
class TestScripts(unittest.TestCase):
"""Tests homeassistant.scripts module."""
@patch('homeassistant.scripts.get_default_config_dir',
return_value='/default')
def test_config_per_platform(self, mock_def):
"""Test config per platform method."""
self.assertEqual(scripts.get_default_config_dir(), '/default')
self.assertEqual(scripts.extract_config_dir(), '/default')
self.assertEqual(scripts.extract_config_dir(['']), '/default')
self.assertEqual(scripts.extract_config_dir(['-c', '/arg']), '/arg')
self.assertEqual(scripts.extract_config_dir(['--config', '/a']), '/a')
@patch('homeassistant.scripts.get_default_config_dir',
return_value='/default')
def test_config_per_platform(mock_def):
"""Test config per platform method."""
assert scripts.get_default_config_dir() == '/default'
assert scripts.extract_config_dir() == '/default'
assert scripts.extract_config_dir(['']) == '/default'
assert scripts.extract_config_dir(['-c', '/arg']) == '/arg'
assert scripts.extract_config_dir(['--config', '/a']) == '/a'

View File

@ -2,7 +2,6 @@
# pylint: disable=protected-access
import asyncio
import os
import unittest
import unittest.mock as mock
from collections import OrderedDict
from ipaddress import ip_network
@ -23,7 +22,6 @@ from homeassistant.const import (
CONF_AUTH_PROVIDERS, CONF_AUTH_MFA_MODULES)
from homeassistant.util import location as location_util, dt as dt_util
from homeassistant.util.yaml import SECRET_YAML
from homeassistant.util.async_ import run_coroutine_threadsafe
from homeassistant.helpers.entity import Entity
from homeassistant.components.config.group import (
CONFIG_PATH as GROUP_CONFIG_PATH)
@ -36,7 +34,7 @@ from homeassistant.components.config.customize import (
import homeassistant.scripts.check_config as check_config
from tests.common import (
get_test_config_dir, get_test_home_assistant, patch_yaml_files)
get_test_config_dir, patch_yaml_files)
CONFIG_DIR = get_test_config_dir()
YAML_PATH = os.path.join(CONFIG_DIR, config_util.YAML_CONFIG_FILE)
@ -55,512 +53,508 @@ def create_file(path):
pass
class TestConfig(unittest.TestCase):
"""Test the configutils."""
def teardown():
"""Clean up."""
dt_util.DEFAULT_TIME_ZONE = ORIG_TIMEZONE
# pylint: disable=invalid-name
def setUp(self):
"""Initialize a test Home Assistant instance."""
self.hass = get_test_home_assistant()
if os.path.isfile(YAML_PATH):
os.remove(YAML_PATH)
# pylint: disable=invalid-name
def tearDown(self):
"""Clean up."""
dt_util.DEFAULT_TIME_ZONE = ORIG_TIMEZONE
if os.path.isfile(SECRET_PATH):
os.remove(SECRET_PATH)
if os.path.isfile(YAML_PATH):
os.remove(YAML_PATH)
if os.path.isfile(VERSION_PATH):
os.remove(VERSION_PATH)
if os.path.isfile(SECRET_PATH):
os.remove(SECRET_PATH)
if os.path.isfile(GROUP_PATH):
os.remove(GROUP_PATH)
if os.path.isfile(VERSION_PATH):
os.remove(VERSION_PATH)
if os.path.isfile(AUTOMATIONS_PATH):
os.remove(AUTOMATIONS_PATH)
if os.path.isfile(GROUP_PATH):
os.remove(GROUP_PATH)
if os.path.isfile(SCRIPTS_PATH):
os.remove(SCRIPTS_PATH)
if os.path.isfile(AUTOMATIONS_PATH):
os.remove(AUTOMATIONS_PATH)
if os.path.isfile(CUSTOMIZE_PATH):
os.remove(CUSTOMIZE_PATH)
if os.path.isfile(SCRIPTS_PATH):
os.remove(SCRIPTS_PATH)
if os.path.isfile(CUSTOMIZE_PATH):
os.remove(CUSTOMIZE_PATH)
def test_create_default_config():
"""Test creation of default config."""
config_util.create_default_config(CONFIG_DIR, False)
self.hass.stop()
assert os.path.isfile(YAML_PATH)
assert os.path.isfile(SECRET_PATH)
assert os.path.isfile(VERSION_PATH)
assert os.path.isfile(GROUP_PATH)
assert os.path.isfile(AUTOMATIONS_PATH)
assert os.path.isfile(CUSTOMIZE_PATH)
# pylint: disable=no-self-use
def test_create_default_config(self):
"""Test creation of default config."""
config_util.create_default_config(CONFIG_DIR, False)
assert os.path.isfile(YAML_PATH)
assert os.path.isfile(SECRET_PATH)
assert os.path.isfile(VERSION_PATH)
assert os.path.isfile(GROUP_PATH)
assert os.path.isfile(AUTOMATIONS_PATH)
assert os.path.isfile(CUSTOMIZE_PATH)
def test_find_config_file_yaml():
"""Test if it finds a YAML config file."""
create_file(YAML_PATH)
def test_find_config_file_yaml(self):
"""Test if it finds a YAML config file."""
create_file(YAML_PATH)
assert YAML_PATH == config_util.find_config_file(CONFIG_DIR)
assert YAML_PATH == config_util.find_config_file(CONFIG_DIR)
@mock.patch('builtins.print')
def test_ensure_config_exists_creates_config(self, mock_print):
"""Test that calling ensure_config_exists.
@mock.patch('builtins.print')
def test_ensure_config_exists_creates_config(mock_print):
"""Test that calling ensure_config_exists.
If not creates a new config file.
"""
config_util.ensure_config_exists(CONFIG_DIR, False)
If not creates a new config file.
"""
config_util.ensure_config_exists(CONFIG_DIR, False)
assert os.path.isfile(YAML_PATH)
assert mock_print.called
assert os.path.isfile(YAML_PATH)
assert mock_print.called
def test_ensure_config_exists_uses_existing_config(self):
"""Test that calling ensure_config_exists uses existing config."""
create_file(YAML_PATH)
config_util.ensure_config_exists(CONFIG_DIR, False)
with open(YAML_PATH) as f:
content = f.read()
def test_ensure_config_exists_uses_existing_config():
"""Test that calling ensure_config_exists uses existing config."""
create_file(YAML_PATH)
config_util.ensure_config_exists(CONFIG_DIR, False)
# File created with create_file are empty
assert '' == content
with open(YAML_PATH) as f:
content = f.read()
def test_load_yaml_config_converts_empty_files_to_dict(self):
"""Test that loading an empty file returns an empty dict."""
create_file(YAML_PATH)
# File created with create_file are empty
assert content == ''
assert isinstance(config_util.load_yaml_config_file(YAML_PATH), dict)
def test_load_yaml_config_raises_error_if_not_dict(self):
"""Test error raised when YAML file is not a dict."""
with open(YAML_PATH, 'w') as f:
f.write('5')
def test_load_yaml_config_converts_empty_files_to_dict():
"""Test that loading an empty file returns an empty dict."""
create_file(YAML_PATH)
with pytest.raises(HomeAssistantError):
config_util.load_yaml_config_file(YAML_PATH)
assert isinstance(config_util.load_yaml_config_file(YAML_PATH), dict)
def test_load_yaml_config_raises_error_if_malformed_yaml(self):
"""Test error raised if invalid YAML."""
with open(YAML_PATH, 'w') as f:
f.write(':')
with pytest.raises(HomeAssistantError):
config_util.load_yaml_config_file(YAML_PATH)
def test_load_yaml_config_raises_error_if_not_dict():
"""Test error raised when YAML file is not a dict."""
with open(YAML_PATH, 'w') as f:
f.write('5')
def test_load_yaml_config_raises_error_if_unsafe_yaml(self):
"""Test error raised if unsafe YAML."""
with open(YAML_PATH, 'w') as f:
f.write('hello: !!python/object/apply:os.system')
with pytest.raises(HomeAssistantError):
config_util.load_yaml_config_file(YAML_PATH)
with pytest.raises(HomeAssistantError):
config_util.load_yaml_config_file(YAML_PATH)
def test_load_yaml_config_preserves_key_order(self):
"""Test removal of library."""
with open(YAML_PATH, 'w') as f:
f.write('hello: 2\n')
f.write('world: 1\n')
def test_load_yaml_config_raises_error_if_malformed_yaml():
"""Test error raised if invalid YAML."""
with open(YAML_PATH, 'w') as f:
f.write(':')
assert [('hello', 2), ('world', 1)] == \
list(config_util.load_yaml_config_file(YAML_PATH).items())
with pytest.raises(HomeAssistantError):
config_util.load_yaml_config_file(YAML_PATH)
@mock.patch('homeassistant.util.location.detect_location_info',
return_value=location_util.LocationInfo(
'0.0.0.0', 'US', 'United States', 'CA', 'California',
'San Diego', '92122', 'America/Los_Angeles', 32.8594,
-117.2073, True))
@mock.patch('homeassistant.util.location.elevation', return_value=101)
@mock.patch('builtins.print')
def test_create_default_config_detect_location(self, mock_detect,
mock_elev, mock_print):
"""Test that detect location sets the correct config keys."""
config_util.ensure_config_exists(CONFIG_DIR)
config = config_util.load_yaml_config_file(YAML_PATH)
def test_load_yaml_config_raises_error_if_unsafe_yaml():
"""Test error raised if unsafe YAML."""
with open(YAML_PATH, 'w') as f:
f.write('hello: !!python/object/apply:os.system')
assert DOMAIN in config
with pytest.raises(HomeAssistantError):
config_util.load_yaml_config_file(YAML_PATH)
ha_conf = config[DOMAIN]
expected_values = {
CONF_LATITUDE: 32.8594,
CONF_LONGITUDE: -117.2073,
CONF_ELEVATION: 101,
CONF_UNIT_SYSTEM: CONF_UNIT_SYSTEM_METRIC,
CONF_NAME: 'Home',
CONF_TIME_ZONE: 'America/Los_Angeles',
CONF_CUSTOMIZE: OrderedDict(),
}
def test_load_yaml_config_preserves_key_order():
"""Test removal of library."""
with open(YAML_PATH, 'w') as f:
f.write('hello: 2\n')
f.write('world: 1\n')
assert expected_values == ha_conf
assert mock_print.called
assert [('hello', 2), ('world', 1)] == \
list(config_util.load_yaml_config_file(YAML_PATH).items())
@mock.patch('builtins.print')
def test_create_default_config_returns_none_if_write_error(self,
mock_print):
"""Test the writing of a default configuration.
Non existing folder returns None.
"""
assert config_util.create_default_config(
os.path.join(CONFIG_DIR, 'non_existing_dir/'), False) is None
assert mock_print.called
@mock.patch('homeassistant.util.location.detect_location_info',
return_value=location_util.LocationInfo(
'0.0.0.0', 'US', 'United States', 'CA', 'California',
'San Diego', '92122', 'America/Los_Angeles', 32.8594,
-117.2073, True))
@mock.patch('homeassistant.util.location.elevation', return_value=101)
@mock.patch('builtins.print')
def test_create_default_config_detect_location(mock_detect,
mock_elev, mock_print):
"""Test that detect location sets the correct config keys."""
config_util.ensure_config_exists(CONFIG_DIR)
# pylint: disable=no-self-use
def test_core_config_schema(self):
"""Test core config schema."""
for value in (
{CONF_UNIT_SYSTEM: 'K'},
{'time_zone': 'non-exist'},
{'latitude': '91'},
{'longitude': -181},
{'customize': 'bla'},
{'customize': {'light.sensor': 100}},
{'customize': {'entity_id': []}},
):
with pytest.raises(MultipleInvalid):
config_util.CORE_CONFIG_SCHEMA(value)
config = config_util.load_yaml_config_file(YAML_PATH)
config_util.CORE_CONFIG_SCHEMA({
'name': 'Test name',
'latitude': '-23.45',
'longitude': '123.45',
CONF_UNIT_SYSTEM: CONF_UNIT_SYSTEM_METRIC,
'customize': {
'sensor.temperature': {
'hidden': True,
},
assert DOMAIN in config
ha_conf = config[DOMAIN]
expected_values = {
CONF_LATITUDE: 32.8594,
CONF_LONGITUDE: -117.2073,
CONF_ELEVATION: 101,
CONF_UNIT_SYSTEM: CONF_UNIT_SYSTEM_METRIC,
CONF_NAME: 'Home',
CONF_TIME_ZONE: 'America/Los_Angeles',
CONF_CUSTOMIZE: OrderedDict(),
}
assert expected_values == ha_conf
assert mock_print.called
@mock.patch('builtins.print')
def test_create_default_config_returns_none_if_write_error(mock_print):
"""Test the writing of a default configuration.
Non existing folder returns None.
"""
assert config_util.create_default_config(
os.path.join(CONFIG_DIR, 'non_existing_dir/'), False) is None
assert mock_print.called
def test_core_config_schema():
"""Test core config schema."""
for value in (
{CONF_UNIT_SYSTEM: 'K'},
{'time_zone': 'non-exist'},
{'latitude': '91'},
{'longitude': -181},
{'customize': 'bla'},
{'customize': {'light.sensor': 100}},
{'customize': {'entity_id': []}},
):
with pytest.raises(MultipleInvalid):
config_util.CORE_CONFIG_SCHEMA(value)
config_util.CORE_CONFIG_SCHEMA({
'name': 'Test name',
'latitude': '-23.45',
'longitude': '123.45',
CONF_UNIT_SYSTEM: CONF_UNIT_SYSTEM_METRIC,
'customize': {
'sensor.temperature': {
'hidden': True,
},
},
})
def test_customize_dict_schema():
"""Test basic customize config validation."""
values = (
{ATTR_FRIENDLY_NAME: None},
{ATTR_HIDDEN: '2'},
{ATTR_ASSUMED_STATE: '2'},
)
for val in values:
print(val)
with pytest.raises(MultipleInvalid):
config_util.CUSTOMIZE_DICT_SCHEMA(val)
assert config_util.CUSTOMIZE_DICT_SCHEMA({
ATTR_FRIENDLY_NAME: 2,
ATTR_HIDDEN: '1',
ATTR_ASSUMED_STATE: '0',
}) == {
ATTR_FRIENDLY_NAME: '2',
ATTR_HIDDEN: True,
ATTR_ASSUMED_STATE: False
}
def test_customize_glob_is_ordered():
"""Test that customize_glob preserves order."""
conf = config_util.CORE_CONFIG_SCHEMA(
{'customize_glob': OrderedDict()})
assert isinstance(conf['customize_glob'], OrderedDict)
async def _compute_state(hass, config):
await config_util.async_process_ha_core_config(hass, config)
entity = Entity()
entity.entity_id = 'test.test'
entity.hass = hass
entity.schedule_update_ha_state()
await hass.async_block_till_done()
return hass.states.get('test.test')
async def test_entity_customization(hass):
"""Test entity customization through configuration."""
config = {CONF_LATITUDE: 50,
CONF_LONGITUDE: 50,
CONF_NAME: 'Test',
CONF_CUSTOMIZE: {'test.test': {'hidden': True}}}
state = await _compute_state(hass, config)
assert state.attributes['hidden']
@mock.patch('homeassistant.config.shutil')
@mock.patch('homeassistant.config.os')
def test_remove_lib_on_upgrade(mock_os, mock_shutil, hass):
"""Test removal of library on upgrade from before 0.50."""
ha_version = '0.49.0'
mock_os.path.isdir = mock.Mock(return_value=True)
mock_open = mock.mock_open()
with mock.patch('homeassistant.config.open', mock_open, create=True):
opened_file = mock_open.return_value
# pylint: disable=no-member
opened_file.readline.return_value = ha_version
hass.config.path = mock.Mock()
config_util.process_ha_config_upgrade(hass)
hass_path = hass.config.path.return_value
assert mock_os.path.isdir.call_count == 1
assert mock_os.path.isdir.call_args == mock.call(hass_path)
assert mock_shutil.rmtree.call_count == 1
assert mock_shutil.rmtree.call_args == mock.call(hass_path)
def test_process_config_upgrade(hass):
"""Test update of version on upgrade."""
ha_version = '0.92.0'
mock_open = mock.mock_open()
with mock.patch('homeassistant.config.open', mock_open, create=True), \
mock.patch.object(config_util, '__version__', '0.91.0'):
opened_file = mock_open.return_value
# pylint: disable=no-member
opened_file.readline.return_value = ha_version
config_util.process_ha_config_upgrade(hass)
assert opened_file.write.call_count == 1
assert opened_file.write.call_args == mock.call('0.91.0')
def test_config_upgrade_same_version(hass):
"""Test no update of version on no upgrade."""
ha_version = __version__
mock_open = mock.mock_open()
with mock.patch('homeassistant.config.open', mock_open, create=True):
opened_file = mock_open.return_value
# pylint: disable=no-member
opened_file.readline.return_value = ha_version
config_util.process_ha_config_upgrade(hass)
assert opened_file.write.call_count == 0
@mock.patch('homeassistant.config.find_config_file', mock.Mock())
def test_config_upgrade_no_file(hass):
"""Test update of version on upgrade, with no version file."""
mock_open = mock.mock_open()
mock_open.side_effect = [FileNotFoundError(),
mock.DEFAULT,
mock.DEFAULT]
with mock.patch('homeassistant.config.open', mock_open, create=True):
opened_file = mock_open.return_value
# pylint: disable=no-member
config_util.process_ha_config_upgrade(hass)
assert opened_file.write.call_count == 1
assert opened_file.write.call_args == mock.call(__version__)
@mock.patch('homeassistant.config.shutil')
@mock.patch('homeassistant.config.os')
@mock.patch('homeassistant.config.find_config_file', mock.Mock())
def test_migrate_file_on_upgrade(mock_os, mock_shutil, hass):
"""Test migrate of config files on upgrade."""
ha_version = '0.7.0'
mock_os.path.isdir = mock.Mock(return_value=True)
mock_open = mock.mock_open()
def _mock_isfile(filename):
return True
with mock.patch('homeassistant.config.open', mock_open, create=True), \
mock.patch('homeassistant.config.os.path.isfile', _mock_isfile):
opened_file = mock_open.return_value
# pylint: disable=no-member
opened_file.readline.return_value = ha_version
hass.config.path = mock.Mock()
config_util.process_ha_config_upgrade(hass)
assert mock_os.rename.call_count == 1
@mock.patch('homeassistant.config.shutil')
@mock.patch('homeassistant.config.os')
@mock.patch('homeassistant.config.find_config_file', mock.Mock())
def test_migrate_no_file_on_upgrade(mock_os, mock_shutil, hass):
"""Test not migrating config files on upgrade."""
ha_version = '0.7.0'
mock_os.path.isdir = mock.Mock(return_value=True)
mock_open = mock.mock_open()
def _mock_isfile(filename):
return False
with mock.patch('homeassistant.config.open', mock_open, create=True), \
mock.patch('homeassistant.config.os.path.isfile', _mock_isfile):
opened_file = mock_open.return_value
# pylint: disable=no-member
opened_file.readline.return_value = ha_version
hass.config.path = mock.Mock()
config_util.process_ha_config_upgrade(hass)
assert mock_os.rename.call_count == 0
async def test_loading_configuration(hass):
"""Test loading core config onto hass object."""
hass.config = mock.Mock()
await config_util.async_process_ha_core_config(hass, {
'latitude': 60,
'longitude': 50,
'elevation': 25,
'name': 'Huis',
CONF_UNIT_SYSTEM: CONF_UNIT_SYSTEM_IMPERIAL,
'time_zone': 'America/New_York',
'whitelist_external_dirs': '/tmp',
})
assert hass.config.latitude == 60
assert hass.config.longitude == 50
assert hass.config.elevation == 25
assert hass.config.location_name == 'Huis'
assert hass.config.units.name == CONF_UNIT_SYSTEM_IMPERIAL
assert hass.config.time_zone.zone == 'America/New_York'
assert len(hass.config.whitelist_external_dirs) == 2
assert '/tmp' in hass.config.whitelist_external_dirs
async def test_loading_configuration_temperature_unit(hass):
"""Test backward compatibility when loading core config."""
hass.config = mock.Mock()
await config_util.async_process_ha_core_config(hass, {
'latitude': 60,
'longitude': 50,
'elevation': 25,
'name': 'Huis',
CONF_TEMPERATURE_UNIT: 'C',
'time_zone': 'America/New_York',
})
assert hass.config.latitude == 60
assert hass.config.longitude == 50
assert hass.config.elevation == 25
assert hass.config.location_name == 'Huis'
assert hass.config.units.name == CONF_UNIT_SYSTEM_METRIC
assert hass.config.time_zone.zone == 'America/New_York'
async def test_loading_configuration_from_packages(hass):
"""Test loading packages config onto hass object config."""
hass.config = mock.Mock()
await config_util.async_process_ha_core_config(hass, {
'latitude': 39,
'longitude': -1,
'elevation': 500,
'name': 'Huis',
CONF_TEMPERATURE_UNIT: 'C',
'time_zone': 'Europe/Madrid',
'packages': {
'package_1': {'wake_on_lan': None},
'package_2': {'light': {'platform': 'hue'},
'media_extractor': None,
'sun': None}},
})
# Empty packages not allowed
with pytest.raises(MultipleInvalid):
await config_util.async_process_ha_core_config(hass, {
'latitude': 39,
'longitude': -1,
'elevation': 500,
'name': 'Huis',
CONF_TEMPERATURE_UNIT: 'C',
'time_zone': 'Europe/Madrid',
'packages': {'empty_package': None},
})
def test_customize_dict_schema(self):
"""Test basic customize config validation."""
values = (
{ATTR_FRIENDLY_NAME: None},
{ATTR_HIDDEN: '2'},
{ATTR_ASSUMED_STATE: '2'},
)
for val in values:
print(val)
with pytest.raises(MultipleInvalid):
config_util.CUSTOMIZE_DICT_SCHEMA(val)
@asynctest.mock.patch('homeassistant.util.location.detect_location_info',
autospec=True, return_value=location_util.LocationInfo(
'0.0.0.0', 'US', 'United States', 'CA', 'California',
'San Diego', '92122', 'America/Los_Angeles', 32.8594,
-117.2073, True))
@asynctest.mock.patch('homeassistant.util.location.elevation',
autospec=True, return_value=101)
async def test_discovering_configuration(mock_detect, mock_elevation, hass):
"""Test auto discovery for missing core configs."""
hass.config.latitude = None
hass.config.longitude = None
hass.config.elevation = None
hass.config.location_name = None
hass.config.time_zone = None
assert config_util.CUSTOMIZE_DICT_SCHEMA({
ATTR_FRIENDLY_NAME: 2,
ATTR_HIDDEN: '1',
ATTR_ASSUMED_STATE: '0',
}) == {
ATTR_FRIENDLY_NAME: '2',
ATTR_HIDDEN: True,
ATTR_ASSUMED_STATE: False
}
await config_util.async_process_ha_core_config(hass, {})
def test_customize_glob_is_ordered(self):
"""Test that customize_glob preserves order."""
conf = config_util.CORE_CONFIG_SCHEMA(
{'customize_glob': OrderedDict()})
assert isinstance(conf['customize_glob'], OrderedDict)
assert hass.config.latitude == 32.8594
assert hass.config.longitude == -117.2073
assert hass.config.elevation == 101
assert hass.config.location_name == 'San Diego'
assert hass.config.units.name == CONF_UNIT_SYSTEM_METRIC
assert hass.config.units.is_metric
assert hass.config.time_zone.zone == 'America/Los_Angeles'
def _compute_state(self, config):
run_coroutine_threadsafe(
config_util.async_process_ha_core_config(self.hass, config),
self.hass.loop).result()
entity = Entity()
entity.entity_id = 'test.test'
entity.hass = self.hass
entity.schedule_update_ha_state()
@asynctest.mock.patch('homeassistant.util.location.detect_location_info',
autospec=True, return_value=None)
@asynctest.mock.patch('homeassistant.util.location.elevation', return_value=0)
async def test_discovering_configuration_auto_detect_fails(mock_detect,
mock_elevation,
hass):
"""Test config remains unchanged if discovery fails."""
hass.config = Config()
hass.config.config_dir = "/test/config"
self.hass.block_till_done()
await config_util.async_process_ha_core_config(hass, {})
return self.hass.states.get('test.test')
blankConfig = Config()
assert hass.config.latitude == blankConfig.latitude
assert hass.config.longitude == blankConfig.longitude
assert hass.config.elevation == blankConfig.elevation
assert hass.config.location_name == blankConfig.location_name
assert hass.config.units == blankConfig.units
assert hass.config.time_zone == blankConfig.time_zone
assert len(hass.config.whitelist_external_dirs) == 1
assert "/test/config/www" in hass.config.whitelist_external_dirs
def test_entity_customization(self):
"""Test entity customization through configuration."""
config = {CONF_LATITUDE: 50,
CONF_LONGITUDE: 50,
CONF_NAME: 'Test',
CONF_CUSTOMIZE: {'test.test': {'hidden': True}}}
state = self._compute_state(config)
@asynctest.mock.patch(
'homeassistant.scripts.check_config.check_ha_config_file')
async def test_check_ha_config_file_correct(mock_check, hass):
"""Check that restart propagates to stop."""
mock_check.return_value = check_config.HomeAssistantConfig()
assert await config_util.async_check_ha_config_file(hass) is None
assert state.attributes['hidden']
@mock.patch('homeassistant.config.shutil')
@mock.patch('homeassistant.config.os')
def test_remove_lib_on_upgrade(self, mock_os, mock_shutil):
"""Test removal of library on upgrade from before 0.50."""
ha_version = '0.49.0'
mock_os.path.isdir = mock.Mock(return_value=True)
mock_open = mock.mock_open()
with mock.patch('homeassistant.config.open', mock_open, create=True):
opened_file = mock_open.return_value
# pylint: disable=no-member
opened_file.readline.return_value = ha_version
self.hass.config.path = mock.Mock()
config_util.process_ha_config_upgrade(self.hass)
hass_path = self.hass.config.path.return_value
@asynctest.mock.patch(
'homeassistant.scripts.check_config.check_ha_config_file')
async def test_check_ha_config_file_wrong(mock_check, hass):
"""Check that restart with a bad config doesn't propagate to stop."""
mock_check.return_value = check_config.HomeAssistantConfig()
mock_check.return_value.add_error("bad")
assert mock_os.path.isdir.call_count == 1
assert mock_os.path.isdir.call_args == mock.call(hass_path)
assert mock_shutil.rmtree.call_count == 1
assert mock_shutil.rmtree.call_args == mock.call(hass_path)
def test_process_config_upgrade(self):
"""Test update of version on upgrade."""
ha_version = '0.92.0'
mock_open = mock.mock_open()
with mock.patch('homeassistant.config.open', mock_open, create=True), \
mock.patch.object(config_util, '__version__', '0.91.0'):
opened_file = mock_open.return_value
# pylint: disable=no-member
opened_file.readline.return_value = ha_version
config_util.process_ha_config_upgrade(self.hass)
assert opened_file.write.call_count == 1
assert opened_file.write.call_args == mock.call('0.91.0')
def test_config_upgrade_same_version(self):
"""Test no update of version on no upgrade."""
ha_version = __version__
mock_open = mock.mock_open()
with mock.patch('homeassistant.config.open', mock_open, create=True):
opened_file = mock_open.return_value
# pylint: disable=no-member
opened_file.readline.return_value = ha_version
config_util.process_ha_config_upgrade(self.hass)
assert opened_file.write.call_count == 0
@mock.patch('homeassistant.config.find_config_file', mock.Mock())
def test_config_upgrade_no_file(self):
"""Test update of version on upgrade, with no version file."""
mock_open = mock.mock_open()
mock_open.side_effect = [FileNotFoundError(),
mock.DEFAULT,
mock.DEFAULT]
with mock.patch('homeassistant.config.open', mock_open, create=True):
opened_file = mock_open.return_value
# pylint: disable=no-member
config_util.process_ha_config_upgrade(self.hass)
assert opened_file.write.call_count == 1
assert opened_file.write.call_args == mock.call(__version__)
@mock.patch('homeassistant.config.shutil')
@mock.patch('homeassistant.config.os')
@mock.patch('homeassistant.config.find_config_file', mock.Mock())
def test_migrate_file_on_upgrade(self, mock_os, mock_shutil):
"""Test migrate of config files on upgrade."""
ha_version = '0.7.0'
mock_os.path.isdir = mock.Mock(return_value=True)
mock_open = mock.mock_open()
def _mock_isfile(filename):
return True
with mock.patch('homeassistant.config.open', mock_open, create=True), \
mock.patch(
'homeassistant.config.os.path.isfile', _mock_isfile):
opened_file = mock_open.return_value
# pylint: disable=no-member
opened_file.readline.return_value = ha_version
self.hass.config.path = mock.Mock()
config_util.process_ha_config_upgrade(self.hass)
assert mock_os.rename.call_count == 1
@mock.patch('homeassistant.config.shutil')
@mock.patch('homeassistant.config.os')
@mock.patch('homeassistant.config.find_config_file', mock.Mock())
def test_migrate_no_file_on_upgrade(self, mock_os, mock_shutil):
"""Test not migrating config files on upgrade."""
ha_version = '0.7.0'
mock_os.path.isdir = mock.Mock(return_value=True)
mock_open = mock.mock_open()
def _mock_isfile(filename):
return False
with mock.patch('homeassistant.config.open', mock_open, create=True), \
mock.patch(
'homeassistant.config.os.path.isfile', _mock_isfile):
opened_file = mock_open.return_value
# pylint: disable=no-member
opened_file.readline.return_value = ha_version
self.hass.config.path = mock.Mock()
config_util.process_ha_config_upgrade(self.hass)
assert mock_os.rename.call_count == 0
def test_loading_configuration(self):
"""Test loading core config onto hass object."""
self.hass.config = mock.Mock()
run_coroutine_threadsafe(
config_util.async_process_ha_core_config(self.hass, {
'latitude': 60,
'longitude': 50,
'elevation': 25,
'name': 'Huis',
CONF_UNIT_SYSTEM: CONF_UNIT_SYSTEM_IMPERIAL,
'time_zone': 'America/New_York',
'whitelist_external_dirs': '/tmp',
}), self.hass.loop).result()
assert self.hass.config.latitude == 60
assert self.hass.config.longitude == 50
assert self.hass.config.elevation == 25
assert self.hass.config.location_name == 'Huis'
assert self.hass.config.units.name == CONF_UNIT_SYSTEM_IMPERIAL
assert self.hass.config.time_zone.zone == 'America/New_York'
assert len(self.hass.config.whitelist_external_dirs) == 2
assert '/tmp' in self.hass.config.whitelist_external_dirs
def test_loading_configuration_temperature_unit(self):
"""Test backward compatibility when loading core config."""
self.hass.config = mock.Mock()
run_coroutine_threadsafe(
config_util.async_process_ha_core_config(self.hass, {
'latitude': 60,
'longitude': 50,
'elevation': 25,
'name': 'Huis',
CONF_TEMPERATURE_UNIT: 'C',
'time_zone': 'America/New_York',
}), self.hass.loop).result()
assert self.hass.config.latitude == 60
assert self.hass.config.longitude == 50
assert self.hass.config.elevation == 25
assert self.hass.config.location_name == 'Huis'
assert self.hass.config.units.name == CONF_UNIT_SYSTEM_METRIC
assert self.hass.config.time_zone.zone == 'America/New_York'
def test_loading_configuration_from_packages(self):
"""Test loading packages config onto hass object config."""
self.hass.config = mock.Mock()
run_coroutine_threadsafe(
config_util.async_process_ha_core_config(self.hass, {
'latitude': 39,
'longitude': -1,
'elevation': 500,
'name': 'Huis',
CONF_TEMPERATURE_UNIT: 'C',
'time_zone': 'Europe/Madrid',
'packages': {
'package_1': {'wake_on_lan': None},
'package_2': {'light': {'platform': 'hue'},
'media_extractor': None,
'sun': None}},
}), self.hass.loop).result()
# Empty packages not allowed
with pytest.raises(MultipleInvalid):
run_coroutine_threadsafe(
config_util.async_process_ha_core_config(self.hass, {
'latitude': 39,
'longitude': -1,
'elevation': 500,
'name': 'Huis',
CONF_TEMPERATURE_UNIT: 'C',
'time_zone': 'Europe/Madrid',
'packages': {'empty_package': None},
}), self.hass.loop).result()
@mock.patch('homeassistant.util.location.detect_location_info',
autospec=True, return_value=location_util.LocationInfo(
'0.0.0.0', 'US', 'United States', 'CA', 'California',
'San Diego', '92122', 'America/Los_Angeles', 32.8594,
-117.2073, True))
@mock.patch('homeassistant.util.location.elevation',
autospec=True, return_value=101)
def test_discovering_configuration(self, mock_detect, mock_elevation):
"""Test auto discovery for missing core configs."""
self.hass.config.latitude = None
self.hass.config.longitude = None
self.hass.config.elevation = None
self.hass.config.location_name = None
self.hass.config.time_zone = None
run_coroutine_threadsafe(
config_util.async_process_ha_core_config(
self.hass, {}), self.hass.loop
).result()
assert self.hass.config.latitude == 32.8594
assert self.hass.config.longitude == -117.2073
assert self.hass.config.elevation == 101
assert self.hass.config.location_name == 'San Diego'
assert self.hass.config.units.name == CONF_UNIT_SYSTEM_METRIC
assert self.hass.config.units.is_metric
assert self.hass.config.time_zone.zone == 'America/Los_Angeles'
@mock.patch('homeassistant.util.location.detect_location_info',
autospec=True, return_value=None)
@mock.patch('homeassistant.util.location.elevation', return_value=0)
def test_discovering_configuration_auto_detect_fails(self, mock_detect,
mock_elevation):
"""Test config remains unchanged if discovery fails."""
self.hass.config = Config()
self.hass.config.config_dir = "/test/config"
run_coroutine_threadsafe(
config_util.async_process_ha_core_config(
self.hass, {}), self.hass.loop
).result()
blankConfig = Config()
assert self.hass.config.latitude == blankConfig.latitude
assert self.hass.config.longitude == blankConfig.longitude
assert self.hass.config.elevation == blankConfig.elevation
assert self.hass.config.location_name == blankConfig.location_name
assert self.hass.config.units == blankConfig.units
assert self.hass.config.time_zone == blankConfig.time_zone
assert len(self.hass.config.whitelist_external_dirs) == 1
assert "/test/config/www" in self.hass.config.whitelist_external_dirs
@asynctest.mock.patch(
'homeassistant.scripts.check_config.check_ha_config_file')
def test_check_ha_config_file_correct(self, mock_check):
"""Check that restart propagates to stop."""
mock_check.return_value = check_config.HomeAssistantConfig()
assert run_coroutine_threadsafe(
config_util.async_check_ha_config_file(self.hass),
self.hass.loop
).result() is None
@asynctest.mock.patch(
'homeassistant.scripts.check_config.check_ha_config_file')
def test_check_ha_config_file_wrong(self, mock_check):
"""Check that restart with a bad config doesn't propagate to stop."""
mock_check.return_value = check_config.HomeAssistantConfig()
mock_check.return_value.add_error("bad")
assert run_coroutine_threadsafe(
config_util.async_check_ha_config_file(self.hass),
self.hass.loop
).result() == 'bad'
assert await config_util.async_check_ha_config_file(hass) == 'bad'
@asynctest.mock.patch('homeassistant.config.os.path.isfile',

View File

@ -1,10 +1,9 @@
"""Test Home Assistant color util methods."""
import unittest
import homeassistant.util.color as color_util
import pytest
import voluptuous as vol
import homeassistant.util.color as color_util
GAMUT = color_util.GamutType(color_util.XYPoint(0.704, 0.296),
color_util.XYPoint(0.2151, 0.7106),
color_util.XYPoint(0.138, 0.08))
@ -22,408 +21,340 @@ GAMUT_INVALID_4 = color_util.GamutType(color_util.XYPoint(0.1, 0.1),
color_util.XYPoint(0.7, 0.7))
class TestColorUtil(unittest.TestCase):
"""Test color util methods."""
# pylint: disable=invalid-name
def test_color_RGB_to_xy_brightness():
"""Test color_RGB_to_xy_brightness."""
assert color_util.color_RGB_to_xy_brightness(0, 0, 0) == (0, 0, 0)
assert color_util.color_RGB_to_xy_brightness(255, 255, 255) == \
(0.323, 0.329, 255)
# pylint: disable=invalid-name
def test_color_RGB_to_xy_brightness(self):
"""Test color_RGB_to_xy_brightness."""
assert (0, 0, 0) == \
color_util.color_RGB_to_xy_brightness(0, 0, 0)
assert (0.323, 0.329, 255) == \
color_util.color_RGB_to_xy_brightness(255, 255, 255)
assert color_util.color_RGB_to_xy_brightness(0, 0, 255) == \
(0.136, 0.04, 12)
assert (0.136, 0.04, 12) == \
color_util.color_RGB_to_xy_brightness(0, 0, 255)
assert color_util.color_RGB_to_xy_brightness(0, 255, 0) == \
(0.172, 0.747, 170)
assert (0.172, 0.747, 170) == \
color_util.color_RGB_to_xy_brightness(0, 255, 0)
assert color_util.color_RGB_to_xy_brightness(255, 0, 0) == \
(0.701, 0.299, 72)
assert (0.701, 0.299, 72) == \
color_util.color_RGB_to_xy_brightness(255, 0, 0)
assert color_util.color_RGB_to_xy_brightness(128, 0, 0) == \
(0.701, 0.299, 16)
assert (0.701, 0.299, 16) == \
color_util.color_RGB_to_xy_brightness(128, 0, 0)
assert color_util.color_RGB_to_xy_brightness(255, 0, 0, GAMUT) == \
(0.7, 0.299, 72)
assert (0.7, 0.299, 72) == \
color_util.color_RGB_to_xy_brightness(255, 0, 0, GAMUT)
assert color_util.color_RGB_to_xy_brightness(0, 255, 0, GAMUT) == \
(0.215, 0.711, 170)
assert (0.215, 0.711, 170) == \
color_util.color_RGB_to_xy_brightness(0, 255, 0, GAMUT)
assert color_util.color_RGB_to_xy_brightness(0, 0, 255, GAMUT) == \
(0.138, 0.08, 12)
assert (0.138, 0.08, 12) == \
color_util.color_RGB_to_xy_brightness(0, 0, 255, GAMUT)
def test_color_RGB_to_xy(self):
"""Test color_RGB_to_xy."""
assert (0, 0) == \
color_util.color_RGB_to_xy(0, 0, 0)
assert (0.323, 0.329) == \
color_util.color_RGB_to_xy(255, 255, 255)
def test_color_RGB_to_xy():
"""Test color_RGB_to_xy."""
assert color_util.color_RGB_to_xy(0, 0, 0) == (0, 0)
assert color_util.color_RGB_to_xy(255, 255, 255) == (0.323, 0.329)
assert (0.136, 0.04) == \
color_util.color_RGB_to_xy(0, 0, 255)
assert color_util.color_RGB_to_xy(0, 0, 255) == (0.136, 0.04)
assert (0.172, 0.747) == \
color_util.color_RGB_to_xy(0, 255, 0)
assert color_util.color_RGB_to_xy(0, 255, 0) == (0.172, 0.747)
assert (0.701, 0.299) == \
color_util.color_RGB_to_xy(255, 0, 0)
assert color_util.color_RGB_to_xy(255, 0, 0) == (0.701, 0.299)
assert (0.701, 0.299) == \
color_util.color_RGB_to_xy(128, 0, 0)
assert color_util.color_RGB_to_xy(128, 0, 0) == (0.701, 0.299)
assert (0.138, 0.08) == \
color_util.color_RGB_to_xy(0, 0, 255, GAMUT)
assert color_util.color_RGB_to_xy(0, 0, 255, GAMUT) == (0.138, 0.08)
assert (0.215, 0.711) == \
color_util.color_RGB_to_xy(0, 255, 0, GAMUT)
assert color_util.color_RGB_to_xy(0, 255, 0, GAMUT) == (0.215, 0.711)
assert (0.7, 0.299) == \
color_util.color_RGB_to_xy(255, 0, 0, GAMUT)
assert color_util.color_RGB_to_xy(255, 0, 0, GAMUT) == (0.7, 0.299)
def test_color_xy_brightness_to_RGB(self):
"""Test color_xy_brightness_to_RGB."""
assert (0, 0, 0) == \
color_util.color_xy_brightness_to_RGB(1, 1, 0)
assert (194, 186, 169) == \
color_util.color_xy_brightness_to_RGB(.35, .35, 128)
def test_color_xy_brightness_to_RGB():
"""Test color_xy_brightness_to_RGB."""
assert color_util.color_xy_brightness_to_RGB(1, 1, 0) == (0, 0, 0)
assert (255, 243, 222) == \
color_util.color_xy_brightness_to_RGB(.35, .35, 255)
assert color_util.color_xy_brightness_to_RGB(.35, .35, 128) == \
(194, 186, 169)
assert (255, 0, 60) == \
color_util.color_xy_brightness_to_RGB(1, 0, 255)
assert color_util.color_xy_brightness_to_RGB(.35, .35, 255) == \
(255, 243, 222)
assert (0, 255, 0) == \
color_util.color_xy_brightness_to_RGB(0, 1, 255)
assert color_util.color_xy_brightness_to_RGB(1, 0, 255) == (255, 0, 60)
assert (0, 63, 255) == \
color_util.color_xy_brightness_to_RGB(0, 0, 255)
assert color_util.color_xy_brightness_to_RGB(0, 1, 255) == (0, 255, 0)
assert (255, 0, 3) == \
color_util.color_xy_brightness_to_RGB(1, 0, 255, GAMUT)
assert color_util.color_xy_brightness_to_RGB(0, 0, 255) == (0, 63, 255)
assert (82, 255, 0) == \
color_util.color_xy_brightness_to_RGB(0, 1, 255, GAMUT)
assert color_util.color_xy_brightness_to_RGB(1, 0, 255, GAMUT) == \
(255, 0, 3)
assert (9, 85, 255) == \
color_util.color_xy_brightness_to_RGB(0, 0, 255, GAMUT)
assert color_util.color_xy_brightness_to_RGB(0, 1, 255, GAMUT) == \
(82, 255, 0)
def test_color_xy_to_RGB(self):
"""Test color_xy_to_RGB."""
assert (255, 243, 222) == \
color_util.color_xy_to_RGB(.35, .35)
assert color_util.color_xy_brightness_to_RGB(0, 0, 255, GAMUT) == \
(9, 85, 255)
assert (255, 0, 60) == \
color_util.color_xy_to_RGB(1, 0)
assert (0, 255, 0) == \
color_util.color_xy_to_RGB(0, 1)
def test_color_xy_to_RGB():
"""Test color_xy_to_RGB."""
assert color_util.color_xy_to_RGB(.35, .35) == (255, 243, 222)
assert (0, 63, 255) == \
color_util.color_xy_to_RGB(0, 0)
assert color_util.color_xy_to_RGB(1, 0) == (255, 0, 60)
assert (255, 0, 3) == \
color_util.color_xy_to_RGB(1, 0, GAMUT)
assert color_util.color_xy_to_RGB(0, 1) == (0, 255, 0)
assert (82, 255, 0) == \
color_util.color_xy_to_RGB(0, 1, GAMUT)
assert color_util.color_xy_to_RGB(0, 0) == (0, 63, 255)
assert (9, 85, 255) == \
color_util.color_xy_to_RGB(0, 0, GAMUT)
assert color_util.color_xy_to_RGB(1, 0, GAMUT) == (255, 0, 3)
def test_color_RGB_to_hsv(self):
"""Test color_RGB_to_hsv."""
assert (0, 0, 0) == \
color_util.color_RGB_to_hsv(0, 0, 0)
assert color_util.color_xy_to_RGB(0, 1, GAMUT) == (82, 255, 0)
assert (0, 0, 100) == \
color_util.color_RGB_to_hsv(255, 255, 255)
assert color_util.color_xy_to_RGB(0, 0, GAMUT) == (9, 85, 255)
assert (240, 100, 100) == \
color_util.color_RGB_to_hsv(0, 0, 255)
assert (120, 100, 100) == \
color_util.color_RGB_to_hsv(0, 255, 0)
def test_color_RGB_to_hsv():
"""Test color_RGB_to_hsv."""
assert color_util.color_RGB_to_hsv(0, 0, 0) == (0, 0, 0)
assert (0, 100, 100) == \
color_util.color_RGB_to_hsv(255, 0, 0)
assert color_util.color_RGB_to_hsv(255, 255, 255) == (0, 0, 100)
def test_color_hsv_to_RGB(self):
"""Test color_hsv_to_RGB."""
assert (0, 0, 0) == \
color_util.color_hsv_to_RGB(0, 0, 0)
assert color_util.color_RGB_to_hsv(0, 0, 255) == (240, 100, 100)
assert (255, 255, 255) == \
color_util.color_hsv_to_RGB(0, 0, 100)
assert color_util.color_RGB_to_hsv(0, 255, 0) == (120, 100, 100)
assert (0, 0, 255) == \
color_util.color_hsv_to_RGB(240, 100, 100)
assert color_util.color_RGB_to_hsv(255, 0, 0) == (0, 100, 100)
assert (0, 255, 0) == \
color_util.color_hsv_to_RGB(120, 100, 100)
assert (255, 0, 0) == \
color_util.color_hsv_to_RGB(0, 100, 100)
def test_color_hsv_to_RGB():
"""Test color_hsv_to_RGB."""
assert color_util.color_hsv_to_RGB(0, 0, 0) == (0, 0, 0)
def test_color_hsb_to_RGB(self):
"""Test color_hsb_to_RGB."""
assert (0, 0, 0) == \
color_util.color_hsb_to_RGB(0, 0, 0)
assert color_util.color_hsv_to_RGB(0, 0, 100) == (255, 255, 255)
assert (255, 255, 255) == \
color_util.color_hsb_to_RGB(0, 0, 1.0)
assert color_util.color_hsv_to_RGB(240, 100, 100) == (0, 0, 255)
assert (0, 0, 255) == \
color_util.color_hsb_to_RGB(240, 1.0, 1.0)
assert color_util.color_hsv_to_RGB(120, 100, 100) == (0, 255, 0)
assert (0, 255, 0) == \
color_util.color_hsb_to_RGB(120, 1.0, 1.0)
assert color_util.color_hsv_to_RGB(0, 100, 100) == (255, 0, 0)
assert (255, 0, 0) == \
color_util.color_hsb_to_RGB(0, 1.0, 1.0)
def test_color_xy_to_hs(self):
"""Test color_xy_to_hs."""
assert (47.294, 100) == \
color_util.color_xy_to_hs(1, 1)
def test_color_hsb_to_RGB():
"""Test color_hsb_to_RGB."""
assert color_util.color_hsb_to_RGB(0, 0, 0) == (0, 0, 0)
assert (38.182, 12.941) == \
color_util.color_xy_to_hs(.35, .35)
assert color_util.color_hsb_to_RGB(0, 0, 1.0) == (255, 255, 255)
assert (345.882, 100) == \
color_util.color_xy_to_hs(1, 0)
assert color_util.color_hsb_to_RGB(240, 1.0, 1.0) == (0, 0, 255)
assert (120, 100) == \
color_util.color_xy_to_hs(0, 1)
assert color_util.color_hsb_to_RGB(120, 1.0, 1.0) == (0, 255, 0)
assert (225.176, 100) == \
color_util.color_xy_to_hs(0, 0)
assert color_util.color_hsb_to_RGB(0, 1.0, 1.0) == (255, 0, 0)
assert (359.294, 100) == \
color_util.color_xy_to_hs(1, 0, GAMUT)
assert (100.706, 100) == \
color_util.color_xy_to_hs(0, 1, GAMUT)
def test_color_xy_to_hs():
"""Test color_xy_to_hs."""
assert color_util.color_xy_to_hs(1, 1) == (47.294, 100)
assert (221.463, 96.471) == \
color_util.color_xy_to_hs(0, 0, GAMUT)
assert color_util.color_xy_to_hs(.35, .35) == (38.182, 12.941)
def test_color_hs_to_xy(self):
"""Test color_hs_to_xy."""
assert (0.151, 0.343) == \
color_util.color_hs_to_xy(180, 100)
assert color_util.color_xy_to_hs(1, 0) == (345.882, 100)
assert (0.356, 0.321) == \
color_util.color_hs_to_xy(350, 12.5)
assert color_util.color_xy_to_hs(0, 1) == (120, 100)
assert (0.229, 0.474) == \
color_util.color_hs_to_xy(140, 50)
assert color_util.color_xy_to_hs(0, 0) == (225.176, 100)
assert (0.474, 0.317) == \
color_util.color_hs_to_xy(0, 40)
assert color_util.color_xy_to_hs(1, 0, GAMUT) == (359.294, 100)
assert (0.323, 0.329) == \
color_util.color_hs_to_xy(360, 0)
assert color_util.color_xy_to_hs(0, 1, GAMUT) == (100.706, 100)
assert (0.7, 0.299) == \
color_util.color_hs_to_xy(0, 100, GAMUT)
assert color_util.color_xy_to_hs(0, 0, GAMUT) == (221.463, 96.471)
assert (0.215, 0.711) == \
color_util.color_hs_to_xy(120, 100, GAMUT)
assert (0.17, 0.34) == \
color_util.color_hs_to_xy(180, 100, GAMUT)
def test_color_hs_to_xy():
"""Test color_hs_to_xy."""
assert color_util.color_hs_to_xy(180, 100) == (0.151, 0.343)
assert (0.138, 0.08) == \
color_util.color_hs_to_xy(240, 100, GAMUT)
assert color_util.color_hs_to_xy(350, 12.5) == (0.356, 0.321)
assert (0.7, 0.299) == \
color_util.color_hs_to_xy(360, 100, GAMUT)
assert color_util.color_hs_to_xy(140, 50) == (0.229, 0.474)
def test_rgb_hex_to_rgb_list(self):
"""Test rgb_hex_to_rgb_list."""
assert [255, 255, 255] == \
color_util.rgb_hex_to_rgb_list('ffffff')
assert color_util.color_hs_to_xy(0, 40) == (0.474, 0.317)
assert [0, 0, 0] == \
color_util.rgb_hex_to_rgb_list('000000')
assert color_util.color_hs_to_xy(360, 0) == (0.323, 0.329)
assert [255, 255, 255, 255] == \
color_util.rgb_hex_to_rgb_list('ffffffff')
assert color_util.color_hs_to_xy(0, 100, GAMUT) == (0.7, 0.299)
assert [0, 0, 0, 0] == \
color_util.rgb_hex_to_rgb_list('00000000')
assert color_util.color_hs_to_xy(120, 100, GAMUT) == (0.215, 0.711)
assert [51, 153, 255] == \
color_util.rgb_hex_to_rgb_list('3399ff')
assert color_util.color_hs_to_xy(180, 100, GAMUT) == (0.17, 0.34)
assert [51, 153, 255, 0] == \
color_util.rgb_hex_to_rgb_list('3399ff00')
assert color_util.color_hs_to_xy(240, 100, GAMUT) == (0.138, 0.08)
def test_color_name_to_rgb_valid_name(self):
"""Test color_name_to_rgb."""
assert (255, 0, 0) == \
color_util.color_name_to_rgb('red')
assert color_util.color_hs_to_xy(360, 100, GAMUT) == (0.7, 0.299)
assert (0, 0, 255) == \
color_util.color_name_to_rgb('blue')
assert (0, 128, 0) == \
color_util.color_name_to_rgb('green')
def test_rgb_hex_to_rgb_list():
"""Test rgb_hex_to_rgb_list."""
assert [255, 255, 255] == \
color_util.rgb_hex_to_rgb_list('ffffff')
# spaces in the name
assert (72, 61, 139) == \
color_util.color_name_to_rgb('dark slate blue')
assert [0, 0, 0] == \
color_util.rgb_hex_to_rgb_list('000000')
# spaces removed from name
assert (72, 61, 139) == \
color_util.color_name_to_rgb('darkslateblue')
assert (72, 61, 139) == \
color_util.color_name_to_rgb('dark slateblue')
assert (72, 61, 139) == \
color_util.color_name_to_rgb('darkslate blue')
assert [255, 255, 255, 255] == \
color_util.rgb_hex_to_rgb_list('ffffffff')
def test_color_name_to_rgb_unknown_name_raises_value_error(self):
"""Test color_name_to_rgb."""
with pytest.raises(ValueError):
color_util.color_name_to_rgb('not a color')
assert [0, 0, 0, 0] == \
color_util.rgb_hex_to_rgb_list('00000000')
def test_color_rgb_to_rgbw(self):
"""Test color_rgb_to_rgbw."""
assert (0, 0, 0, 0) == \
color_util.color_rgb_to_rgbw(0, 0, 0)
assert [51, 153, 255] == \
color_util.rgb_hex_to_rgb_list('3399ff')
assert (0, 0, 0, 255) == \
color_util.color_rgb_to_rgbw(255, 255, 255)
assert [51, 153, 255, 0] == \
color_util.rgb_hex_to_rgb_list('3399ff00')
assert (255, 0, 0, 0) == \
color_util.color_rgb_to_rgbw(255, 0, 0)
assert (0, 255, 0, 0) == \
color_util.color_rgb_to_rgbw(0, 255, 0)
def test_color_name_to_rgb_valid_name():
"""Test color_name_to_rgb."""
assert color_util.color_name_to_rgb('red') == (255, 0, 0)
assert (0, 0, 255, 0) == \
color_util.color_rgb_to_rgbw(0, 0, 255)
assert color_util.color_name_to_rgb('blue') == (0, 0, 255)
assert (255, 127, 0, 0) == \
color_util.color_rgb_to_rgbw(255, 127, 0)
assert color_util.color_name_to_rgb('green') == (0, 128, 0)
assert (255, 0, 0, 253) == \
color_util.color_rgb_to_rgbw(255, 127, 127)
# spaces in the name
assert color_util.color_name_to_rgb('dark slate blue') == (72, 61, 139)
assert (0, 0, 0, 127) == \
color_util.color_rgb_to_rgbw(127, 127, 127)
# spaces removed from name
assert color_util.color_name_to_rgb('darkslateblue') == (72, 61, 139)
assert color_util.color_name_to_rgb('dark slateblue') == (72, 61, 139)
assert color_util.color_name_to_rgb('darkslate blue') == (72, 61, 139)
def test_color_rgbw_to_rgb(self):
"""Test color_rgbw_to_rgb."""
assert (0, 0, 0) == \
color_util.color_rgbw_to_rgb(0, 0, 0, 0)
assert (255, 255, 255) == \
color_util.color_rgbw_to_rgb(0, 0, 0, 255)
def test_color_name_to_rgb_unknown_name_raises_value_error():
"""Test color_name_to_rgb."""
with pytest.raises(ValueError):
color_util.color_name_to_rgb('not a color')
assert (255, 0, 0) == \
color_util.color_rgbw_to_rgb(255, 0, 0, 0)
assert (0, 255, 0) == \
color_util.color_rgbw_to_rgb(0, 255, 0, 0)
def test_color_rgb_to_rgbw():
"""Test color_rgb_to_rgbw."""
assert color_util.color_rgb_to_rgbw(0, 0, 0) == (0, 0, 0, 0)
assert (0, 0, 255) == \
color_util.color_rgbw_to_rgb(0, 0, 255, 0)
assert color_util.color_rgb_to_rgbw(255, 255, 255) == (0, 0, 0, 255)
assert (255, 127, 0) == \
color_util.color_rgbw_to_rgb(255, 127, 0, 0)
assert color_util.color_rgb_to_rgbw(255, 0, 0) == (255, 0, 0, 0)
assert (255, 127, 127) == \
color_util.color_rgbw_to_rgb(255, 0, 0, 253)
assert color_util.color_rgb_to_rgbw(0, 255, 0) == (0, 255, 0, 0)
assert (127, 127, 127) == \
color_util.color_rgbw_to_rgb(0, 0, 0, 127)
assert color_util.color_rgb_to_rgbw(0, 0, 255) == (0, 0, 255, 0)
def test_color_rgb_to_hex(self):
"""Test color_rgb_to_hex."""
assert color_util.color_rgb_to_hex(255, 255, 255) == 'ffffff'
assert color_util.color_rgb_to_hex(0, 0, 0) == '000000'
assert color_util.color_rgb_to_hex(51, 153, 255) == '3399ff'
assert color_util.color_rgb_to_hex(255, 67.9204190, 0) == 'ff4400'
assert color_util.color_rgb_to_rgbw(255, 127, 0) == (255, 127, 0, 0)
def test_gamut(self):
"""Test gamut functions."""
assert color_util.check_valid_gamut(GAMUT)
assert not color_util.check_valid_gamut(GAMUT_INVALID_1)
assert not color_util.check_valid_gamut(GAMUT_INVALID_2)
assert not color_util.check_valid_gamut(GAMUT_INVALID_3)
assert not color_util.check_valid_gamut(GAMUT_INVALID_4)
assert color_util.color_rgb_to_rgbw(255, 127, 127) == (255, 0, 0, 253)
assert color_util.color_rgb_to_rgbw(127, 127, 127) == (0, 0, 0, 127)
class ColorTemperatureMiredToKelvinTests(unittest.TestCase):
"""Test color_temperature_mired_to_kelvin."""
def test_should_return_25000_kelvin_when_input_is_40_mired(self):
"""Function should return 25000K if given 40 mired."""
kelvin = color_util.color_temperature_mired_to_kelvin(40)
assert 25000 == kelvin
def test_color_rgbw_to_rgb():
"""Test color_rgbw_to_rgb."""
assert color_util.color_rgbw_to_rgb(0, 0, 0, 0) == (0, 0, 0)
def test_should_return_5000_kelvin_when_input_is_200_mired(self):
"""Function should return 5000K if given 200 mired."""
kelvin = color_util.color_temperature_mired_to_kelvin(200)
assert 5000 == kelvin
class ColorTemperatureKelvinToMiredTests(unittest.TestCase):
"""Test color_temperature_kelvin_to_mired."""
def test_should_return_40_mired_when_input_is_25000_kelvin(self):
"""Function should return 40 mired when given 25000 Kelvin."""
mired = color_util.color_temperature_kelvin_to_mired(25000)
assert 40 == mired
def test_should_return_200_mired_when_input_is_5000_kelvin(self):
"""Function should return 200 mired when given 5000 Kelvin."""
mired = color_util.color_temperature_kelvin_to_mired(5000)
assert 200 == mired
assert color_util.color_rgbw_to_rgb(0, 0, 0, 255) == (255, 255, 255)
assert color_util.color_rgbw_to_rgb(255, 0, 0, 0) == (255, 0, 0)
class ColorTemperatureToRGB(unittest.TestCase):
"""Test color_temperature_to_rgb."""
assert color_util.color_rgbw_to_rgb(0, 255, 0, 0) == (0, 255, 0)
def test_returns_same_value_for_any_two_temperatures_below_1000(self):
"""Function should return same value for 999 Kelvin and 0 Kelvin."""
rgb_1 = color_util.color_temperature_to_rgb(999)
rgb_2 = color_util.color_temperature_to_rgb(0)
assert rgb_1 == rgb_2
assert color_util.color_rgbw_to_rgb(0, 0, 255, 0) == (0, 0, 255)
def test_returns_same_value_for_any_two_temperatures_above_40000(self):
"""Function should return same value for 40001K and 999999K."""
rgb_1 = color_util.color_temperature_to_rgb(40001)
rgb_2 = color_util.color_temperature_to_rgb(999999)
assert rgb_1 == rgb_2
assert color_util.color_rgbw_to_rgb(255, 127, 0, 0) == (255, 127, 0)
def test_should_return_pure_white_at_6600(self):
"""
Function should return red=255, blue=255, green=255 when given 6600K.
assert color_util.color_rgbw_to_rgb(255, 0, 0, 253) == (255, 127, 127)
6600K is considered "pure white" light.
This is just a rough estimate because the formula itself is a "best
guess" approach.
"""
rgb = color_util.color_temperature_to_rgb(6600)
assert (255, 255, 255) == rgb
def test_color_above_6600_should_have_more_blue_than_red_or_green(self):
"""Function should return a higher blue value for blue-ish light."""
rgb = color_util.color_temperature_to_rgb(6700)
assert rgb[2] > rgb[1]
assert rgb[2] > rgb[0]
def test_color_below_6600_should_have_more_red_than_blue_or_green(self):
"""Function should return a higher red value for red-ish light."""
rgb = color_util.color_temperature_to_rgb(6500)
assert rgb[0] > rgb[1]
assert rgb[0] > rgb[2]
assert color_util.color_rgbw_to_rgb(0, 0, 0, 127) == (127, 127, 127)
def test_color_rgb_to_hex():
"""Test color_rgb_to_hex."""
assert color_util.color_rgb_to_hex(255, 255, 255) == 'ffffff'
assert color_util.color_rgb_to_hex(0, 0, 0) == '000000'
assert color_util.color_rgb_to_hex(51, 153, 255) == '3399ff'
assert color_util.color_rgb_to_hex(255, 67.9204190, 0) == 'ff4400'
def test_gamut():
"""Test gamut functions."""
assert color_util.check_valid_gamut(GAMUT)
assert not color_util.check_valid_gamut(GAMUT_INVALID_1)
assert not color_util.check_valid_gamut(GAMUT_INVALID_2)
assert not color_util.check_valid_gamut(GAMUT_INVALID_3)
assert not color_util.check_valid_gamut(GAMUT_INVALID_4)
def test_should_return_25000_kelvin_when_input_is_40_mired():
"""Function should return 25000K if given 40 mired."""
kelvin = color_util.color_temperature_mired_to_kelvin(40)
assert kelvin == 25000
def test_should_return_5000_kelvin_when_input_is_200_mired():
"""Function should return 5000K if given 200 mired."""
kelvin = color_util.color_temperature_mired_to_kelvin(200)
assert kelvin == 5000
def test_should_return_40_mired_when_input_is_25000_kelvin():
"""Function should return 40 mired when given 25000 Kelvin."""
mired = color_util.color_temperature_kelvin_to_mired(25000)
assert mired == 40
def test_should_return_200_mired_when_input_is_5000_kelvin():
"""Function should return 200 mired when given 5000 Kelvin."""
mired = color_util.color_temperature_kelvin_to_mired(5000)
assert mired == 200
def test_returns_same_value_for_any_two_temperatures_below_1000():
"""Function should return same value for 999 Kelvin and 0 Kelvin."""
rgb_1 = color_util.color_temperature_to_rgb(999)
rgb_2 = color_util.color_temperature_to_rgb(0)
assert rgb_1 == rgb_2
def test_returns_same_value_for_any_two_temperatures_above_40000():
"""Function should return same value for 40001K and 999999K."""
rgb_1 = color_util.color_temperature_to_rgb(40001)
rgb_2 = color_util.color_temperature_to_rgb(999999)
assert rgb_1 == rgb_2
def test_should_return_pure_white_at_6600():
"""
Function should return red=255, blue=255, green=255 when given 6600K.
6600K is considered "pure white" light.
This is just a rough estimate because the formula itself is a "best
guess" approach.
"""
rgb = color_util.color_temperature_to_rgb(6600)
assert (255, 255, 255) == rgb
def test_color_above_6600_should_have_more_blue_than_red_or_green():
"""Function should return a higher blue value for blue-ish light."""
rgb = color_util.color_temperature_to_rgb(6700)
assert rgb[2] > rgb[1]
assert rgb[2] > rgb[0]
def test_color_below_6600_should_have_more_red_than_blue_or_green():
"""Function should return a higher red value for red-ish light."""
rgb = color_util.color_temperature_to_rgb(6500)
assert rgb[0] > rgb[1]
assert rgb[0] > rgb[2]
def test_get_color_in_voluptuous():

View File

@ -1,79 +1,68 @@
"""Test homeassistant distance utility functions."""
import unittest
import pytest
import homeassistant.util.distance as distance_util
from homeassistant.const import (LENGTH_KILOMETERS, LENGTH_METERS, LENGTH_FEET,
LENGTH_MILES)
import pytest
INVALID_SYMBOL = 'bob'
VALID_SYMBOL = LENGTH_KILOMETERS
class TestDistanceUtil(unittest.TestCase):
"""Test the distance utility functions."""
def test_convert_same_unit():
"""Test conversion from any unit to same unit."""
assert distance_util.convert(5, LENGTH_KILOMETERS, LENGTH_KILOMETERS) == 5
assert distance_util.convert(2, LENGTH_METERS, LENGTH_METERS) == 2
assert distance_util.convert(10, LENGTH_MILES, LENGTH_MILES) == 10
assert distance_util.convert(9, LENGTH_FEET, LENGTH_FEET) == 9
def test_convert_same_unit(self):
"""Test conversion from any unit to same unit."""
assert 5 == distance_util.convert(5, LENGTH_KILOMETERS,
LENGTH_KILOMETERS)
assert 2 == distance_util.convert(2, LENGTH_METERS,
LENGTH_METERS)
assert 10 == distance_util.convert(10, LENGTH_MILES, LENGTH_MILES)
assert 9 == distance_util.convert(9, LENGTH_FEET, LENGTH_FEET)
def test_convert_invalid_unit(self):
"""Test exception is thrown for invalid units."""
with pytest.raises(ValueError):
distance_util.convert(5, INVALID_SYMBOL,
VALID_SYMBOL)
def test_convert_invalid_unit():
"""Test exception is thrown for invalid units."""
with pytest.raises(ValueError):
distance_util.convert(5, INVALID_SYMBOL, VALID_SYMBOL)
with pytest.raises(ValueError):
distance_util.convert(5, VALID_SYMBOL,
INVALID_SYMBOL)
with pytest.raises(ValueError):
distance_util.convert(5, VALID_SYMBOL, INVALID_SYMBOL)
def test_convert_nonnumeric_value(self):
"""Test exception is thrown for nonnumeric type."""
with pytest.raises(TypeError):
distance_util.convert('a', LENGTH_KILOMETERS, LENGTH_METERS)
def test_convert_from_miles(self):
"""Test conversion from miles to other units."""
miles = 5
assert distance_util.convert(
miles, LENGTH_MILES, LENGTH_KILOMETERS
) == 8.04672
assert distance_util.convert(miles, LENGTH_MILES, LENGTH_METERS) == \
8046.72
assert distance_util.convert(miles, LENGTH_MILES, LENGTH_FEET) == \
26400.0008448
def test_convert_nonnumeric_value():
"""Test exception is thrown for nonnumeric type."""
with pytest.raises(TypeError):
distance_util.convert('a', LENGTH_KILOMETERS, LENGTH_METERS)
def test_convert_from_feet(self):
"""Test conversion from feet to other units."""
feet = 5000
assert distance_util.convert(feet, LENGTH_FEET, LENGTH_KILOMETERS) == \
1.524
assert distance_util.convert(feet, LENGTH_FEET, LENGTH_METERS) == \
1524
assert distance_util.convert(feet, LENGTH_FEET, LENGTH_MILES) == \
0.9469694040000001
def test_convert_from_kilometers(self):
"""Test conversion from kilometers to other units."""
km = 5
assert distance_util.convert(km, LENGTH_KILOMETERS, LENGTH_FEET) == \
16404.2
assert distance_util.convert(km, LENGTH_KILOMETERS, LENGTH_METERS) == \
5000
assert distance_util.convert(km, LENGTH_KILOMETERS, LENGTH_MILES) == \
3.106855
def test_convert_from_miles():
"""Test conversion from miles to other units."""
miles = 5
assert distance_util.convert(miles, LENGTH_MILES, LENGTH_KILOMETERS) == \
8.04672
assert distance_util.convert(miles, LENGTH_MILES, LENGTH_METERS) == 8046.72
assert distance_util.convert(miles, LENGTH_MILES, LENGTH_FEET) == \
26400.0008448
def test_convert_from_meters(self):
"""Test conversion from meters to other units."""
m = 5000
assert distance_util.convert(m, LENGTH_METERS, LENGTH_FEET) == \
16404.2
assert distance_util.convert(m, LENGTH_METERS, LENGTH_KILOMETERS) == \
5
assert distance_util.convert(m, LENGTH_METERS, LENGTH_MILES) == \
3.106855
def test_convert_from_feet():
"""Test conversion from feet to other units."""
feet = 5000
assert distance_util.convert(feet, LENGTH_FEET, LENGTH_KILOMETERS) == 1.524
assert distance_util.convert(feet, LENGTH_FEET, LENGTH_METERS) == 1524
assert distance_util.convert(feet, LENGTH_FEET, LENGTH_MILES) == \
0.9469694040000001
def test_convert_from_kilometers():
"""Test conversion from kilometers to other units."""
km = 5
assert distance_util.convert(km, LENGTH_KILOMETERS, LENGTH_FEET) == 16404.2
assert distance_util.convert(km, LENGTH_KILOMETERS, LENGTH_METERS) == 5000
assert distance_util.convert(km, LENGTH_KILOMETERS, LENGTH_MILES) == \
3.106855
def test_convert_from_meters():
"""Test conversion from meters to other units."""
m = 5000
assert distance_util.convert(m, LENGTH_METERS, LENGTH_FEET) == 16404.2
assert distance_util.convert(m, LENGTH_METERS, LENGTH_KILOMETERS) == 5
assert distance_util.convert(m, LENGTH_METERS, LENGTH_MILES) == 3.106855

View File

@ -1,253 +1,266 @@
"""Test Home Assistant date util methods."""
import unittest
from datetime import datetime, timedelta
import homeassistant.util.dt as dt_util
import pytest
import homeassistant.util.dt as dt_util
DEFAULT_TIME_ZONE = dt_util.DEFAULT_TIME_ZONE
TEST_TIME_ZONE = 'America/Los_Angeles'
class TestDateUtil(unittest.TestCase):
"""Test util date methods."""
def teardown():
"""Stop everything that was started."""
dt_util.set_default_time_zone(DEFAULT_TIME_ZONE)
def setUp(self):
"""Set up the tests."""
self.orig_default_time_zone = dt_util.DEFAULT_TIME_ZONE
def tearDown(self):
"""Stop everything that was started."""
dt_util.set_default_time_zone(self.orig_default_time_zone)
def test_get_time_zone_retrieves_valid_time_zone():
"""Test getting a time zone."""
time_zone = dt_util.get_time_zone(TEST_TIME_ZONE)
def test_get_time_zone_retrieves_valid_time_zone(self):
"""Test getting a time zone."""
time_zone = dt_util.get_time_zone(TEST_TIME_ZONE)
assert time_zone is not None
assert TEST_TIME_ZONE == time_zone.zone
assert time_zone is not None
assert TEST_TIME_ZONE == time_zone.zone
def test_get_time_zone_returns_none_for_garbage_time_zone(self):
"""Test getting a non existing time zone."""
time_zone = dt_util.get_time_zone("Non existing time zone")
def test_get_time_zone_returns_none_for_garbage_time_zone():
"""Test getting a non existing time zone."""
time_zone = dt_util.get_time_zone("Non existing time zone")
assert time_zone is None
assert time_zone is None
def test_set_default_time_zone(self):
"""Test setting default time zone."""
time_zone = dt_util.get_time_zone(TEST_TIME_ZONE)
dt_util.set_default_time_zone(time_zone)
def test_set_default_time_zone():
"""Test setting default time zone."""
time_zone = dt_util.get_time_zone(TEST_TIME_ZONE)
# We cannot compare the timezones directly because of DST
assert time_zone.zone == dt_util.now().tzinfo.zone
dt_util.set_default_time_zone(time_zone)
def test_utcnow(self):
"""Test the UTC now method."""
assert abs(dt_util.utcnow().replace(tzinfo=None)-datetime.utcnow()) < \
timedelta(seconds=1)
# We cannot compare the timezones directly because of DST
assert time_zone.zone == dt_util.now().tzinfo.zone
def test_now(self):
"""Test the now method."""
dt_util.set_default_time_zone(dt_util.get_time_zone(TEST_TIME_ZONE))
assert abs(
dt_util.as_utc(dt_util.now()).replace(
tzinfo=None
) - datetime.utcnow()
) < timedelta(seconds=1)
def test_utcnow():
"""Test the UTC now method."""
assert abs(dt_util.utcnow().replace(tzinfo=None)-datetime.utcnow()) < \
timedelta(seconds=1)
def test_as_utc_with_naive_object(self):
"""Test the now method."""
utcnow = datetime.utcnow()
assert utcnow == dt_util.as_utc(utcnow).replace(tzinfo=None)
def test_now():
"""Test the now method."""
dt_util.set_default_time_zone(dt_util.get_time_zone(TEST_TIME_ZONE))
def test_as_utc_with_utc_object(self):
"""Test UTC time with UTC object."""
utcnow = dt_util.utcnow()
assert abs(
dt_util.as_utc(dt_util.now()).replace(
tzinfo=None
) - datetime.utcnow()
) < timedelta(seconds=1)
assert utcnow == dt_util.as_utc(utcnow)
def test_as_utc_with_local_object(self):
"""Test the UTC time with local object."""
dt_util.set_default_time_zone(dt_util.get_time_zone(TEST_TIME_ZONE))
localnow = dt_util.now()
utcnow = dt_util.as_utc(localnow)
def test_as_utc_with_naive_object():
"""Test the now method."""
utcnow = datetime.utcnow()
assert localnow == utcnow
assert localnow.tzinfo != utcnow.tzinfo
assert utcnow == dt_util.as_utc(utcnow).replace(tzinfo=None)
def test_as_local_with_naive_object(self):
"""Test local time with native object."""
now = dt_util.now()
assert abs(now-dt_util.as_local(datetime.utcnow())) < \
timedelta(seconds=1)
def test_as_local_with_local_object(self):
"""Test local with local object."""
now = dt_util.now()
assert now == now
def test_as_utc_with_utc_object():
"""Test UTC time with UTC object."""
utcnow = dt_util.utcnow()
def test_as_local_with_utc_object(self):
"""Test local time with UTC object."""
dt_util.set_default_time_zone(dt_util.get_time_zone(TEST_TIME_ZONE))
assert utcnow == dt_util.as_utc(utcnow)
utcnow = dt_util.utcnow()
localnow = dt_util.as_local(utcnow)
assert localnow == utcnow
assert localnow.tzinfo != utcnow.tzinfo
def test_as_utc_with_local_object():
"""Test the UTC time with local object."""
dt_util.set_default_time_zone(dt_util.get_time_zone(TEST_TIME_ZONE))
localnow = dt_util.now()
utcnow = dt_util.as_utc(localnow)
def test_utc_from_timestamp(self):
"""Test utc_from_timestamp method."""
assert datetime(1986, 7, 9, tzinfo=dt_util.UTC) == \
dt_util.utc_from_timestamp(521251200)
assert localnow == utcnow
assert localnow.tzinfo != utcnow.tzinfo
def test_as_timestamp(self):
"""Test as_timestamp method."""
ts = 1462401234
utc_dt = dt_util.utc_from_timestamp(ts)
assert ts == dt_util.as_timestamp(utc_dt)
utc_iso = utc_dt.isoformat()
assert ts == dt_util.as_timestamp(utc_iso)
# confirm the ability to handle a string passed in
delta = dt_util.as_timestamp("2016-01-01 12:12:12")
delta -= dt_util.as_timestamp("2016-01-01 12:12:11")
assert 1 == delta
def test_as_local_with_naive_object():
"""Test local time with native object."""
now = dt_util.now()
assert abs(now-dt_util.as_local(datetime.utcnow())) < \
timedelta(seconds=1)
def test_parse_datetime_converts_correctly(self):
"""Test parse_datetime converts strings."""
assert \
datetime(1986, 7, 9, 12, 0, 0, tzinfo=dt_util.UTC) == \
dt_util.parse_datetime("1986-07-09T12:00:00Z")
utcnow = dt_util.utcnow()
def test_as_local_with_local_object():
"""Test local with local object."""
now = dt_util.now()
assert now == now
assert utcnow == dt_util.parse_datetime(utcnow.isoformat())
def test_parse_datetime_returns_none_for_incorrect_format(self):
"""Test parse_datetime returns None if incorrect format."""
assert dt_util.parse_datetime("not a datetime string") is None
def test_as_local_with_utc_object():
"""Test local time with UTC object."""
dt_util.set_default_time_zone(dt_util.get_time_zone(TEST_TIME_ZONE))
def test_get_age(self):
"""Test get_age."""
diff = dt_util.now() - timedelta(seconds=0)
assert dt_util.get_age(diff) == "0 seconds"
utcnow = dt_util.utcnow()
localnow = dt_util.as_local(utcnow)
diff = dt_util.now() - timedelta(seconds=1)
assert dt_util.get_age(diff) == "1 second"
assert localnow == utcnow
assert localnow.tzinfo != utcnow.tzinfo
diff = dt_util.now() - timedelta(seconds=30)
assert dt_util.get_age(diff) == "30 seconds"
diff = dt_util.now() - timedelta(minutes=5)
assert dt_util.get_age(diff) == "5 minutes"
def test_utc_from_timestamp():
"""Test utc_from_timestamp method."""
assert datetime(1986, 7, 9, tzinfo=dt_util.UTC) == \
dt_util.utc_from_timestamp(521251200)
diff = dt_util.now() - timedelta(minutes=1)
assert dt_util.get_age(diff) == "1 minute"
diff = dt_util.now() - timedelta(minutes=300)
assert dt_util.get_age(diff) == "5 hours"
def test_as_timestamp():
"""Test as_timestamp method."""
ts = 1462401234
utc_dt = dt_util.utc_from_timestamp(ts)
assert ts == dt_util.as_timestamp(utc_dt)
utc_iso = utc_dt.isoformat()
assert ts == dt_util.as_timestamp(utc_iso)
diff = dt_util.now() - timedelta(minutes=320)
assert dt_util.get_age(diff) == "5 hours"
# confirm the ability to handle a string passed in
delta = dt_util.as_timestamp("2016-01-01 12:12:12")
delta -= dt_util.as_timestamp("2016-01-01 12:12:11")
assert delta == 1
diff = dt_util.now() - timedelta(minutes=2*60*24)
assert dt_util.get_age(diff) == "2 days"
diff = dt_util.now() - timedelta(minutes=32*60*24)
assert dt_util.get_age(diff) == "1 month"
def test_parse_datetime_converts_correctly():
"""Test parse_datetime converts strings."""
assert \
datetime(1986, 7, 9, 12, 0, 0, tzinfo=dt_util.UTC) == \
dt_util.parse_datetime("1986-07-09T12:00:00Z")
diff = dt_util.now() - timedelta(minutes=365*60*24)
assert dt_util.get_age(diff) == "1 year"
utcnow = dt_util.utcnow()
def test_parse_time_expression(self):
"""Test parse_time_expression."""
assert [x for x in range(60)] == \
dt_util.parse_time_expression('*', 0, 59)
assert [x for x in range(60)] == \
dt_util.parse_time_expression(None, 0, 59)
assert utcnow == dt_util.parse_datetime(utcnow.isoformat())
assert [x for x in range(0, 60, 5)] == \
dt_util.parse_time_expression('/5', 0, 59)
assert [1, 2, 3] == \
dt_util.parse_time_expression([2, 1, 3], 0, 59)
def test_parse_datetime_returns_none_for_incorrect_format():
"""Test parse_datetime returns None if incorrect format."""
assert dt_util.parse_datetime("not a datetime string") is None
assert [x for x in range(24)] == \
dt_util.parse_time_expression('*', 0, 23)
assert [42] == \
dt_util.parse_time_expression(42, 0, 59)
def test_get_age():
"""Test get_age."""
diff = dt_util.now() - timedelta(seconds=0)
assert dt_util.get_age(diff) == "0 seconds"
with pytest.raises(ValueError):
dt_util.parse_time_expression(61, 0, 60)
diff = dt_util.now() - timedelta(seconds=1)
assert dt_util.get_age(diff) == "1 second"
def test_find_next_time_expression_time_basic(self):
"""Test basic stuff for find_next_time_expression_time."""
def find(dt, hour, minute, second):
"""Call test_find_next_time_expression_time."""
seconds = dt_util.parse_time_expression(second, 0, 59)
minutes = dt_util.parse_time_expression(minute, 0, 59)
hours = dt_util.parse_time_expression(hour, 0, 23)
diff = dt_util.now() - timedelta(seconds=30)
assert dt_util.get_age(diff) == "30 seconds"
return dt_util.find_next_time_expression_time(
dt, seconds, minutes, hours)
diff = dt_util.now() - timedelta(minutes=5)
assert dt_util.get_age(diff) == "5 minutes"
assert datetime(2018, 10, 7, 10, 30, 0) == \
find(datetime(2018, 10, 7, 10, 20, 0), '*', '/30', 0)
diff = dt_util.now() - timedelta(minutes=1)
assert dt_util.get_age(diff) == "1 minute"
assert datetime(2018, 10, 7, 10, 30, 0) == \
find(datetime(2018, 10, 7, 10, 30, 0), '*', '/30', 0)
diff = dt_util.now() - timedelta(minutes=300)
assert dt_util.get_age(diff) == "5 hours"
assert datetime(2018, 10, 7, 12, 30, 30) == \
find(datetime(2018, 10, 7, 10, 30, 0), '/3', '/30', [30, 45])
diff = dt_util.now() - timedelta(minutes=320)
assert dt_util.get_age(diff) == "5 hours"
assert datetime(2018, 10, 8, 5, 0, 0) == \
find(datetime(2018, 10, 7, 10, 30, 0), 5, 0, 0)
diff = dt_util.now() - timedelta(minutes=2*60*24)
assert dt_util.get_age(diff) == "2 days"
def test_find_next_time_expression_time_dst(self):
"""Test daylight saving time for find_next_time_expression_time."""
tz = dt_util.get_time_zone('Europe/Vienna')
dt_util.set_default_time_zone(tz)
diff = dt_util.now() - timedelta(minutes=32*60*24)
assert dt_util.get_age(diff) == "1 month"
def find(dt, hour, minute, second):
"""Call test_find_next_time_expression_time."""
seconds = dt_util.parse_time_expression(second, 0, 59)
minutes = dt_util.parse_time_expression(minute, 0, 59)
hours = dt_util.parse_time_expression(hour, 0, 23)
diff = dt_util.now() - timedelta(minutes=365*60*24)
assert dt_util.get_age(diff) == "1 year"
return dt_util.find_next_time_expression_time(
dt, seconds, minutes, hours)
# Entering DST, clocks are rolled forward
assert tz.localize(datetime(2018, 3, 26, 2, 30, 0)) == \
find(tz.localize(datetime(2018, 3, 25, 1, 50, 0)), 2, 30, 0)
def test_parse_time_expression():
"""Test parse_time_expression."""
assert [x for x in range(60)] == \
dt_util.parse_time_expression('*', 0, 59)
assert [x for x in range(60)] == \
dt_util.parse_time_expression(None, 0, 59)
assert tz.localize(datetime(2018, 3, 26, 2, 30, 0)) == \
find(tz.localize(datetime(2018, 3, 25, 3, 50, 0)), 2, 30, 0)
assert [x for x in range(0, 60, 5)] == \
dt_util.parse_time_expression('/5', 0, 59)
assert tz.localize(datetime(2018, 3, 26, 2, 30, 0)) == \
find(tz.localize(datetime(2018, 3, 26, 1, 50, 0)), 2, 30, 0)
assert [1, 2, 3] == \
dt_util.parse_time_expression([2, 1, 3], 0, 59)
# Leaving DST, clocks are rolled back
assert tz.localize(datetime(2018, 10, 28, 2, 30, 0), is_dst=False) == \
find(tz.localize(datetime(2018, 10, 28, 2, 5, 0), is_dst=False),
2, 30, 0)
assert [x for x in range(24)] == \
dt_util.parse_time_expression('*', 0, 23)
assert tz.localize(datetime(2018, 10, 28, 2, 30, 0), is_dst=False) == \
find(tz.localize(datetime(2018, 10, 28, 2, 55, 0), is_dst=True),
2, 30, 0)
assert [42] == \
dt_util.parse_time_expression(42, 0, 59)
assert tz.localize(datetime(2018, 10, 28, 4, 30, 0), is_dst=False) == \
find(tz.localize(datetime(2018, 10, 28, 2, 55, 0), is_dst=True),
4, 30, 0)
with pytest.raises(ValueError):
dt_util.parse_time_expression(61, 0, 60)
assert tz.localize(datetime(2018, 10, 28, 2, 30, 0), is_dst=True) == \
find(tz.localize(datetime(2018, 10, 28, 2, 5, 0), is_dst=True),
2, 30, 0)
assert tz.localize(datetime(2018, 10, 29, 2, 30, 0)) == \
find(tz.localize(datetime(2018, 10, 28, 2, 55, 0), is_dst=False),
2, 30, 0)
def test_find_next_time_expression_time_basic():
"""Test basic stuff for find_next_time_expression_time."""
def find(dt, hour, minute, second):
"""Call test_find_next_time_expression_time."""
seconds = dt_util.parse_time_expression(second, 0, 59)
minutes = dt_util.parse_time_expression(minute, 0, 59)
hours = dt_util.parse_time_expression(hour, 0, 23)
return dt_util.find_next_time_expression_time(
dt, seconds, minutes, hours)
assert datetime(2018, 10, 7, 10, 30, 0) == \
find(datetime(2018, 10, 7, 10, 20, 0), '*', '/30', 0)
assert datetime(2018, 10, 7, 10, 30, 0) == \
find(datetime(2018, 10, 7, 10, 30, 0), '*', '/30', 0)
assert datetime(2018, 10, 7, 12, 30, 30) == \
find(datetime(2018, 10, 7, 10, 30, 0), '/3', '/30', [30, 45])
assert datetime(2018, 10, 8, 5, 0, 0) == \
find(datetime(2018, 10, 7, 10, 30, 0), 5, 0, 0)
def test_find_next_time_expression_time_dst():
"""Test daylight saving time for find_next_time_expression_time."""
tz = dt_util.get_time_zone('Europe/Vienna')
dt_util.set_default_time_zone(tz)
def find(dt, hour, minute, second):
"""Call test_find_next_time_expression_time."""
seconds = dt_util.parse_time_expression(second, 0, 59)
minutes = dt_util.parse_time_expression(minute, 0, 59)
hours = dt_util.parse_time_expression(hour, 0, 23)
return dt_util.find_next_time_expression_time(
dt, seconds, minutes, hours)
# Entering DST, clocks are rolled forward
assert tz.localize(datetime(2018, 3, 26, 2, 30, 0)) == \
find(tz.localize(datetime(2018, 3, 25, 1, 50, 0)), 2, 30, 0)
assert tz.localize(datetime(2018, 3, 26, 2, 30, 0)) == \
find(tz.localize(datetime(2018, 3, 25, 3, 50, 0)), 2, 30, 0)
assert tz.localize(datetime(2018, 3, 26, 2, 30, 0)) == \
find(tz.localize(datetime(2018, 3, 26, 1, 50, 0)), 2, 30, 0)
# Leaving DST, clocks are rolled back
assert tz.localize(datetime(2018, 10, 28, 2, 30, 0), is_dst=False) == \
find(tz.localize(datetime(2018, 10, 28, 2, 5, 0), is_dst=False),
2, 30, 0)
assert tz.localize(datetime(2018, 10, 28, 2, 30, 0), is_dst=False) == \
find(tz.localize(datetime(2018, 10, 28, 2, 55, 0), is_dst=True),
2, 30, 0)
assert tz.localize(datetime(2018, 10, 28, 4, 30, 0), is_dst=False) == \
find(tz.localize(datetime(2018, 10, 28, 2, 55, 0), is_dst=True),
4, 30, 0)
assert tz.localize(datetime(2018, 10, 28, 2, 30, 0), is_dst=True) == \
find(tz.localize(datetime(2018, 10, 28, 2, 5, 0), is_dst=True),
2, 30, 0)
assert tz.localize(datetime(2018, 10, 29, 2, 30, 0)) == \
find(tz.localize(datetime(2018, 10, 28, 2, 55, 0), is_dst=False),
2, 30, 0)

View File

@ -1,223 +1,228 @@
"""Test Home Assistant util methods."""
import unittest
from unittest.mock import patch, MagicMock
from datetime import datetime, timedelta
from homeassistant import util
import homeassistant.util.dt as dt_util
import pytest
from homeassistant import util
import homeassistant.util.dt as dt_util
class TestUtil(unittest.TestCase):
"""Test util methods."""
def test_sanitize_filename(self):
"""Test sanitize_filename."""
assert "test" == util.sanitize_filename("test")
assert "test" == util.sanitize_filename("/test")
assert "test" == util.sanitize_filename("..test")
assert "test" == util.sanitize_filename("\\test")
assert "test" == util.sanitize_filename("\\../test")
def test_sanitize_filename():
"""Test sanitize_filename."""
assert util.sanitize_filename("test") == 'test'
assert util.sanitize_filename("/test") == 'test'
assert util.sanitize_filename("..test") == 'test'
assert util.sanitize_filename("\\test") == 'test'
assert util.sanitize_filename("\\../test") == 'test'
def test_sanitize_path(self):
"""Test sanitize_path."""
assert "test/path" == util.sanitize_path("test/path")
assert "test/path" == util.sanitize_path("~test/path")
assert "//test/path" == util.sanitize_path("~/../test/path")
def test_slugify(self):
"""Test slugify."""
assert "t_est" == util.slugify("T-!@#$!#@$!$est")
assert "test_more" == util.slugify("Test More")
assert "test_more" == util.slugify("Test_(More)")
assert "test_more" == util.slugify("Tèst_Mörê")
assert "b8_27_eb_00_00_00" == util.slugify("B8:27:EB:00:00:00")
assert "test_com" == util.slugify("test.com")
assert "greg_phone_exp_wayp1" == \
util.slugify("greg_phone - exp_wayp1")
assert "we_are_we_are_a_test_calendar" == \
util.slugify("We are, we are, a... Test Calendar")
assert "test_aouss_aou" == util.slugify("Tèst_äöüß_ÄÖÜ")
assert "ying_shi_ma" == util.slugify("影師嗎")
assert "keihuonto" == util.slugify("けいふぉんと")
def test_sanitize_path():
"""Test sanitize_path."""
assert util.sanitize_path("test/path") == 'test/path'
assert util.sanitize_path("~test/path") == 'test/path'
assert util.sanitize_path("~/../test/path") == '//test/path'
def test_repr_helper(self):
"""Test repr_helper."""
assert "A" == util.repr_helper("A")
assert "5" == util.repr_helper(5)
assert "True" == util.repr_helper(True)
assert "test=1" == util.repr_helper({"test": 1})
assert "1986-07-09T12:00:00+00:00" == \
util.repr_helper(datetime(1986, 7, 9, 12, 0, 0))
def test_convert(self):
"""Test convert."""
assert 5 == util.convert("5", int)
assert 5.0 == util.convert("5", float)
assert util.convert("True", bool) is True
assert 1 == util.convert("NOT A NUMBER", int, 1)
assert 1 == util.convert(None, int, 1)
assert 1 == util.convert(object, int, 1)
def test_slugify():
"""Test slugify."""
assert util.slugify("T-!@#$!#@$!$est") == 't_est'
assert util.slugify("Test More") == 'test_more'
assert util.slugify("Test_(More)") == 'test_more'
assert util.slugify("Tèst_Mörê") == 'test_more'
assert util.slugify("B8:27:EB:00:00:00") == 'b8_27_eb_00_00_00'
assert util.slugify("test.com") == 'test_com'
assert util.slugify("greg_phone - exp_wayp1") == 'greg_phone_exp_wayp1'
assert util.slugify("We are, we are, a... Test Calendar") == \
'we_are_we_are_a_test_calendar'
assert util.slugify("Tèst_äöüß_ÄÖÜ") == 'test_aouss_aou'
assert util.slugify("影師嗎") == 'ying_shi_ma'
assert util.slugify("けいふぉんと") == 'keihuonto'
def test_ensure_unique_string(self):
"""Test ensure_unique_string."""
assert "Beer_3" == \
util.ensure_unique_string("Beer", ["Beer", "Beer_2"])
assert "Beer" == \
util.ensure_unique_string("Beer", ["Wine", "Soda"])
def test_ordered_enum(self):
"""Test the ordered enum class."""
class TestEnum(util.OrderedEnum):
"""Test enum that can be ordered."""
def test_repr_helper():
"""Test repr_helper."""
assert util.repr_helper("A") == 'A'
assert util.repr_helper(5) == '5'
assert util.repr_helper(True) == 'True'
assert util.repr_helper({"test": 1}) == 'test=1'
assert util.repr_helper(datetime(1986, 7, 9, 12, 0, 0)) == \
'1986-07-09T12:00:00+00:00'
FIRST = 1
SECOND = 2
THIRD = 3
assert TestEnum.SECOND >= TestEnum.FIRST
assert TestEnum.SECOND >= TestEnum.SECOND
assert not (TestEnum.SECOND >= TestEnum.THIRD)
def test_convert():
"""Test convert."""
assert util.convert("5", int) == 5
assert util.convert("5", float) == 5.0
assert util.convert("True", bool) is True
assert util.convert("NOT A NUMBER", int, 1) == 1
assert util.convert(None, int, 1) == 1
assert util.convert(object, int, 1) == 1
assert TestEnum.SECOND > TestEnum.FIRST
assert not (TestEnum.SECOND > TestEnum.SECOND)
assert not (TestEnum.SECOND > TestEnum.THIRD)
assert not (TestEnum.SECOND <= TestEnum.FIRST)
assert TestEnum.SECOND <= TestEnum.SECOND
assert TestEnum.SECOND <= TestEnum.THIRD
def test_ensure_unique_string():
"""Test ensure_unique_string."""
assert util.ensure_unique_string("Beer", ["Beer", "Beer_2"]) == 'Beer_3'
assert util.ensure_unique_string("Beer", ["Wine", "Soda"]) == 'Beer'
assert not (TestEnum.SECOND < TestEnum.FIRST)
assert not (TestEnum.SECOND < TestEnum.SECOND)
assert TestEnum.SECOND < TestEnum.THIRD
# Python will raise a TypeError if the <, <=, >, >= methods
# raise a NotImplemented error.
with pytest.raises(TypeError):
TestEnum.FIRST < 1
def test_ordered_enum():
"""Test the ordered enum class."""
class TestEnum(util.OrderedEnum):
"""Test enum that can be ordered."""
with pytest.raises(TypeError):
TestEnum.FIRST <= 1
FIRST = 1
SECOND = 2
THIRD = 3
with pytest.raises(TypeError):
TestEnum.FIRST > 1
assert TestEnum.SECOND >= TestEnum.FIRST
assert TestEnum.SECOND >= TestEnum.SECOND
assert TestEnum.SECOND < TestEnum.THIRD
with pytest.raises(TypeError):
TestEnum.FIRST >= 1
assert TestEnum.SECOND > TestEnum.FIRST
assert TestEnum.SECOND <= TestEnum.SECOND
assert TestEnum.SECOND <= TestEnum.THIRD
def test_throttle(self):
"""Test the add cooldown decorator."""
calls1 = []
calls2 = []
assert TestEnum.SECOND > TestEnum.FIRST
assert TestEnum.SECOND <= TestEnum.SECOND
assert TestEnum.SECOND <= TestEnum.THIRD
@util.Throttle(timedelta(seconds=4))
def test_throttle1():
calls1.append(1)
assert TestEnum.SECOND >= TestEnum.FIRST
assert TestEnum.SECOND >= TestEnum.SECOND
assert TestEnum.SECOND < TestEnum.THIRD
@util.Throttle(timedelta(seconds=4), timedelta(seconds=2))
def test_throttle2():
calls2.append(1)
# Python will raise a TypeError if the <, <=, >, >= methods
# raise a NotImplemented error.
with pytest.raises(TypeError):
TestEnum.FIRST < 1
now = dt_util.utcnow()
plus3 = now + timedelta(seconds=3)
plus5 = plus3 + timedelta(seconds=2)
with pytest.raises(TypeError):
TestEnum.FIRST <= 1
# Call first time and ensure methods got called
with pytest.raises(TypeError):
TestEnum.FIRST > 1
with pytest.raises(TypeError):
TestEnum.FIRST >= 1
def test_throttle():
"""Test the add cooldown decorator."""
calls1 = []
calls2 = []
@util.Throttle(timedelta(seconds=4))
def test_throttle1():
calls1.append(1)
@util.Throttle(timedelta(seconds=4), timedelta(seconds=2))
def test_throttle2():
calls2.append(1)
now = dt_util.utcnow()
plus3 = now + timedelta(seconds=3)
plus5 = plus3 + timedelta(seconds=2)
# Call first time and ensure methods got called
test_throttle1()
test_throttle2()
assert len(calls1) == 1
assert len(calls2) == 1
# Call second time. Methods should not get called
test_throttle1()
test_throttle2()
assert len(calls1) == 1
assert len(calls2) == 1
# Call again, overriding throttle, only first one should fire
test_throttle1(no_throttle=True)
test_throttle2(no_throttle=True)
assert len(calls1) == 2
assert len(calls2) == 1
with patch('homeassistant.util.utcnow', return_value=plus3):
test_throttle1()
test_throttle2()
assert 1 == len(calls1)
assert 1 == len(calls2)
assert len(calls1) == 2
assert len(calls2) == 1
# Call second time. Methods should not get called
with patch('homeassistant.util.utcnow', return_value=plus5):
test_throttle1()
test_throttle2()
assert 1 == len(calls1)
assert 1 == len(calls2)
assert len(calls1) == 3
assert len(calls2) == 2
# Call again, overriding throttle, only first one should fire
test_throttle1(no_throttle=True)
test_throttle2(no_throttle=True)
assert 2 == len(calls1)
assert 1 == len(calls2)
def test_throttle_per_instance():
"""Test that the throttle method is done per instance of a class."""
class Tester:
"""A tester class for the throttle."""
with patch('homeassistant.util.utcnow', return_value=plus3):
test_throttle1()
test_throttle2()
@util.Throttle(timedelta(seconds=1))
def hello(self):
"""Test the throttle."""
return True
assert 2 == len(calls1)
assert 1 == len(calls2)
assert Tester().hello()
assert Tester().hello()
with patch('homeassistant.util.utcnow', return_value=plus5):
test_throttle1()
test_throttle2()
assert 3 == len(calls1)
assert 2 == len(calls2)
def test_throttle_on_method():
"""Test that throttle works when wrapping a method."""
class Tester:
"""A tester class for the throttle."""
def test_throttle_per_instance(self):
"""Test that the throttle method is done per instance of a class."""
class Tester:
"""A tester class for the throttle."""
def hello(self):
"""Test the throttle."""
return True
@util.Throttle(timedelta(seconds=1))
def hello(self):
"""Test the throttle."""
return True
tester = Tester()
throttled = util.Throttle(timedelta(seconds=1))(tester.hello)
assert Tester().hello()
assert Tester().hello()
assert throttled()
assert throttled() is None
def test_throttle_on_method(self):
"""Test that throttle works when wrapping a method."""
class Tester:
"""A tester class for the throttle."""
def hello(self):
"""Test the throttle."""
return True
def test_throttle_on_two_method():
"""Test that throttle works when wrapping two methods."""
class Tester:
"""A test class for the throttle."""
tester = Tester()
throttled = util.Throttle(timedelta(seconds=1))(tester.hello)
@util.Throttle(timedelta(seconds=1))
def hello(self):
"""Test the throttle."""
return True
assert throttled()
assert throttled() is None
@util.Throttle(timedelta(seconds=1))
def goodbye(self):
"""Test the throttle."""
return True
def test_throttle_on_two_method(self):
"""Test that throttle works when wrapping two methods."""
class Tester:
"""A test class for the throttle."""
tester = Tester()
@util.Throttle(timedelta(seconds=1))
def hello(self):
"""Test the throttle."""
return True
assert tester.hello()
assert tester.goodbye()
@util.Throttle(timedelta(seconds=1))
def goodbye(self):
"""Test the throttle."""
return True
tester = Tester()
@patch.object(util, 'random')
def test_get_random_string(mock_random):
"""Test get random string."""
results = ['A', 'B', 'C']
assert tester.hello()
assert tester.goodbye()
def mock_choice(choices):
return results.pop(0)
@patch.object(util, 'random')
def test_get_random_string(self, mock_random):
"""Test get random string."""
results = ['A', 'B', 'C']
generator = MagicMock()
generator.choice.side_effect = mock_choice
mock_random.SystemRandom.return_value = generator
def mock_choice(choices):
return results.pop(0)
generator = MagicMock()
generator.choice.side_effect = mock_choice
mock_random.SystemRandom.return_value = generator
assert util.get_random_string(length=3) == 'ABC'
assert util.get_random_string(length=3) == 'ABC'
async def test_throttle_async():

View File

@ -2,15 +2,16 @@
from json import JSONEncoder
import os
import unittest
from unittest.mock import Mock
import sys
from tempfile import mkdtemp
import pytest
from homeassistant.util.json import (
SerializationError, load_json, save_json)
from homeassistant.exceptions import HomeAssistantError
import pytest
from unittest.mock import Mock
# Test data that can be saved as JSON
TEST_JSON_A = {"a": 1, "B": "two"}
@ -19,75 +20,82 @@ TEST_JSON_B = {"a": "one", "B": 2}
TEST_BAD_OBJECT = {("A",): 1}
# Test data that can not be loaded as JSON
TEST_BAD_SERIALIED = "THIS IS NOT JSON\n"
TMP_DIR = None
class TestJSON(unittest.TestCase):
"""Test util.json save and load."""
def setup():
"""Set up for tests."""
global TMP_DIR
TMP_DIR = mkdtemp()
def setUp(self):
"""Set up for tests."""
self.tmp_dir = mkdtemp()
def tearDown(self):
"""Clean up after tests."""
for fname in os.listdir(self.tmp_dir):
os.remove(os.path.join(self.tmp_dir, fname))
os.rmdir(self.tmp_dir)
def teardown():
"""Clean up after tests."""
for fname in os.listdir(TMP_DIR):
os.remove(os.path.join(TMP_DIR, fname))
os.rmdir(TMP_DIR)
def _path_for(self, leaf_name):
return os.path.join(self.tmp_dir, leaf_name+".json")
def test_save_and_load(self):
"""Test saving and loading back."""
fname = self._path_for("test1")
save_json(fname, TEST_JSON_A)
data = load_json(fname)
assert data == TEST_JSON_A
def _path_for(leaf_name):
return os.path.join(TMP_DIR, leaf_name+".json")
# Skipped on Windows
@unittest.skipIf(sys.platform.startswith('win'),
"private permissions not supported on Windows")
def test_save_and_load_private(self):
"""Test we can load private files and that they are protected."""
fname = self._path_for("test2")
save_json(fname, TEST_JSON_A, private=True)
data = load_json(fname)
assert data == TEST_JSON_A
stats = os.stat(fname)
assert stats.st_mode & 0o77 == 0
def test_overwrite_and_reload(self):
"""Test that we can overwrite an existing file and read back."""
fname = self._path_for("test3")
save_json(fname, TEST_JSON_A)
save_json(fname, TEST_JSON_B)
data = load_json(fname)
assert data == TEST_JSON_B
def test_save_and_load():
"""Test saving and loading back."""
fname = _path_for("test1")
save_json(fname, TEST_JSON_A)
data = load_json(fname)
assert data == TEST_JSON_A
def test_save_bad_data(self):
"""Test error from trying to save unserialisable data."""
fname = self._path_for("test4")
with pytest.raises(SerializationError):
save_json(fname, TEST_BAD_OBJECT)
def test_load_bad_data(self):
"""Test error from trying to load unserialisable data."""
fname = self._path_for("test5")
with open(fname, "w") as fh:
fh.write(TEST_BAD_SERIALIED)
with pytest.raises(HomeAssistantError):
load_json(fname)
# Skipped on Windows
@unittest.skipIf(sys.platform.startswith('win'),
"private permissions not supported on Windows")
def test_save_and_load_private():
"""Test we can load private files and that they are protected."""
fname = _path_for("test2")
save_json(fname, TEST_JSON_A, private=True)
data = load_json(fname)
assert data == TEST_JSON_A
stats = os.stat(fname)
assert stats.st_mode & 0o77 == 0
def test_custom_encoder(self):
"""Test serializing with a custom encoder."""
class MockJSONEncoder(JSONEncoder):
"""Mock JSON encoder."""
def default(self, o):
"""Mock JSON encode method."""
return "9"
def test_overwrite_and_reload():
"""Test that we can overwrite an existing file and read back."""
fname = _path_for("test3")
save_json(fname, TEST_JSON_A)
save_json(fname, TEST_JSON_B)
data = load_json(fname)
assert data == TEST_JSON_B
fname = self._path_for("test6")
save_json(fname, Mock(), encoder=MockJSONEncoder)
data = load_json(fname)
self.assertEqual(data, "9")
def test_save_bad_data():
"""Test error from trying to save unserialisable data."""
fname = _path_for("test4")
with pytest.raises(SerializationError):
save_json(fname, TEST_BAD_OBJECT)
def test_load_bad_data():
"""Test error from trying to load unserialisable data."""
fname = _path_for("test5")
with open(fname, "w") as fh:
fh.write(TEST_BAD_SERIALIED)
with pytest.raises(HomeAssistantError):
load_json(fname)
def test_custom_encoder():
"""Test serializing with a custom encoder."""
class MockJSONEncoder(JSONEncoder):
"""Mock JSON encoder."""
def default(self, o):
"""Mock JSON encode method."""
return "9"
fname = _path_for("test6")
save_json(fname, Mock(), encoder=MockJSONEncoder)
data = load_json(fname)
assert data == "9"

View File

@ -1,5 +1,4 @@
"""Test homeassistant pressure utility functions."""
import unittest
import pytest
from homeassistant.const import (PRESSURE_PA, PRESSURE_HPA, PRESSURE_MBAR,
@ -10,57 +9,50 @@ INVALID_SYMBOL = 'bob'
VALID_SYMBOL = PRESSURE_PA
class TestPressureUtil(unittest.TestCase):
"""Test the pressure utility functions."""
def test_convert_same_unit():
"""Test conversion from any unit to same unit."""
assert pressure_util.convert(2, PRESSURE_PA, PRESSURE_PA) == 2
assert pressure_util.convert(3, PRESSURE_HPA, PRESSURE_HPA) == 3
assert pressure_util.convert(4, PRESSURE_MBAR, PRESSURE_MBAR) == 4
assert pressure_util.convert(5, PRESSURE_INHG, PRESSURE_INHG) == 5
def test_convert_same_unit(self):
"""Test conversion from any unit to same unit."""
assert pressure_util.convert(2, PRESSURE_PA, PRESSURE_PA) == 2
assert pressure_util.convert(3, PRESSURE_HPA, PRESSURE_HPA) == 3
assert pressure_util.convert(4, PRESSURE_MBAR, PRESSURE_MBAR) == 4
assert pressure_util.convert(5, PRESSURE_INHG, PRESSURE_INHG) == 5
def test_convert_invalid_unit(self):
"""Test exception is thrown for invalid units."""
with pytest.raises(ValueError):
pressure_util.convert(5, INVALID_SYMBOL, VALID_SYMBOL)
def test_convert_invalid_unit():
"""Test exception is thrown for invalid units."""
with pytest.raises(ValueError):
pressure_util.convert(5, INVALID_SYMBOL, VALID_SYMBOL)
with pytest.raises(ValueError):
pressure_util.convert(5, VALID_SYMBOL, INVALID_SYMBOL)
with pytest.raises(ValueError):
pressure_util.convert(5, VALID_SYMBOL, INVALID_SYMBOL)
def test_convert_nonnumeric_value(self):
"""Test exception is thrown for nonnumeric type."""
with pytest.raises(TypeError):
pressure_util.convert('a', PRESSURE_HPA, PRESSURE_INHG)
def test_convert_from_hpascals(self):
"""Test conversion from hPA to other units."""
hpascals = 1000
self.assertAlmostEqual(
pressure_util.convert(hpascals, PRESSURE_HPA, PRESSURE_PSI),
14.5037743897)
self.assertAlmostEqual(
pressure_util.convert(hpascals, PRESSURE_HPA, PRESSURE_INHG),
29.5299801647)
self.assertAlmostEqual(
pressure_util.convert(hpascals, PRESSURE_HPA, PRESSURE_PA),
100000)
self.assertAlmostEqual(
pressure_util.convert(hpascals, PRESSURE_HPA, PRESSURE_MBAR),
1000)
def test_convert_nonnumeric_value():
"""Test exception is thrown for nonnumeric type."""
with pytest.raises(TypeError):
pressure_util.convert('a', PRESSURE_HPA, PRESSURE_INHG)
def test_convert_from_inhg(self):
"""Test conversion from inHg to other units."""
inhg = 30
self.assertAlmostEqual(
pressure_util.convert(inhg, PRESSURE_INHG, PRESSURE_PSI),
14.7346266155)
self.assertAlmostEqual(
pressure_util.convert(inhg, PRESSURE_INHG, PRESSURE_HPA),
1015.9167)
self.assertAlmostEqual(
pressure_util.convert(inhg, PRESSURE_INHG, PRESSURE_PA),
101591.67)
self.assertAlmostEqual(
pressure_util.convert(inhg, PRESSURE_INHG, PRESSURE_MBAR),
1015.9167)
def test_convert_from_hpascals():
"""Test conversion from hPA to other units."""
hpascals = 1000
assert pressure_util.convert(hpascals, PRESSURE_HPA, PRESSURE_PSI) == \
pytest.approx(14.5037743897)
assert pressure_util.convert(hpascals, PRESSURE_HPA, PRESSURE_INHG) == \
pytest.approx(29.5299801647)
assert pressure_util.convert(hpascals, PRESSURE_HPA, PRESSURE_PA) == \
pytest.approx(100000)
assert pressure_util.convert(hpascals, PRESSURE_HPA, PRESSURE_MBAR) == \
pytest.approx(1000)
def test_convert_from_inhg():
"""Test conversion from inHg to other units."""
inhg = 30
assert pressure_util.convert(inhg, PRESSURE_INHG, PRESSURE_PSI) == \
pytest.approx(14.7346266155)
assert pressure_util.convert(inhg, PRESSURE_INHG, PRESSURE_HPA) == \
pytest.approx(1015.9167)
assert pressure_util.convert(inhg, PRESSURE_INHG, PRESSURE_PA) == \
pytest.approx(101591.67)
assert pressure_util.convert(inhg, PRESSURE_INHG, PRESSURE_MBAR) == \
pytest.approx(1015.9167)

View File

@ -1,6 +1,5 @@
"""Test Home Assistant ruamel.yaml loader."""
import os
import unittest
from tempfile import mkdtemp
import pytest
@ -114,45 +113,51 @@ views:
cards: !include cards.yaml
"""
TMP_DIR = None
class TestYAML(unittest.TestCase):
"""Test lovelace.yaml save and load."""
def setUp(self):
"""Set up for tests."""
self.tmp_dir = mkdtemp()
self.yaml = YAML(typ='rt')
def setup():
"""Set up for tests."""
global TMP_DIR
TMP_DIR = mkdtemp()
def tearDown(self):
"""Clean up after tests."""
for fname in os.listdir(self.tmp_dir):
os.remove(os.path.join(self.tmp_dir, fname))
os.rmdir(self.tmp_dir)
def _path_for(self, leaf_name):
return os.path.join(self.tmp_dir, leaf_name+".yaml")
def teardown():
"""Clean up after tests."""
for fname in os.listdir(TMP_DIR):
os.remove(os.path.join(TMP_DIR, fname))
os.rmdir(TMP_DIR)
def test_save_and_load(self):
"""Test saving and loading back."""
fname = self._path_for("test1")
open(fname, "w+").close()
util_yaml.save_yaml(fname, self.yaml.load(TEST_YAML_A))
data = util_yaml.load_yaml(fname, True)
assert data == self.yaml.load(TEST_YAML_A)
def test_overwrite_and_reload(self):
"""Test that we can overwrite an existing file and read back."""
fname = self._path_for("test2")
open(fname, "w+").close()
util_yaml.save_yaml(fname, self.yaml.load(TEST_YAML_A))
util_yaml.save_yaml(fname, self.yaml.load(TEST_YAML_B))
data = util_yaml.load_yaml(fname, True)
assert data == self.yaml.load(TEST_YAML_B)
def _path_for(leaf_name):
return os.path.join(TMP_DIR, leaf_name+".yaml")
def test_load_bad_data(self):
"""Test error from trying to load unserialisable data."""
fname = self._path_for("test3")
with open(fname, "w") as fh:
fh.write(TEST_BAD_YAML)
with pytest.raises(HomeAssistantError):
util_yaml.load_yaml(fname, True)
def test_save_and_load():
"""Test saving and loading back."""
yaml = YAML(typ='rt')
fname = _path_for("test1")
open(fname, "w+").close()
util_yaml.save_yaml(fname, yaml.load(TEST_YAML_A))
data = util_yaml.load_yaml(fname, True)
assert data == yaml.load(TEST_YAML_A)
def test_overwrite_and_reload():
"""Test that we can overwrite an existing file and read back."""
yaml = YAML(typ='rt')
fname = _path_for("test2")
open(fname, "w+").close()
util_yaml.save_yaml(fname, yaml.load(TEST_YAML_A))
util_yaml.save_yaml(fname, yaml.load(TEST_YAML_B))
data = util_yaml.load_yaml(fname, True)
assert data == yaml.load(TEST_YAML_B)
def test_load_bad_data():
"""Test error from trying to load unserialisable data."""
fname = _path_for("test3")
with open(fname, "w") as fh:
fh.write(TEST_BAD_YAML)
with pytest.raises(HomeAssistantError):
util_yaml.load_yaml(fname, True)

View File

@ -1,5 +1,5 @@
"""Test the unit system helper."""
import unittest
import pytest
from homeassistant.util.unit_system import (
UnitSystem,
@ -19,141 +19,138 @@ from homeassistant.const import (
TEMPERATURE,
VOLUME
)
import pytest
SYSTEM_NAME = 'TEST'
INVALID_UNIT = 'INVALID'
class TestUnitSystem(unittest.TestCase):
"""Test the unit system helper."""
def test_invalid_units():
"""Test errors are raised when invalid units are passed in."""
with pytest.raises(ValueError):
UnitSystem(SYSTEM_NAME, INVALID_UNIT, LENGTH_METERS, VOLUME_LITERS,
MASS_GRAMS, PRESSURE_PA)
def test_invalid_units(self):
"""Test errors are raised when invalid units are passed in."""
with pytest.raises(ValueError):
UnitSystem(SYSTEM_NAME, INVALID_UNIT, LENGTH_METERS, VOLUME_LITERS,
MASS_GRAMS, PRESSURE_PA)
with pytest.raises(ValueError):
UnitSystem(SYSTEM_NAME, TEMP_CELSIUS, INVALID_UNIT, VOLUME_LITERS,
MASS_GRAMS, PRESSURE_PA)
with pytest.raises(ValueError):
UnitSystem(SYSTEM_NAME, TEMP_CELSIUS, INVALID_UNIT, VOLUME_LITERS,
MASS_GRAMS, PRESSURE_PA)
with pytest.raises(ValueError):
UnitSystem(SYSTEM_NAME, TEMP_CELSIUS, LENGTH_METERS, INVALID_UNIT,
MASS_GRAMS, PRESSURE_PA)
with pytest.raises(ValueError):
UnitSystem(SYSTEM_NAME, TEMP_CELSIUS, LENGTH_METERS, INVALID_UNIT,
MASS_GRAMS, PRESSURE_PA)
with pytest.raises(ValueError):
UnitSystem(SYSTEM_NAME, TEMP_CELSIUS, LENGTH_METERS, VOLUME_LITERS,
INVALID_UNIT, PRESSURE_PA)
with pytest.raises(ValueError):
UnitSystem(SYSTEM_NAME, TEMP_CELSIUS, LENGTH_METERS, VOLUME_LITERS,
INVALID_UNIT, PRESSURE_PA)
with pytest.raises(ValueError):
UnitSystem(SYSTEM_NAME, TEMP_CELSIUS, LENGTH_METERS, VOLUME_LITERS,
MASS_GRAMS, INVALID_UNIT)
with pytest.raises(ValueError):
UnitSystem(SYSTEM_NAME, TEMP_CELSIUS, LENGTH_METERS, VOLUME_LITERS,
MASS_GRAMS, INVALID_UNIT)
def test_invalid_value(self):
"""Test no conversion happens if value is non-numeric."""
with pytest.raises(TypeError):
METRIC_SYSTEM.length('25a', LENGTH_KILOMETERS)
with pytest.raises(TypeError):
METRIC_SYSTEM.temperature('50K', TEMP_CELSIUS)
with pytest.raises(TypeError):
METRIC_SYSTEM.volume('50L', VOLUME_LITERS)
with pytest.raises(TypeError):
METRIC_SYSTEM.pressure('50Pa', PRESSURE_PA)
def test_invalid_value():
"""Test no conversion happens if value is non-numeric."""
with pytest.raises(TypeError):
METRIC_SYSTEM.length('25a', LENGTH_KILOMETERS)
with pytest.raises(TypeError):
METRIC_SYSTEM.temperature('50K', TEMP_CELSIUS)
with pytest.raises(TypeError):
METRIC_SYSTEM.volume('50L', VOLUME_LITERS)
with pytest.raises(TypeError):
METRIC_SYSTEM.pressure('50Pa', PRESSURE_PA)
def test_as_dict(self):
"""Test that the as_dict() method returns the expected dictionary."""
expected = {
LENGTH: LENGTH_KILOMETERS,
TEMPERATURE: TEMP_CELSIUS,
VOLUME: VOLUME_LITERS,
MASS: MASS_GRAMS,
PRESSURE: PRESSURE_PA
}
assert expected == METRIC_SYSTEM.as_dict()
def test_as_dict():
"""Test that the as_dict() method returns the expected dictionary."""
expected = {
LENGTH: LENGTH_KILOMETERS,
TEMPERATURE: TEMP_CELSIUS,
VOLUME: VOLUME_LITERS,
MASS: MASS_GRAMS,
PRESSURE: PRESSURE_PA
}
def test_temperature_same_unit(self):
"""Test no conversion happens if to unit is same as from unit."""
assert 5 == \
METRIC_SYSTEM.temperature(5,
METRIC_SYSTEM.temperature_unit)
assert expected == METRIC_SYSTEM.as_dict()
def test_temperature_unknown_unit(self):
"""Test no conversion happens if unknown unit."""
with pytest.raises(ValueError):
METRIC_SYSTEM.temperature(5, 'K')
def test_temperature_to_metric(self):
"""Test temperature conversion to metric system."""
assert 25 == \
METRIC_SYSTEM.temperature(25, METRIC_SYSTEM.temperature_unit)
assert 26.7 == \
round(METRIC_SYSTEM.temperature(
80, IMPERIAL_SYSTEM.temperature_unit), 1)
def test_temperature_same_unit():
"""Test no conversion happens if to unit is same as from unit."""
assert METRIC_SYSTEM.temperature(5, METRIC_SYSTEM.temperature_unit) == 5
def test_temperature_to_imperial(self):
"""Test temperature conversion to imperial system."""
assert 77 == \
IMPERIAL_SYSTEM.temperature(77, IMPERIAL_SYSTEM.temperature_unit)
assert 77 == \
IMPERIAL_SYSTEM.temperature(25, METRIC_SYSTEM.temperature_unit)
def test_length_unknown_unit(self):
"""Test length conversion with unknown from unit."""
with pytest.raises(ValueError):
METRIC_SYSTEM.length(5, 'fr')
def test_temperature_unknown_unit():
"""Test no conversion happens if unknown unit."""
with pytest.raises(ValueError):
METRIC_SYSTEM.temperature(5, 'K')
def test_length_to_metric(self):
"""Test length conversion to metric system."""
assert 100 == \
METRIC_SYSTEM.length(100, METRIC_SYSTEM.length_unit)
assert 8.04672 == \
METRIC_SYSTEM.length(5, IMPERIAL_SYSTEM.length_unit)
def test_length_to_imperial(self):
"""Test length conversion to imperial system."""
assert 100 == \
IMPERIAL_SYSTEM.length(100,
IMPERIAL_SYSTEM.length_unit)
assert 3.106855 == \
IMPERIAL_SYSTEM.length(5, METRIC_SYSTEM.length_unit)
def test_temperature_to_metric():
"""Test temperature conversion to metric system."""
assert METRIC_SYSTEM.temperature(25, METRIC_SYSTEM.temperature_unit) == 25
assert round(METRIC_SYSTEM.temperature(
80, IMPERIAL_SYSTEM.temperature_unit), 1) == 26.7
def test_pressure_same_unit(self):
"""Test no conversion happens if to unit is same as from unit."""
assert 5 == \
METRIC_SYSTEM.pressure(5, METRIC_SYSTEM.pressure_unit)
def test_pressure_unknown_unit(self):
"""Test no conversion happens if unknown unit."""
with pytest.raises(ValueError):
METRIC_SYSTEM.pressure(5, 'K')
def test_temperature_to_imperial():
"""Test temperature conversion to imperial system."""
assert IMPERIAL_SYSTEM.temperature(
77, IMPERIAL_SYSTEM.temperature_unit) == 77
assert IMPERIAL_SYSTEM.temperature(
25, METRIC_SYSTEM.temperature_unit) == 77
def test_pressure_to_metric(self):
"""Test pressure conversion to metric system."""
assert 25 == \
METRIC_SYSTEM.pressure(25, METRIC_SYSTEM.pressure_unit)
self.assertAlmostEqual(
METRIC_SYSTEM.pressure(14.7, IMPERIAL_SYSTEM.pressure_unit),
101352.932, places=1)
def test_pressure_to_imperial(self):
"""Test pressure conversion to imperial system."""
assert 77 == \
IMPERIAL_SYSTEM.pressure(77, IMPERIAL_SYSTEM.pressure_unit)
self.assertAlmostEqual(
IMPERIAL_SYSTEM.pressure(101352.932, METRIC_SYSTEM.pressure_unit),
14.7, places=4)
def test_length_unknown_unit():
"""Test length conversion with unknown from unit."""
with pytest.raises(ValueError):
METRIC_SYSTEM.length(5, 'fr')
def test_properties(self):
"""Test the unit properties are returned as expected."""
assert LENGTH_KILOMETERS == METRIC_SYSTEM.length_unit
assert TEMP_CELSIUS == METRIC_SYSTEM.temperature_unit
assert MASS_GRAMS == METRIC_SYSTEM.mass_unit
assert VOLUME_LITERS == METRIC_SYSTEM.volume_unit
assert PRESSURE_PA == METRIC_SYSTEM.pressure_unit
def test_is_metric(self):
"""Test the is metric flag."""
assert METRIC_SYSTEM.is_metric
assert not IMPERIAL_SYSTEM.is_metric
def test_length_to_metric():
"""Test length conversion to metric system."""
assert METRIC_SYSTEM.length(100, METRIC_SYSTEM.length_unit) == 100
assert METRIC_SYSTEM.length(5, IMPERIAL_SYSTEM.length_unit) == 8.04672
def test_length_to_imperial():
"""Test length conversion to imperial system."""
assert IMPERIAL_SYSTEM.length(100, IMPERIAL_SYSTEM.length_unit) == 100
assert IMPERIAL_SYSTEM.length(5, METRIC_SYSTEM.length_unit) == 3.106855
def test_pressure_same_unit():
"""Test no conversion happens if to unit is same as from unit."""
assert METRIC_SYSTEM.pressure(5, METRIC_SYSTEM.pressure_unit) == 5
def test_pressure_unknown_unit():
"""Test no conversion happens if unknown unit."""
with pytest.raises(ValueError):
METRIC_SYSTEM.pressure(5, 'K')
def test_pressure_to_metric():
"""Test pressure conversion to metric system."""
assert METRIC_SYSTEM.pressure(25, METRIC_SYSTEM.pressure_unit) == 25
assert METRIC_SYSTEM.pressure(14.7, IMPERIAL_SYSTEM.pressure_unit) == \
pytest.approx(101352.932, abs=1e-1)
def test_pressure_to_imperial():
"""Test pressure conversion to imperial system."""
assert IMPERIAL_SYSTEM.pressure(77, IMPERIAL_SYSTEM.pressure_unit) == 77
assert IMPERIAL_SYSTEM.pressure(
101352.932, METRIC_SYSTEM.pressure_unit) == \
pytest.approx(14.7, abs=1e-4)
def test_properties():
"""Test the unit properties are returned as expected."""
assert LENGTH_KILOMETERS == METRIC_SYSTEM.length_unit
assert TEMP_CELSIUS == METRIC_SYSTEM.temperature_unit
assert MASS_GRAMS == METRIC_SYSTEM.mass_unit
assert VOLUME_LITERS == METRIC_SYSTEM.volume_unit
assert PRESSURE_PA == METRIC_SYSTEM.pressure_unit
def test_is_metric():
"""Test the is metric flag."""
assert METRIC_SYSTEM.is_metric
assert not IMPERIAL_SYSTEM.is_metric

View File

@ -1,49 +1,45 @@
"""Test homeassistant volume utility functions."""
import unittest
import pytest
import homeassistant.util.volume as volume_util
from homeassistant.const import (VOLUME_LITERS, VOLUME_MILLILITERS,
VOLUME_GALLONS, VOLUME_FLUID_OUNCE)
import pytest
INVALID_SYMBOL = 'bob'
VALID_SYMBOL = VOLUME_LITERS
class TestVolumeUtil(unittest.TestCase):
"""Test the volume utility functions."""
def test_convert_same_unit():
"""Test conversion from any unit to same unit."""
assert volume_util.convert(2, VOLUME_LITERS, VOLUME_LITERS) == 2
assert volume_util.convert(3, VOLUME_MILLILITERS, VOLUME_MILLILITERS) == 3
assert volume_util.convert(4, VOLUME_GALLONS, VOLUME_GALLONS) == 4
assert volume_util.convert(5, VOLUME_FLUID_OUNCE, VOLUME_FLUID_OUNCE) == 5
def test_convert_same_unit(self):
"""Test conversion from any unit to same unit."""
assert 2 == volume_util.convert(2, VOLUME_LITERS, VOLUME_LITERS)
assert 3 == volume_util.convert(3, VOLUME_MILLILITERS,
VOLUME_MILLILITERS)
assert 4 == volume_util.convert(4, VOLUME_GALLONS,
VOLUME_GALLONS)
assert 5 == volume_util.convert(5, VOLUME_FLUID_OUNCE,
VOLUME_FLUID_OUNCE)
def test_convert_invalid_unit(self):
"""Test exception is thrown for invalid units."""
with pytest.raises(ValueError):
volume_util.convert(5, INVALID_SYMBOL, VALID_SYMBOL)
def test_convert_invalid_unit():
"""Test exception is thrown for invalid units."""
with pytest.raises(ValueError):
volume_util.convert(5, INVALID_SYMBOL, VALID_SYMBOL)
with pytest.raises(ValueError):
volume_util.convert(5, VALID_SYMBOL, INVALID_SYMBOL)
with pytest.raises(ValueError):
volume_util.convert(5, VALID_SYMBOL, INVALID_SYMBOL)
def test_convert_nonnumeric_value(self):
"""Test exception is thrown for nonnumeric type."""
with pytest.raises(TypeError):
volume_util.convert('a', VOLUME_GALLONS, VOLUME_LITERS)
def test_convert_from_liters(self):
"""Test conversion from liters to other units."""
liters = 5
assert volume_util.convert(liters, VOLUME_LITERS,
VOLUME_GALLONS) == 1.321
def test_convert_nonnumeric_value():
"""Test exception is thrown for nonnumeric type."""
with pytest.raises(TypeError):
volume_util.convert('a', VOLUME_GALLONS, VOLUME_LITERS)
def test_convert_from_gallons(self):
"""Test conversion from gallons to other units."""
gallons = 5
assert volume_util.convert(gallons, VOLUME_GALLONS,
VOLUME_LITERS) == 18.925
def test_convert_from_liters():
"""Test conversion from liters to other units."""
liters = 5
assert volume_util.convert(liters, VOLUME_LITERS, VOLUME_GALLONS) == 1.321
def test_convert_from_gallons():
"""Test conversion from gallons to other units."""
gallons = 5
assert volume_util.convert(gallons, VOLUME_GALLONS,
VOLUME_LITERS) == 18.925

View File

@ -21,256 +21,269 @@ def mock_credstash():
yield mock_credstash
class TestYaml(unittest.TestCase):
"""Test util.yaml loader."""
def test_simple_list():
"""Test simple list."""
conf = "config:\n - simple\n - list"
with io.StringIO(conf) as file:
doc = yaml.yaml.safe_load(file)
assert doc['config'] == ["simple", "list"]
# pylint: disable=no-self-use, invalid-name
def test_simple_list(self):
"""Test simple list."""
conf = "config:\n - simple\n - list"
def test_simple_dict():
"""Test simple dict."""
conf = "key: value"
with io.StringIO(conf) as file:
doc = yaml.yaml.safe_load(file)
assert doc['key'] == 'value'
def test_unhashable_key():
"""Test an unhasable key."""
files = {YAML_CONFIG_FILE: 'message:\n {{ states.state }}'}
with pytest.raises(HomeAssistantError), \
patch_yaml_files(files):
load_yaml_config_file(YAML_CONFIG_FILE)
def test_no_key():
"""Test item without a key."""
files = {YAML_CONFIG_FILE: 'a: a\nnokeyhere'}
with pytest.raises(HomeAssistantError), \
patch_yaml_files(files):
yaml.load_yaml(YAML_CONFIG_FILE)
def test_environment_variable():
"""Test config file with environment variable."""
os.environ["PASSWORD"] = "secret_password"
conf = "password: !env_var PASSWORD"
with io.StringIO(conf) as file:
doc = yaml.yaml.safe_load(file)
assert doc['password'] == "secret_password"
del os.environ["PASSWORD"]
def test_environment_variable_default():
"""Test config file with default value for environment variable."""
conf = "password: !env_var PASSWORD secret_password"
with io.StringIO(conf) as file:
doc = yaml.yaml.safe_load(file)
assert doc['password'] == "secret_password"
def test_invalid_environment_variable():
"""Test config file with no environment variable sat."""
conf = "password: !env_var PASSWORD"
with pytest.raises(HomeAssistantError):
with io.StringIO(conf) as file:
yaml.yaml.safe_load(file)
def test_include_yaml():
"""Test include yaml."""
with patch_yaml_files({'test.yaml': 'value'}):
conf = 'key: !include test.yaml'
with io.StringIO(conf) as file:
doc = yaml.yaml.safe_load(file)
assert doc['config'] == ["simple", "list"]
assert doc["key"] == "value"
def test_simple_dict(self):
"""Test simple dict."""
conf = "key: value"
with patch_yaml_files({'test.yaml': None}):
conf = 'key: !include test.yaml'
with io.StringIO(conf) as file:
doc = yaml.yaml.safe_load(file)
assert doc['key'] == 'value'
assert doc["key"] == {}
def test_unhashable_key(self):
"""Test an unhasable key."""
files = {YAML_CONFIG_FILE: 'message:\n {{ states.state }}'}
with pytest.raises(HomeAssistantError), \
patch_yaml_files(files):
load_yaml_config_file(YAML_CONFIG_FILE)
def test_no_key(self):
"""Test item without a key."""
files = {YAML_CONFIG_FILE: 'a: a\nnokeyhere'}
with pytest.raises(HomeAssistantError), \
patch_yaml_files(files):
yaml.load_yaml(YAML_CONFIG_FILE)
@patch('homeassistant.util.yaml.os.walk')
def test_include_dir_list(mock_walk):
"""Test include dir list yaml."""
mock_walk.return_value = [
['/tmp', [], ['two.yaml', 'one.yaml']],
]
def test_environment_variable(self):
"""Test config file with environment variable."""
os.environ["PASSWORD"] = "secret_password"
conf = "password: !env_var PASSWORD"
with io.StringIO(conf) as file:
doc = yaml.yaml.safe_load(file)
assert doc['password'] == "secret_password"
del os.environ["PASSWORD"]
def test_environment_variable_default(self):
"""Test config file with default value for environment variable."""
conf = "password: !env_var PASSWORD secret_password"
with io.StringIO(conf) as file:
doc = yaml.yaml.safe_load(file)
assert doc['password'] == "secret_password"
def test_invalid_environment_variable(self):
"""Test config file with no environment variable sat."""
conf = "password: !env_var PASSWORD"
with pytest.raises(HomeAssistantError):
with io.StringIO(conf) as file:
yaml.yaml.safe_load(file)
def test_include_yaml(self):
"""Test include yaml."""
with patch_yaml_files({'test.yaml': 'value'}):
conf = 'key: !include test.yaml'
with io.StringIO(conf) as file:
doc = yaml.yaml.safe_load(file)
assert doc["key"] == "value"
with patch_yaml_files({'test.yaml': None}):
conf = 'key: !include test.yaml'
with io.StringIO(conf) as file:
doc = yaml.yaml.safe_load(file)
assert doc["key"] == {}
@patch('homeassistant.util.yaml.os.walk')
def test_include_dir_list(self, mock_walk):
"""Test include dir list yaml."""
mock_walk.return_value = [
['/tmp', [], ['two.yaml', 'one.yaml']],
]
with patch_yaml_files({
with patch_yaml_files({
'/tmp/one.yaml': 'one',
'/tmp/two.yaml': 'two',
}):
conf = "key: !include_dir_list /tmp"
with io.StringIO(conf) as file:
doc = yaml.yaml.safe_load(file)
assert doc["key"] == sorted(["one", "two"])
}):
conf = "key: !include_dir_list /tmp"
with io.StringIO(conf) as file:
doc = yaml.yaml.safe_load(file)
assert doc["key"] == sorted(["one", "two"])
@patch('homeassistant.util.yaml.os.walk')
def test_include_dir_list_recursive(self, mock_walk):
"""Test include dir recursive list yaml."""
mock_walk.return_value = [
['/tmp', ['tmp2', '.ignore', 'ignore'], ['zero.yaml']],
['/tmp/tmp2', [], ['one.yaml', 'two.yaml']],
['/tmp/ignore', [], ['.ignore.yaml']]
]
with patch_yaml_files({
@patch('homeassistant.util.yaml.os.walk')
def test_include_dir_list_recursive(mock_walk):
"""Test include dir recursive list yaml."""
mock_walk.return_value = [
['/tmp', ['tmp2', '.ignore', 'ignore'], ['zero.yaml']],
['/tmp/tmp2', [], ['one.yaml', 'two.yaml']],
['/tmp/ignore', [], ['.ignore.yaml']]
]
with patch_yaml_files({
'/tmp/zero.yaml': 'zero',
'/tmp/tmp2/one.yaml': 'one',
'/tmp/tmp2/two.yaml': 'two'
}):
conf = "key: !include_dir_list /tmp"
with io.StringIO(conf) as file:
assert '.ignore' in mock_walk.return_value[0][1], \
"Expecting .ignore in here"
doc = yaml.yaml.safe_load(file)
assert 'tmp2' in mock_walk.return_value[0][1]
assert '.ignore' not in mock_walk.return_value[0][1]
assert sorted(doc["key"]) == sorted(["zero", "one", "two"])
}):
conf = "key: !include_dir_list /tmp"
with io.StringIO(conf) as file:
assert '.ignore' in mock_walk.return_value[0][1], \
"Expecting .ignore in here"
doc = yaml.yaml.safe_load(file)
assert 'tmp2' in mock_walk.return_value[0][1]
assert '.ignore' not in mock_walk.return_value[0][1]
assert sorted(doc["key"]) == sorted(["zero", "one", "two"])
@patch('homeassistant.util.yaml.os.walk')
def test_include_dir_named(self, mock_walk):
"""Test include dir named yaml."""
mock_walk.return_value = [
['/tmp', [], ['first.yaml', 'second.yaml', 'secrets.yaml']]
]
with patch_yaml_files({
@patch('homeassistant.util.yaml.os.walk')
def test_include_dir_named(mock_walk):
"""Test include dir named yaml."""
mock_walk.return_value = [
['/tmp', [], ['first.yaml', 'second.yaml', 'secrets.yaml']]
]
with patch_yaml_files({
'/tmp/first.yaml': 'one',
'/tmp/second.yaml': 'two'
}):
conf = "key: !include_dir_named /tmp"
correct = {'first': 'one', 'second': 'two'}
with io.StringIO(conf) as file:
doc = yaml.yaml.safe_load(file)
assert doc["key"] == correct
}):
conf = "key: !include_dir_named /tmp"
correct = {'first': 'one', 'second': 'two'}
with io.StringIO(conf) as file:
doc = yaml.yaml.safe_load(file)
assert doc["key"] == correct
@patch('homeassistant.util.yaml.os.walk')
def test_include_dir_named_recursive(self, mock_walk):
"""Test include dir named yaml."""
mock_walk.return_value = [
['/tmp', ['tmp2', '.ignore', 'ignore'], ['first.yaml']],
['/tmp/tmp2', [], ['second.yaml', 'third.yaml']],
['/tmp/ignore', [], ['.ignore.yaml']]
]
with patch_yaml_files({
@patch('homeassistant.util.yaml.os.walk')
def test_include_dir_named_recursive(mock_walk):
"""Test include dir named yaml."""
mock_walk.return_value = [
['/tmp', ['tmp2', '.ignore', 'ignore'], ['first.yaml']],
['/tmp/tmp2', [], ['second.yaml', 'third.yaml']],
['/tmp/ignore', [], ['.ignore.yaml']]
]
with patch_yaml_files({
'/tmp/first.yaml': 'one',
'/tmp/tmp2/second.yaml': 'two',
'/tmp/tmp2/third.yaml': 'three'
}):
conf = "key: !include_dir_named /tmp"
correct = {'first': 'one', 'second': 'two', 'third': 'three'}
with io.StringIO(conf) as file:
assert '.ignore' in mock_walk.return_value[0][1], \
"Expecting .ignore in here"
doc = yaml.yaml.safe_load(file)
assert 'tmp2' in mock_walk.return_value[0][1]
assert '.ignore' not in mock_walk.return_value[0][1]
assert doc["key"] == correct
}):
conf = "key: !include_dir_named /tmp"
correct = {'first': 'one', 'second': 'two', 'third': 'three'}
with io.StringIO(conf) as file:
assert '.ignore' in mock_walk.return_value[0][1], \
"Expecting .ignore in here"
doc = yaml.yaml.safe_load(file)
assert 'tmp2' in mock_walk.return_value[0][1]
assert '.ignore' not in mock_walk.return_value[0][1]
assert doc["key"] == correct
@patch('homeassistant.util.yaml.os.walk')
def test_include_dir_merge_list(self, mock_walk):
"""Test include dir merge list yaml."""
mock_walk.return_value = [['/tmp', [], ['first.yaml', 'second.yaml']]]
with patch_yaml_files({
@patch('homeassistant.util.yaml.os.walk')
def test_include_dir_merge_list(mock_walk):
"""Test include dir merge list yaml."""
mock_walk.return_value = [['/tmp', [], ['first.yaml', 'second.yaml']]]
with patch_yaml_files({
'/tmp/first.yaml': '- one',
'/tmp/second.yaml': '- two\n- three'
}):
conf = "key: !include_dir_merge_list /tmp"
with io.StringIO(conf) as file:
doc = yaml.yaml.safe_load(file)
assert sorted(doc["key"]) == sorted(["one", "two", "three"])
}):
conf = "key: !include_dir_merge_list /tmp"
with io.StringIO(conf) as file:
doc = yaml.yaml.safe_load(file)
assert sorted(doc["key"]) == sorted(["one", "two", "three"])
@patch('homeassistant.util.yaml.os.walk')
def test_include_dir_merge_list_recursive(self, mock_walk):
"""Test include dir merge list yaml."""
mock_walk.return_value = [
['/tmp', ['tmp2', '.ignore', 'ignore'], ['first.yaml']],
['/tmp/tmp2', [], ['second.yaml', 'third.yaml']],
['/tmp/ignore', [], ['.ignore.yaml']]
]
with patch_yaml_files({
@patch('homeassistant.util.yaml.os.walk')
def test_include_dir_merge_list_recursive(mock_walk):
"""Test include dir merge list yaml."""
mock_walk.return_value = [
['/tmp', ['tmp2', '.ignore', 'ignore'], ['first.yaml']],
['/tmp/tmp2', [], ['second.yaml', 'third.yaml']],
['/tmp/ignore', [], ['.ignore.yaml']]
]
with patch_yaml_files({
'/tmp/first.yaml': '- one',
'/tmp/tmp2/second.yaml': '- two',
'/tmp/tmp2/third.yaml': '- three\n- four'
}):
conf = "key: !include_dir_merge_list /tmp"
with io.StringIO(conf) as file:
assert '.ignore' in mock_walk.return_value[0][1], \
"Expecting .ignore in here"
doc = yaml.yaml.safe_load(file)
assert 'tmp2' in mock_walk.return_value[0][1]
assert '.ignore' not in mock_walk.return_value[0][1]
assert sorted(doc["key"]) == sorted(["one", "two",
"three", "four"])
}):
conf = "key: !include_dir_merge_list /tmp"
with io.StringIO(conf) as file:
assert '.ignore' in mock_walk.return_value[0][1], \
"Expecting .ignore in here"
doc = yaml.yaml.safe_load(file)
assert 'tmp2' in mock_walk.return_value[0][1]
assert '.ignore' not in mock_walk.return_value[0][1]
assert sorted(doc["key"]) == sorted(["one", "two",
"three", "four"])
@patch('homeassistant.util.yaml.os.walk')
def test_include_dir_merge_named(self, mock_walk):
"""Test include dir merge named yaml."""
mock_walk.return_value = [['/tmp', [], ['first.yaml', 'second.yaml']]]
files = {
'/tmp/first.yaml': 'key1: one',
'/tmp/second.yaml': 'key2: two\nkey3: three',
}
@patch('homeassistant.util.yaml.os.walk')
def test_include_dir_merge_named(mock_walk):
"""Test include dir merge named yaml."""
mock_walk.return_value = [['/tmp', [], ['first.yaml', 'second.yaml']]]
with patch_yaml_files(files):
conf = "key: !include_dir_merge_named /tmp"
with io.StringIO(conf) as file:
doc = yaml.yaml.safe_load(file)
assert doc["key"] == {
"key1": "one",
"key2": "two",
"key3": "three"
}
files = {
'/tmp/first.yaml': 'key1: one',
'/tmp/second.yaml': 'key2: two\nkey3: three',
}
@patch('homeassistant.util.yaml.os.walk')
def test_include_dir_merge_named_recursive(self, mock_walk):
"""Test include dir merge named yaml."""
mock_walk.return_value = [
['/tmp', ['tmp2', '.ignore', 'ignore'], ['first.yaml']],
['/tmp/tmp2', [], ['second.yaml', 'third.yaml']],
['/tmp/ignore', [], ['.ignore.yaml']]
]
with patch_yaml_files(files):
conf = "key: !include_dir_merge_named /tmp"
with io.StringIO(conf) as file:
doc = yaml.yaml.safe_load(file)
assert doc["key"] == {
"key1": "one",
"key2": "two",
"key3": "three"
}
with patch_yaml_files({
@patch('homeassistant.util.yaml.os.walk')
def test_include_dir_merge_named_recursive(mock_walk):
"""Test include dir merge named yaml."""
mock_walk.return_value = [
['/tmp', ['tmp2', '.ignore', 'ignore'], ['first.yaml']],
['/tmp/tmp2', [], ['second.yaml', 'third.yaml']],
['/tmp/ignore', [], ['.ignore.yaml']]
]
with patch_yaml_files({
'/tmp/first.yaml': 'key1: one',
'/tmp/tmp2/second.yaml': 'key2: two',
'/tmp/tmp2/third.yaml': 'key3: three\nkey4: four'
}):
conf = "key: !include_dir_merge_named /tmp"
with io.StringIO(conf) as file:
assert '.ignore' in mock_walk.return_value[0][1], \
"Expecting .ignore in here"
doc = yaml.yaml.safe_load(file)
assert 'tmp2' in mock_walk.return_value[0][1]
assert '.ignore' not in mock_walk.return_value[0][1]
assert doc["key"] == {
"key1": "one",
"key2": "two",
"key3": "three",
"key4": "four"
}
}):
conf = "key: !include_dir_merge_named /tmp"
with io.StringIO(conf) as file:
assert '.ignore' in mock_walk.return_value[0][1], \
"Expecting .ignore in here"
doc = yaml.yaml.safe_load(file)
assert 'tmp2' in mock_walk.return_value[0][1]
assert '.ignore' not in mock_walk.return_value[0][1]
assert doc["key"] == {
"key1": "one",
"key2": "two",
"key3": "three",
"key4": "four"
}
@patch('homeassistant.util.yaml.open', create=True)
def test_load_yaml_encoding_error(self, mock_open):
"""Test raising a UnicodeDecodeError."""
mock_open.side_effect = UnicodeDecodeError('', b'', 1, 0, '')
with pytest.raises(HomeAssistantError):
yaml.load_yaml('test')
def test_dump(self):
"""The that the dump method returns empty None values."""
assert yaml.dump({'a': None, 'b': 'b'}) == 'a:\nb: b\n'
@patch('homeassistant.util.yaml.open', create=True)
def test_load_yaml_encoding_error(mock_open):
"""Test raising a UnicodeDecodeError."""
mock_open.side_effect = UnicodeDecodeError('', b'', 1, 0, '')
with pytest.raises(HomeAssistantError):
yaml.load_yaml('test')
def test_dump_unicode(self):
"""The that the dump method returns empty None values."""
assert yaml.dump({'a': None, 'b': 'привет'}) == 'a:\nb: привет\n'
def test_dump():
"""The that the dump method returns empty None values."""
assert yaml.dump({'a': None, 'b': 'b'}) == 'a:\nb: b\n'
def test_dump_unicode():
"""The that the dump method returns empty None values."""
assert yaml.dump({'a': None, 'b': 'привет'}) == 'a:\nb: привет\n'
FILES = {}
@ -415,9 +428,9 @@ class TestSecrets(unittest.TestCase):
def test_secrets_are_not_dict(self):
"""Did secrets handle non-dict file."""
FILES[self._secret_path] = (
'- http_pw: pwhttp\n'
' comp1_un: un1\n'
' comp1_pw: pw1\n')
'- http_pw: pwhttp\n'
' comp1_un: un1\n'
' comp1_pw: pw1\n')
yaml.clear_secret_cache()
with pytest.raises(HomeAssistantError):
load_yaml(self._yaml_path,