Completed
Push — master ( 03dc98...6f4edb )
by
unknown
9s
created

test_default_user_config_overwrite()   B

Complexity

Conditions 2

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 2
c 2
b 0
f 0
dl 0
loc 24
rs 8.9713
1
# -*- coding: utf-8 -*-
2
3
import os
4
import json
5
6
from click.testing import CliRunner
7
import pytest
8
9
from cookiecutter.__main__ import main
10
from cookiecutter.main import cookiecutter
11
from cookiecutter import utils
12
13
14
@pytest.fixture(scope='session')
15
def cli_runner():
16
    """Fixture that returns a helper function to run the cookiecutter cli."""
17
    runner = CliRunner()
18
19
    def cli_main(*cli_args):
20
        """Run cookiecutter cli main with the given args."""
21
        return runner.invoke(main, cli_args)
22
23
    return cli_main
24
25
26
@pytest.fixture
27
def remove_fake_project_dir(request):
28
    """
29
    Remove the fake project directory created during the tests.
30
    """
31
    def fin_remove_fake_project_dir():
32
        if os.path.isdir('fake-project'):
33
            utils.rmtree('fake-project')
34
    request.addfinalizer(fin_remove_fake_project_dir)
35
36
37
@pytest.fixture
38
def make_fake_project_dir(request):
39
    """Create a fake project to be overwritten in the according tests."""
40
    os.makedirs('fake-project')
41
42
43
@pytest.fixture(params=['-V', '--version'])
44
def version_cli_flag(request):
45
    return request.param
46
47
48
def test_cli_version(cli_runner, version_cli_flag):
49
    result = cli_runner(version_cli_flag)
50
    assert result.exit_code == 0
51
    assert result.output.startswith('Cookiecutter')
52
53
54
@pytest.mark.usefixtures('make_fake_project_dir', 'remove_fake_project_dir')
55
def test_cli_error_on_existing_output_directory(cli_runner):
56
    result = cli_runner('tests/fake-repo-pre/', '--no-input')
57
    assert result.exit_code != 0
58
    expected_error_msg = 'Error: "fake-project" directory already exists\n'
59
    assert result.output == expected_error_msg
60
61
62
@pytest.mark.usefixtures('remove_fake_project_dir')
63
def test_cli(cli_runner):
64
    result = cli_runner('tests/fake-repo-pre/', '--no-input')
65
    assert result.exit_code == 0
66
    assert os.path.isdir('fake-project')
67
    with open(os.path.join('fake-project', 'README.rst')) as f:
68
        assert 'Project name: **Fake Project**' in f.read()
69
70
71
@pytest.mark.usefixtures('remove_fake_project_dir')
72
def test_cli_verbose(cli_runner):
73
    result = cli_runner('tests/fake-repo-pre/', '--no-input', '-v')
74
    assert result.exit_code == 0
75
    assert os.path.isdir('fake-project')
76
    with open(os.path.join('fake-project', 'README.rst')) as f:
77
        assert 'Project name: **Fake Project**' in f.read()
78
79
80
@pytest.mark.usefixtures('remove_fake_project_dir')
81
def test_cli_replay(mocker, cli_runner):
82
    mock_cookiecutter = mocker.patch(
83
        'cookiecutter.cli.cookiecutter'
84
    )
85
86
    template_path = 'tests/fake-repo-pre/'
87
    result = cli_runner(template_path, '--replay', '-v')
88
89
    assert result.exit_code == 0
90
    mock_cookiecutter.assert_called_once_with(
91
        template_path,
92
        None,
93
        False,
94
        replay=True,
95
        overwrite_if_exists=False,
96
        output_dir='.',
97
        config_file=None,
98
        default_config=False,
99
        extra_context=None,
100
    )
101
102
103
@pytest.mark.usefixtures('remove_fake_project_dir')
104
def test_cli_exit_on_noinput_and_replay(mocker, cli_runner):
105
    mock_cookiecutter = mocker.patch(
106
        'cookiecutter.cli.cookiecutter',
107
        side_effect=cookiecutter
108
    )
109
110
    template_path = 'tests/fake-repo-pre/'
111
    result = cli_runner(template_path, '--no-input', '--replay', '-v')
112
113
    assert result.exit_code == 1
114
115
    expected_error_msg = (
116
        "You can not use both replay and no_input or extra_context "
117
        "at the same time."
118
    )
119
120
    assert expected_error_msg in result.output
121
122
    mock_cookiecutter.assert_called_once_with(
123
        template_path,
124
        None,
125
        True,
126
        replay=True,
127
        overwrite_if_exists=False,
128
        output_dir='.',
129
        config_file=None,
130
        default_config=False,
131
        extra_context=None,
132
    )
133
134
135
@pytest.fixture(params=['-f', '--overwrite-if-exists'])
136
def overwrite_cli_flag(request):
137
    return request.param
138
139
140
@pytest.mark.usefixtures('remove_fake_project_dir')
141
def test_run_cookiecutter_on_overwrite_if_exists_and_replay(
142
        mocker, cli_runner, overwrite_cli_flag):
143
    mock_cookiecutter = mocker.patch(
144
        'cookiecutter.cli.cookiecutter',
145
        side_effect=cookiecutter
146
    )
147
148
    template_path = 'tests/fake-repo-pre/'
149
    result = cli_runner(template_path, '--replay', '-v', overwrite_cli_flag)
150
151
    assert result.exit_code == 0
152
153
    mock_cookiecutter.assert_called_once_with(
154
        template_path,
155
        None,
156
        False,
157
        replay=True,
158
        overwrite_if_exists=True,
159
        output_dir='.',
160
        config_file=None,
161
        default_config=False,
162
        extra_context=None,
163
    )
164
165
166
@pytest.mark.usefixtures('remove_fake_project_dir')
167
def test_cli_overwrite_if_exists_when_output_dir_does_not_exist(
168
        cli_runner, overwrite_cli_flag):
169
170
    result = cli_runner(
171
        'tests/fake-repo-pre/',
172
        '--no-input',
173
        overwrite_cli_flag,
174
    )
175
176
    assert result.exit_code == 0
177
    assert os.path.isdir('fake-project')
178
179
180
@pytest.mark.usefixtures('make_fake_project_dir', 'remove_fake_project_dir')
181
def test_cli_overwrite_if_exists_when_output_dir_exists(
182
        cli_runner, overwrite_cli_flag):
183
184
    result = cli_runner(
185
        'tests/fake-repo-pre/',
186
        '--no-input',
187
        overwrite_cli_flag,
188
    )
189
    assert result.exit_code == 0
190
    assert os.path.isdir('fake-project')
191
192
193
@pytest.fixture(params=['-o', '--output-dir'])
194
def output_dir_flag(request):
195
    return request.param
196
197
198
@pytest.fixture
199
def output_dir(tmpdir):
200
    return str(tmpdir.mkdir('output'))
201
202
203
def test_cli_output_dir(mocker, cli_runner, output_dir_flag, output_dir):
204
    mock_cookiecutter = mocker.patch(
205
        'cookiecutter.cli.cookiecutter'
206
    )
207
208
    template_path = 'tests/fake-repo-pre/'
209
    result = cli_runner(template_path, output_dir_flag, output_dir)
210
211
    assert result.exit_code == 0
212
    mock_cookiecutter.assert_called_once_with(
213
        template_path,
214
        None,
215
        False,
216
        replay=False,
217
        overwrite_if_exists=False,
218
        output_dir=output_dir,
219
        config_file=None,
220
        default_config=False,
221
        extra_context=None,
222
    )
223
224
225
@pytest.fixture(params=['-h', '--help', 'help'])
226
def help_cli_flag(request):
227
    return request.param
228
229
230
def test_cli_help(cli_runner, help_cli_flag):
231
    result = cli_runner(help_cli_flag)
232
    assert result.exit_code == 0
233
    assert result.output.startswith('Usage')
234
235
236
@pytest.fixture
237
def user_config_path(tmpdir):
238
    return str(tmpdir.join('tests/config.yaml'))
239
240
241
def test_user_config(mocker, cli_runner, user_config_path):
242
    mock_cookiecutter = mocker.patch(
243
        'cookiecutter.cli.cookiecutter'
244
    )
245
246
    template_path = 'tests/fake-repo-pre/'
247
    result = cli_runner(template_path, '--config-file', user_config_path)
248
249
    assert result.exit_code == 0
250
    mock_cookiecutter.assert_called_once_with(
251
        template_path,
252
        None,
253
        False,
254
        replay=False,
255
        overwrite_if_exists=False,
256
        output_dir='.',
257
        config_file=user_config_path,
258
        default_config=False,
259
        extra_context=None,
260
    )
261
262
263
def test_default_user_config_overwrite(mocker, cli_runner, user_config_path):
264
    mock_cookiecutter = mocker.patch(
265
        'cookiecutter.cli.cookiecutter'
266
    )
267
268
    template_path = 'tests/fake-repo-pre/'
269
    result = cli_runner(
270
        template_path,
271
        '--config-file',
272
        user_config_path,
273
        '--default-config',
274
    )
275
276
    assert result.exit_code == 0
277
    mock_cookiecutter.assert_called_once_with(
278
        template_path,
279
        None,
280
        False,
281
        replay=False,
282
        overwrite_if_exists=False,
283
        output_dir='.',
284
        config_file=user_config_path,
285
        default_config=True,
286
        extra_context=None
287
    )
288
289
290
def test_default_user_config(mocker, cli_runner):
291
    mock_cookiecutter = mocker.patch(
292
        'cookiecutter.cli.cookiecutter'
293
    )
294
295
    template_path = 'tests/fake-repo-pre/'
296
    result = cli_runner(template_path, '--default-config')
297
298
    assert result.exit_code == 0
299
    mock_cookiecutter.assert_called_once_with(
300
        template_path,
301
        None,
302
        False,
303
        replay=False,
304
        overwrite_if_exists=False,
305
        output_dir='.',
306
        config_file=None,
307
        default_config=True,
308
        extra_context=None,
309
    )
310
311
312
def test_echo_undefined_variable_error(tmpdir, cli_runner):
313
    output_dir = str(tmpdir.mkdir('output'))
314
    template_path = 'tests/undefined-variable/file-name/'
315
316
    result = cli_runner(
317
        '--no-input',
318
        '--default-config',
319
        '--output-dir',
320
        output_dir,
321
        template_path,
322
    )
323
324
    assert result.exit_code == 1
325
326
    error = "Unable to create file '{{cookiecutter.foobar}}'"
327
    assert error in result.output
328
329
    message = "Error message: 'dict object' has no attribute 'foobar'"
330
    assert message in result.output
331
332
    context = {
333
        'cookiecutter': {
334
            'github_username': 'hackebrot',
335
            'project_slug': 'testproject'
336
        }
337
    }
338
    context_str = json.dumps(context, indent=4, sort_keys=True)
339
    assert context_str in result.output
340
341
342
def test_echo_unknown_extension_error(tmpdir, cli_runner):
343
    output_dir = str(tmpdir.mkdir('output'))
344
    template_path = 'tests/test-extensions/unknown/'
345
346
    result = cli_runner(
347
        '--no-input',
348
        '--default-config',
349
        '--output-dir',
350
        output_dir,
351
        template_path,
352
    )
353
354
    assert result.exit_code == 1
355
356
    assert 'Unable to load extension: ' in result.output
357
358
359
@pytest.mark.usefixtures('remove_fake_project_dir')
360
def test_cli_extra_context(cli_runner):
361
    result = cli_runner(
362
        'tests/fake-repo-pre/',
363
        '--no-input',
364
        '-v',
365
        'project_name=Awesomez',
366
    )
367
    assert result.exit_code == 0
368
    assert os.path.isdir('fake-project')
369
    with open(os.path.join('fake-project', 'README.rst')) as f:
370
        assert 'Project name: **Awesomez**' in f.read()
371
372
373
@pytest.mark.usefixtures('remove_fake_project_dir')
374
def test_cli_extra_context_invalid_format(cli_runner):
375
    result = cli_runner(
376
        'tests/fake-repo-pre/',
377
        '--no-input',
378
        '-v',
379
        'ExtraContextWithNoEqualsSoInvalid',
380
    )
381
    assert result.exit_code == 2
382
    assert 'Error: Invalid value for "extra_context"' in result.output
383
    assert 'should contain items of the form key=value' in result.output
384
385
386
@pytest.fixture
387
def debug_file(tmpdir):
388
    return tmpdir / 'fake-repo.log'
389
390
391
@pytest.mark.usefixtures('remove_fake_project_dir')
392
def test_debug_file_non_verbose(cli_runner, debug_file):
393
    assert not debug_file.exists()
394
395
    result = cli_runner(
396
        '--no-input',
397
        '--debug-file',
398
        str(debug_file),
399
        'tests/fake-repo-pre/',
400
    )
401
    assert result.exit_code == 0
402
403
    assert debug_file.exists()
404
405
    context_log = (
406
        "DEBUG cookiecutter.main: context_file is "
407
        "tests/fake-repo-pre/cookiecutter.json"
408
    )
409
    assert context_log in debug_file.readlines(cr=False)
410
    assert context_log not in result.output
411
412
413
@pytest.mark.usefixtures('remove_fake_project_dir')
414
def test_debug_file_verbose(cli_runner, debug_file):
415
    assert not debug_file.exists()
416
417
    result = cli_runner(
418
        '--verbose',
419
        '--no-input',
420
        '--debug-file',
421
        str(debug_file),
422
        'tests/fake-repo-pre/',
423
    )
424
    assert result.exit_code == 0
425
426
    assert debug_file.exists()
427
428
    context_log = (
429
        "DEBUG cookiecutter.main: context_file is "
430
        "tests/fake-repo-pre/cookiecutter.json"
431
    )
432
    assert context_log in debug_file.readlines(cr=False)
433
    assert context_log in result.output
434