summaryrefslogtreecommitdiffstats
path: root/tests/test_config.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_config.py')
-rw-r--r--tests/test_config.py293
1 files changed, 293 insertions, 0 deletions
diff --git a/tests/test_config.py b/tests/test_config.py
new file mode 100644
index 0000000..131bc8c
--- /dev/null
+++ b/tests/test_config.py
@@ -0,0 +1,293 @@
+# -*- coding: utf-8 -*-
+"""Test the cli_helpers.config module."""
+
+from __future__ import unicode_literals
+import os
+
+from unittest.mock import MagicMock
+import pytest
+
+from cli_helpers.compat import MAC, text_type, WIN
+from cli_helpers.config import (
+ Config,
+ DefaultConfigValidationError,
+ get_system_config_dirs,
+ get_user_config_dir,
+ _pathify,
+)
+from .utils import with_temp_dir
+
+APP_NAME, APP_AUTHOR = "Test", "Acme"
+TEST_DATA_DIR = os.path.join(os.path.dirname(__file__), "config_data")
+DEFAULT_CONFIG = {
+ "section": {
+ "test_boolean_default": "True",
+ "test_string_file": "~/myfile",
+ "test_option": "foobar✔",
+ },
+ "section2": {},
+}
+DEFAULT_VALID_CONFIG = {
+ "section": {
+ "test_boolean_default": True,
+ "test_string_file": "~/myfile",
+ "test_option": "foobar✔",
+ },
+ "section2": {},
+}
+
+
+def _mocked_user_config(temp_dir, *args, **kwargs):
+ config = Config(*args, **kwargs)
+ config.user_config_file = MagicMock(
+ return_value=os.path.join(temp_dir, config.filename)
+ )
+ return config
+
+
+def test_user_config_dir():
+ """Test that the config directory is a string with the app name in it."""
+ if "XDG_CONFIG_HOME" in os.environ:
+ del os.environ["XDG_CONFIG_HOME"]
+ config_dir = get_user_config_dir(APP_NAME, APP_AUTHOR)
+ assert isinstance(config_dir, text_type)
+ assert config_dir.endswith(APP_NAME) or config_dir.endswith(_pathify(APP_NAME))
+
+
+def test_sys_config_dirs():
+ """Test that the sys config directories are returned correctly."""
+ if "XDG_CONFIG_DIRS" in os.environ:
+ del os.environ["XDG_CONFIG_DIRS"]
+ config_dirs = get_system_config_dirs(APP_NAME, APP_AUTHOR)
+ assert isinstance(config_dirs, list)
+ assert config_dirs[0].endswith(APP_NAME) or config_dirs[0].endswith(
+ _pathify(APP_NAME)
+ )
+
+
+@pytest.mark.skipif(not WIN, reason="requires Windows")
+def test_windows_user_config_dir_no_roaming():
+ """Test that Windows returns the user config directory without roaming."""
+ config_dir = get_user_config_dir(APP_NAME, APP_AUTHOR, roaming=False)
+ assert isinstance(config_dir, text_type)
+ assert config_dir.endswith(APP_NAME)
+ assert "Local" in config_dir
+
+
+@pytest.mark.skipif(not MAC, reason="requires macOS")
+def test_mac_user_config_dir_no_xdg():
+ """Test that macOS returns the user config directory without XDG."""
+ config_dir = get_user_config_dir(APP_NAME, APP_AUTHOR, force_xdg=False)
+ assert isinstance(config_dir, text_type)
+ assert config_dir.endswith(APP_NAME)
+ assert "Library" in config_dir
+
+
+@pytest.mark.skipif(not MAC, reason="requires macOS")
+def test_mac_system_config_dirs_no_xdg():
+ """Test that macOS returns the system config directories without XDG."""
+ config_dirs = get_system_config_dirs(APP_NAME, APP_AUTHOR, force_xdg=False)
+ assert isinstance(config_dirs, list)
+ assert config_dirs[0].endswith(APP_NAME)
+ assert "Library" in config_dirs[0]
+
+
+def test_config_reading_raise_errors():
+ """Test that instantiating Config will raise errors when appropriate."""
+ with pytest.raises(ValueError):
+ Config(APP_NAME, APP_AUTHOR, "test_config", write_default=True)
+
+ with pytest.raises(ValueError):
+ Config(APP_NAME, APP_AUTHOR, "test_config", validate=True)
+
+ with pytest.raises(TypeError):
+ Config(APP_NAME, APP_AUTHOR, "test_config", default=b"test")
+
+
+def test_config_user_file():
+ """Test that the Config user_config_file is appropriate."""
+ config = Config(APP_NAME, APP_AUTHOR, "test_config")
+ assert get_user_config_dir(APP_NAME, APP_AUTHOR) in config.user_config_file()
+
+
+def test_config_reading_default_dict():
+ """Test that the Config constructor will read in defaults from a dict."""
+ default = {"main": {"foo": "bar"}}
+ config = Config(APP_NAME, APP_AUTHOR, "test_config", default=default)
+ assert config.data == default
+
+
+def test_config_reading_no_default():
+ """Test that the Config constructor will work without any defaults."""
+ config = Config(APP_NAME, APP_AUTHOR, "test_config")
+ assert config.data == {}
+
+
+def test_config_reading_default_file():
+ """Test that the Config will work with a default file."""
+ config = Config(
+ APP_NAME,
+ APP_AUTHOR,
+ "test_config",
+ default=os.path.join(TEST_DATA_DIR, "configrc"),
+ )
+ config.read_default_config()
+ assert config.data == DEFAULT_CONFIG
+
+
+def test_config_reading_configspec():
+ """Test that the Config default file will work with a configspec."""
+ config = Config(
+ APP_NAME,
+ APP_AUTHOR,
+ "test_config",
+ validate=True,
+ default=os.path.join(TEST_DATA_DIR, "configspecrc"),
+ )
+ config.read_default_config()
+ assert config.data == DEFAULT_VALID_CONFIG
+
+
+def test_config_reading_configspec_with_error():
+ """Test that reading an invalid configspec raises and exception."""
+ with pytest.raises(DefaultConfigValidationError):
+ config = Config(
+ APP_NAME,
+ APP_AUTHOR,
+ "test_config",
+ validate=True,
+ default=os.path.join(TEST_DATA_DIR, "invalid_configspecrc"),
+ )
+ config.read_default_config()
+
+
+@with_temp_dir
+def test_write_and_read_default_config(temp_dir=None):
+ config_file = "test_config"
+ default_file = os.path.join(TEST_DATA_DIR, "configrc")
+ temp_config_file = os.path.join(temp_dir, config_file)
+
+ config = _mocked_user_config(
+ temp_dir, APP_NAME, APP_AUTHOR, config_file, default=default_file
+ )
+ config.read_default_config()
+ config.write_default_config()
+
+ user_config = _mocked_user_config(
+ temp_dir, APP_NAME, APP_AUTHOR, config_file, default=default_file
+ )
+ user_config.read()
+ assert temp_config_file in user_config.config_filenames
+ assert user_config == config
+
+ with open(temp_config_file) as f:
+ contents = f.read()
+ assert "# Test file comment" in contents
+ assert "# Test section comment" in contents
+ assert "# Test field comment" in contents
+ assert "# Test field commented out" in contents
+
+
+@with_temp_dir
+def test_write_and_read_default_config_from_configspec(temp_dir=None):
+ config_file = "test_config"
+ default_file = os.path.join(TEST_DATA_DIR, "configspecrc")
+ temp_config_file = os.path.join(temp_dir, config_file)
+
+ config = _mocked_user_config(
+ temp_dir, APP_NAME, APP_AUTHOR, config_file, default=default_file, validate=True
+ )
+ config.read_default_config()
+ config.write_default_config()
+
+ user_config = _mocked_user_config(
+ temp_dir, APP_NAME, APP_AUTHOR, config_file, default=default_file, validate=True
+ )
+ user_config.read()
+ assert temp_config_file in user_config.config_filenames
+ assert user_config == config
+
+ with open(temp_config_file) as f:
+ contents = f.read()
+ assert "# Test file comment" in contents
+ assert "# Test section comment" in contents
+ assert "# Test field comment" in contents
+ assert "# Test field commented out" in contents
+
+
+@with_temp_dir
+def test_overwrite_default_config_from_configspec(temp_dir=None):
+ config_file = "test_config"
+ default_file = os.path.join(TEST_DATA_DIR, "configspecrc")
+ temp_config_file = os.path.join(temp_dir, config_file)
+
+ config = _mocked_user_config(
+ temp_dir, APP_NAME, APP_AUTHOR, config_file, default=default_file, validate=True
+ )
+ config.read_default_config()
+ config.write_default_config()
+
+ with open(temp_config_file, "a") as f:
+ f.write("--APPEND--")
+
+ config.write_default_config()
+
+ with open(temp_config_file) as f:
+ assert "--APPEND--" in f.read()
+
+ config.write_default_config(overwrite=True)
+
+ with open(temp_config_file) as f:
+ assert "--APPEND--" not in f.read()
+
+
+def test_read_invalid_config_file():
+ config_file = "invalid_configrc"
+
+ config = _mocked_user_config(TEST_DATA_DIR, APP_NAME, APP_AUTHOR, config_file)
+ config.read()
+ assert "section" in config
+ assert "test_string_file" in config["section"]
+ assert "test_boolean_default" not in config["section"]
+ assert "section2" in config
+
+
+@with_temp_dir
+def test_write_to_user_config(temp_dir=None):
+ config_file = "test_config"
+ default_file = os.path.join(TEST_DATA_DIR, "configrc")
+ temp_config_file = os.path.join(temp_dir, config_file)
+
+ config = _mocked_user_config(
+ temp_dir, APP_NAME, APP_AUTHOR, config_file, default=default_file
+ )
+ config.read_default_config()
+ config.write_default_config()
+
+ with open(temp_config_file) as f:
+ assert "test_boolean_default = True" in f.read()
+
+ config["section"]["test_boolean_default"] = False
+ config.write()
+
+ with open(temp_config_file) as f:
+ assert "test_boolean_default = False" in f.read()
+
+
+@with_temp_dir
+def test_write_to_outfile(temp_dir=None):
+ config_file = "test_config"
+ outfile = os.path.join(temp_dir, "foo")
+ default_file = os.path.join(TEST_DATA_DIR, "configrc")
+
+ config = _mocked_user_config(
+ temp_dir, APP_NAME, APP_AUTHOR, config_file, default=default_file
+ )
+ config.read_default_config()
+ config.write_default_config()
+
+ config["section"]["test_boolean_default"] = False
+ config.write(outfile=outfile)
+
+ with open(outfile) as f:
+ assert "test_boolean_default = False" in f.read()