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

test_find_user_config_gets_existing_default()   A

Complexity

Conditions 2

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
c 0
b 0
f 0
dl 0
loc 15
rs 9.4285
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
    """If $COOKIECUTTERS_DIR or $COOKIECUTTER_REPLAY is set, use that"""
98
    tmpdatadir = tmpdir.mkdir('spoof').join('temprc').ensure(dir=True)
99
    monkeypatch.setenv(kind.upper(), str(tmpdatadir))
100
    assert config._find_user_data_dir(kind) == str(tmpdatadir)
101
102
103
@pytest.mark.parametrize('kind', ['cookiecutters_dir', 'cookiecutter_replay'])
104
def test_find_user_data_dir_preexisting_dotdir(monkeypatch, tmpdir, kind):
105
    """If a pre-existing ~/.cookiecutter_replay/ or ~/.cookiecutters_dir/
106
    exists and the relevant envvars are unset, use the existing dirs
107
    """
108
    tmphome = tmpdir.mkdir('phonyhome')
109
    monkeypatch.setattr(config, 'HOME_DIR', str(tmphome))
110
    tmpdatadir = tmphome.join('.{}'.format(kind.lower())).ensure(dir=True)
111
    assert config._find_user_data_dir(kind) == str(tmpdatadir)
112
113
114
@pytest.mark.parametrize('kind', ['cookiecutters_dir', 'cookiecutter_replay'])
115
@pytest.mark.parametrize("platform", ['XDG', 'NIX', 'OSX', 'WIN'])
116
def test_find_user_data_dir_search_path(monkeypatch, tmpdir, kind, platform):
117
    base_path = tmpdir.mkdir('datadir')
118
    search_path = {
119
        'XDG': base_path.join('XDG'),
120
        'WIN': base_path.join('WIN'),
121
        # these two are a little more concrete - they have to match what's
122
        # hardcoded in the join in cookiecutter/config.py
123
        'NIX': base_path.join('.local', 'share'),
124
        'OSX': base_path.join('Library', 'Application Support')
125
    }
126
    monkeypatch.setenv('XDG_DATA_HOME', str(search_path['XDG']))
127
    monkeypatch.setenv('APPDATA', str(search_path['WIN']))
128
    monkeypatch.setattr(config, 'HOME_DIR', str(base_path))
129
    path = search_path.pop(platform)
130
    path = path.join('cookiecutter', kind).ensure(dir=True)
131
    assert config._find_user_data_dir(kind) == str(path)
132
    for _, other_path in search_path.items():
133
        assert config._find_user_data_dir(kind) != str(other_path)
134
135
136
@pytest.mark.parametrize('kind', ['cookiecutters_dir', 'cookiecutter_replay'])
137
def test_find_user_data_dir_falls_back_to_user_home(monkeypatch, tmpdir, kind):
138
    """If all else fails, store user data in $HOME"""
139
    monkeypatch.delenv(kind.upper(), raising=False)
140
    monkeypatch.delenv('XDG_DATA_HOME', raising=False)
141
    monkeypatch.delenv('APPDATA', raising=False)
142
    mockdir = tmpdir.mkdir('mock')
143
    monkeypatch.setattr(config, 'HOME_DIR', str(mockdir))
144
    expected = os.path.normpath('{}/.{}'.format(str(mockdir), kind.lower()))
145
    assert config._find_user_data_dir(kind) == expected
146
147
148
def test_merge_configs():
149
    default = {
150
        'cookiecutters_dir': '/home/example/some-path-to-templates',
151
        'replay_dir': '/home/example/some-path-to-replay-files',
152
        'default_context': {},
153
        'abbreviations': {
154
            'gh': 'https://github.com/{0}.git',
155
            'gl': 'https://gitlab.com/{0}.git',
156
            'bb': 'https://bitbucket.org/{0}',
157
        }
158
    }
159
160
    user_config = {
161
        'default_context': {
162
            'full_name': 'Raphael Pierzina',
163
            'github_username': 'hackebrot',
164
        },
165
        'abbreviations': {
166
            'gl': 'https://gitlab.com/hackebrot/{0}.git',
167
            'pytest-plugin': 'https://github.com/pytest-dev/pytest-plugin.git',
168
        }
169
    }
170
171
    expected_config = {
172
        'cookiecutters_dir': '/home/example/some-path-to-templates',
173
        'replay_dir': '/home/example/some-path-to-replay-files',
174
        'default_context': {
175
            'full_name': 'Raphael Pierzina',
176
            'github_username': 'hackebrot',
177
        },
178
        'abbreviations': {
179
            'gh': 'https://github.com/{0}.git',
180
            'gl': 'https://gitlab.com/hackebrot/{0}.git',
181
            'bb': 'https://bitbucket.org/{0}',
182
            'pytest-plugin': 'https://github.com/pytest-dev/pytest-plugin.git',
183
        }
184
    }
185
186
    assert config.merge_configs(default, user_config) == expected_config
187
188
189
def test_get_config():
190
    """
191
    Opening and reading config file
192
    """
193
    conf = config.get_config('tests/test-config/valid-config.yaml')
194
    expected_conf = {
195
        'cookiecutters_dir': '/home/example/some-path-to-templates',
196
        'replay_dir': '/home/example/some-path-to-replay-files',
197
        'default_context': {
198
            'full_name': 'Firstname Lastname',
199
            'email': '[email protected]',
200
            'github_username': 'example'
201
        },
202
        'abbreviations': {
203
            'gh': 'https://github.com/{0}.git',
204
            'gl': 'https://gitlab.com/{0}.git',
205
            'bb': 'https://bitbucket.org/{0}',
206
            'helloworld': 'https://github.com/hackebrot/helloworld'
207
        }
208
    }
209
    assert conf == expected_conf
210
211
212
def test_get_config_does_not_exist():
213
    """
214
    Check that `exceptions.ConfigDoesNotExistException` is raised when
215
    attempting to get a non-existent config file.
216
    """
217
    with pytest.raises(ConfigDoesNotExistException):
218
        config.get_config('tests/test-config/this-does-not-exist.yaml')
219
220
221
def test_invalid_config():
222
    """
223
    An invalid config file should raise an `InvalidConfiguration` exception.
224
    """
225
    with pytest.raises(InvalidConfiguration) as excinfo:
226
        config.get_config('tests/test-config/invalid-config.yaml')
227
228
    expected_error_msg = (
229
        'Unable to parse YAML file '
230
        'tests/test-config/invalid-config.yaml. '
231
        'Error: '
232
    )
233
    assert expected_error_msg in str(excinfo.value)
234
235
236
def test_get_config_with_defaults():
237
    """
238
    A config file that overrides 1 of 3 defaults
239
    """
240
    conf = config.get_config('tests/test-config/valid-partial-config.yaml')
241
    # use the defaults directly rather than invoke config._find_user_data_dir;
242
    # _find_user_data_dir should be an implementation detail
243
    default_cookiecutters_dir = config.DEFAULT_CONFIG['cookiecutters_dir']
244
    default_replay_dir = config.DEFAULT_CONFIG['replay_dir']
245
    expected_conf = {
246
        'cookiecutters_dir': default_cookiecutters_dir,
247
        'replay_dir': default_replay_dir,
248
        'default_context': {
249
            'full_name': 'Firstname Lastname',
250
            'email': '[email protected]',
251
            'github_username': 'example'
252
        },
253
        'abbreviations': {
254
            'gh': 'https://github.com/{0}.git',
255
            'gl': 'https://gitlab.com/{0}.git',
256
            'bb': 'https://bitbucket.org/{0}',
257
        }
258
    }
259
    assert conf == expected_conf
260