Migrate tests to pytest (#23544)
* Migrate tests to pytest * Fixup * Use loop fixture in test_check_config * Lint
This commit is contained in:
parent
d71424f285
commit
407e0c58f9
25 changed files with 4744 additions and 4910 deletions
|
@ -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',
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue