Completed
Pull Request — master (#971)
by
unknown
31s
created

test_get_config_with_defaults()   B

Complexity

Conditions 2

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
c 0
b 0
f 0
dl 0
loc 24
rs 8.9713
1
# -*- coding: utf-8 -*-
2
import os
3
4
import pytest
5
6
from cookiecutter import config
7
from cookiecutter.exceptions import (InvalidConfiguration,
8
                                     ConfigDoesNotExistException)
9
10
11
def test_find_user_config_envvar_is_valid_path(monkeypatch, tmpdir):
12
    """If COOKIECUTTER_CONFIG is set and valid, use it"""
13
    # .ensure makes the path exist so it passes os.path.isfile
14
    path = tmpdir.mkdir('spoofdir').join('spoofrc').ensure()
15
    monkeypatch.setenv('COOKIECUTTER_CONFIG', str(path))
16
    assert config._find_user_config() == str(path)
17
18
19
def test_find_user_config_raises_for_invalid_envvar(monkeypatch, tmpdir):
20
    """If COOKIECUTTER_CONFIG is set but not a file,
21
    raise ConfigDoesNotExistException
22
    """
23
    # path doesn't actually exist unless we call ensure
24
    path = tmpdir.mkdir('spoofdir').join('spoofrc')
25
    monkeypatch.setenv('COOKIECUTTER_CONFIG', str(path))
26
    with pytest.raises(ConfigDoesNotExistException):
27
        config._find_user_config()
28
29
30
def test_find_user_config_gets_existing_default(monkeypatch, tmpdir):
31
    """
32
    If COOKIECUTTER_CONFIG is unset but ~/.cookiecutterrc exists, return it
33
    """
34
    base_path = tmpdir.mkdir('spoofdir')
35
    # we can't just patch cookiecutter.config.expanduser; the value of
36
    # USER_CONFIG_FALLBACK_PATH is set at import time, which is prior to when
37
    # we can patch - so patch the computed constant directly against the
38
    # imported module
39
    monkeypatch.setattr(config,
40
                        'USER_CONFIG_FALLBACK_PATH',
41
                        str(base_path.join('.cookiecutterrc')))
42
    default_conf_path = str(base_path.join('.cookiecutterrc').ensure())
43
    monkeypatch.delenv('COOKIECUTTER_CONFIG', raising=False)
44
    assert config._find_user_config() == default_conf_path
45
46
47
@pytest.mark.parametrize("platform", ['XDG', 'NIX', 'OSX', 'WIN', None])
48
def test_find_user_config_platform_dir_search_path(monkeypatch,
49
                                                   tmpdir,
50
                                                   platform):
51
    r"""
52
    If COOKIECUTTER_CONFIG is unset and ~/.cookiecutterrc does not exist, then
53
    search the following:
54
        $XDG_CONFIG_HOME/cookiecutter/config
55
        %APPDATA%\cookiecutter\config
56
        ~/.config/cookiecutter/config
57
        ~/Library/Application\ Support/cookiecutter/config
58
    And the return the first match that exists
59
    """
60
    base_path = tmpdir.mkdir('spoofdir')
61
    # patch this in this test so we can assert it isn't a file (since nothing
62
    # below is supposed to run if it is)
63
    monkeypatch.setattr(config,
64
                        'USER_CONFIG_FALLBACK_PATH',
65
                        str(base_path.join('.cookiecutterrc')))
66
    # preconditions of searching for a platform-specific dir
67
    monkeypatch.delenv('COOKIECUTTER_CONFIG', raising=False)
68
    assert not os.path.isfile(config.USER_CONFIG_FALLBACK_PATH)
69
70
    search_path = {
71
        # make them unique - they're just envvars, so they could be anything
72
        'XDG': base_path.join('XDG'),
73
        'WIN': base_path.join('WIN'),
74
        # these two are a little more concrete - they have to match what's
75
        # hardcoded in the join in cookiecutter/config.py
76
        'NIX': base_path.join('.config'),
77
        'OSX': base_path.join('Library', 'Application Support')
78
    }
79
    monkeypatch.setenv('XDG_CONFIG_HOME', str(search_path['XDG']))
80
    monkeypatch.setenv('APPDATA', str(search_path['WIN']))
81
    monkeypatch.setattr(config, 'HOME_DIR', str(base_path))
82
83
    if platform is None:
84
        assert config._find_user_config() is None
85
        return
86
87
    path = search_path.pop(platform)
88
    path = path.join('cookiecutter', 'config').ensure()
89
90
    assert config._find_user_config() == str(path)
91
    for _, other_path in search_path.items():
92
        assert config._find_user_config() != str(other_path)
93
94
95
@pytest.mark.parametrize('kind', ['cookiecutters_dir', 'cookiecutter_replay'])
96
def test_find_user_data_dir_valid_envvar(monkeypatch, tmpdir, kind):
97
    tmpdatadir = tmpdir.mkdir('spoof').join('temprc').ensure(dir=True)
98
    monkeypatch.setenv(kind.upper(), str(tmpdatadir))
99
    assert config._find_user_data_dir(kind) == str(tmpdatadir)
100
101
102
@pytest.mark.parametrize('kind', ['cookiecutters_dir', 'cookiecutter_replay'])
103
def test_find_user_data_dir_preexisting_dotdir(monkeypatch, tmpdir, kind):
104
    tmphome = tmpdir.mkdir('phonyhome')
105
    monkeypatch.setattr(config, 'HOME_DIR', str(tmphome))
106
    tmpdatadir = tmphome.join('.{}'.format(kind.lower())).ensure(dir=True)
107
    assert config._find_user_data_dir(kind) == str(tmpdatadir)
108
109
110
@pytest.mark.parametrize('kind', ['cookiecutters_dir', 'cookiecutter_replay'])
111
def test_find_user_data_dir_falls_back_to_user_home(monkeypatch, tmpdir, kind):
112
    monkeypatch.delenv(kind.upper(), raising=False)
113
    monkeypatch.delenv('XDG_DATA_HOME', raising=False)
114
    monkeypatch.delenv('APPDATA', raising=False)
115
    mockdir = tmpdir.mkdir('mock')
116
    monkeypatch.setattr(config, 'HOME_DIR', str(mockdir))
117
    expected = os.path.normpath('{}/.{}'.format(str(mockdir), kind.lower()))
118
    assert config._find_user_data_dir(kind) == expected
119
120
121
def test_merge_configs():
122
    default = {
123
        'cookiecutters_dir': '/home/example/some-path-to-templates',
124
        'replay_dir': '/home/example/some-path-to-replay-files',
125
        'default_context': {},
126
        'abbreviations': {
127
            'gh': 'https://github.com/{0}.git',
128
            'gl': 'https://gitlab.com/{0}.git',
129
            'bb': 'https://bitbucket.org/{0}',
130
        }
131
    }
132
133
    user_config = {
134
        'default_context': {
135
            'full_name': 'Raphael Pierzina',
136
            'github_username': 'hackebrot',
137
        },
138
        'abbreviations': {
139
            'gl': 'https://gitlab.com/hackebrot/{0}.git',
140
            'pytest-plugin': 'https://github.com/pytest-dev/pytest-plugin.git',
141
        }
142
    }
143
144
    expected_config = {
145
        'cookiecutters_dir': '/home/example/some-path-to-templates',
146
        'replay_dir': '/home/example/some-path-to-replay-files',
147
        'default_context': {
148
            'full_name': 'Raphael Pierzina',
149
            'github_username': 'hackebrot',
150
        },
151
        'abbreviations': {
152
            'gh': 'https://github.com/{0}.git',
153
            'gl': 'https://gitlab.com/hackebrot/{0}.git',
154
            'bb': 'https://bitbucket.org/{0}',
155
            'pytest-plugin': 'https://github.com/pytest-dev/pytest-plugin.git',
156
        }
157
    }
158
159
    assert config.merge_configs(default, user_config) == expected_config
160
161
162
def test_get_config():
163
    """
164
    Opening and reading config file
165
    """
166
    conf = config.get_config('tests/test-config/valid-config.yaml')
167
    expected_conf = {
168
        'cookiecutters_dir': '/home/example/some-path-to-templates',
169
        'replay_dir': '/home/example/some-path-to-replay-files',
170
        'default_context': {
171
            'full_name': 'Firstname Lastname',
172
            'email': '[email protected]',
173
            'github_username': 'example'
174
        },
175
        'abbreviations': {
176
            'gh': 'https://github.com/{0}.git',
177
            'gl': 'https://gitlab.com/{0}.git',
178
            'bb': 'https://bitbucket.org/{0}',
179
            'helloworld': 'https://github.com/hackebrot/helloworld'
180
        }
181
    }
182
    assert conf == expected_conf
183
184
185
def test_get_config_does_not_exist():
186
    """
187
    Check that `exceptions.ConfigDoesNotExistException` is raised when
188
    attempting to get a non-existent config file.
189
    """
190
    with pytest.raises(ConfigDoesNotExistException):
191
        config.get_config('tests/test-config/this-does-not-exist.yaml')
192
193
194
def test_invalid_config():
195
    """
196
    An invalid config file should raise an `InvalidConfiguration` exception.
197
    """
198
    with pytest.raises(InvalidConfiguration) as excinfo:
199
        config.get_config('tests/test-config/invalid-config.yaml')
200
201
    expected_error_msg = (
202
        'Unable to parse YAML file '
203
        'tests/test-config/invalid-config.yaml. '
204
        'Error: '
205
    )
206
    assert expected_error_msg in str(excinfo.value)
207
208
209
def test_get_config_with_defaults():
210
    """
211
    A config file that overrides 1 of 3 defaults
212
    """
213
    conf = config.get_config('tests/test-config/valid-partial-config.yaml')
214
    # use the defaults directly rather than invoke config._find_user_data_dir;
215
    # _find_user_data_dir should be an implementation detail
216
    default_cookiecutters_dir = config.DEFAULT_CONFIG['cookiecutters_dir']
217
    default_replay_dir = config.DEFAULT_CONFIG['replay_dir']
218
    expected_conf = {
219
        'cookiecutters_dir': default_cookiecutters_dir,
220
        'replay_dir': default_replay_dir,
221
        'default_context': {
222
            'full_name': 'Firstname Lastname',
223
            'email': '[email protected]',
224
            'github_username': 'example'
225
        },
226
        'abbreviations': {
227
            'gh': 'https://github.com/{0}.git',
228
            'gl': 'https://gitlab.com/{0}.git',
229
            'bb': 'https://bitbucket.org/{0}',
230
        }
231
    }
232
    assert conf == expected_conf
233