Completed
Push — master ( 56245b...a9d00e )
by
unknown
38s
created

test_run_cookiecutter_on_overwrite_if_exists_and_replay()   B

Complexity

Conditions 2

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
dl 0
loc 24
rs 8.9713
c 0
b 0
f 0
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
        password=None
101
    )
102
103
104
@pytest.mark.usefixtures('remove_fake_project_dir')
105
def test_cli_exit_on_noinput_and_replay(mocker, cli_runner):
106
    mock_cookiecutter = mocker.patch(
107
        'cookiecutter.cli.cookiecutter',
108
        side_effect=cookiecutter
109
    )
110
111
    template_path = 'tests/fake-repo-pre/'
112
    result = cli_runner(template_path, '--no-input', '--replay', '-v')
113
114
    assert result.exit_code == 1
115
116
    expected_error_msg = (
117
        "You can not use both replay and no_input or extra_context "
118
        "at the same time."
119
    )
120
121
    assert expected_error_msg in result.output
122
123
    mock_cookiecutter.assert_called_once_with(
124
        template_path,
125
        None,
126
        True,
127
        replay=True,
128
        overwrite_if_exists=False,
129
        output_dir='.',
130
        config_file=None,
131
        default_config=False,
132
        extra_context=None,
133
        password=None,
134
    )
135
136
137
@pytest.fixture(params=['-f', '--overwrite-if-exists'])
138
def overwrite_cli_flag(request):
139
    return request.param
140
141
142
@pytest.mark.usefixtures('remove_fake_project_dir')
143
def test_run_cookiecutter_on_overwrite_if_exists_and_replay(
144
        mocker, cli_runner, overwrite_cli_flag):
145
    mock_cookiecutter = mocker.patch(
146
        'cookiecutter.cli.cookiecutter',
147
        side_effect=cookiecutter
148
    )
149
150
    template_path = 'tests/fake-repo-pre/'
151
    result = cli_runner(template_path, '--replay', '-v', overwrite_cli_flag)
152
153
    assert result.exit_code == 0
154
155
    mock_cookiecutter.assert_called_once_with(
156
        template_path,
157
        None,
158
        False,
159
        replay=True,
160
        overwrite_if_exists=True,
161
        output_dir='.',
162
        config_file=None,
163
        default_config=False,
164
        extra_context=None,
165
        password=None,
166
    )
167
168
169
@pytest.mark.usefixtures('remove_fake_project_dir')
170
def test_cli_overwrite_if_exists_when_output_dir_does_not_exist(
171
        cli_runner, overwrite_cli_flag):
172
173
    result = cli_runner(
174
        'tests/fake-repo-pre/',
175
        '--no-input',
176
        overwrite_cli_flag,
177
    )
178
179
    assert result.exit_code == 0
180
    assert os.path.isdir('fake-project')
181
182
183
@pytest.mark.usefixtures('make_fake_project_dir', 'remove_fake_project_dir')
184
def test_cli_overwrite_if_exists_when_output_dir_exists(
185
        cli_runner, overwrite_cli_flag):
186
187
    result = cli_runner(
188
        'tests/fake-repo-pre/',
189
        '--no-input',
190
        overwrite_cli_flag,
191
    )
192
    assert result.exit_code == 0
193
    assert os.path.isdir('fake-project')
194
195
196
@pytest.fixture(params=['-o', '--output-dir'])
197
def output_dir_flag(request):
198
    return request.param
199
200
201
@pytest.fixture
202
def output_dir(tmpdir):
203
    return str(tmpdir.mkdir('output'))
204
205
206
def test_cli_output_dir(mocker, cli_runner, output_dir_flag, output_dir):
207
    mock_cookiecutter = mocker.patch(
208
        'cookiecutter.cli.cookiecutter'
209
    )
210
211
    template_path = 'tests/fake-repo-pre/'
212
    result = cli_runner(template_path, output_dir_flag, output_dir)
213
214
    assert result.exit_code == 0
215
    mock_cookiecutter.assert_called_once_with(
216
        template_path,
217
        None,
218
        False,
219
        replay=False,
220
        overwrite_if_exists=False,
221
        output_dir=output_dir,
222
        config_file=None,
223
        default_config=False,
224
        extra_context=None,
225
        password=None,
226
    )
227
228
229
@pytest.fixture(params=['-h', '--help', 'help'])
230
def help_cli_flag(request):
231
    return request.param
232
233
234
def test_cli_help(cli_runner, help_cli_flag):
235
    result = cli_runner(help_cli_flag)
236
    assert result.exit_code == 0
237
    assert result.output.startswith('Usage')
238
239
240
@pytest.fixture
241
def user_config_path(tmpdir):
242
    return str(tmpdir.join('tests/config.yaml'))
243
244
245
def test_user_config(mocker, cli_runner, user_config_path):
246
    mock_cookiecutter = mocker.patch(
247
        'cookiecutter.cli.cookiecutter'
248
    )
249
250
    template_path = 'tests/fake-repo-pre/'
251
    result = cli_runner(template_path, '--config-file', user_config_path)
252
253
    assert result.exit_code == 0
254
    mock_cookiecutter.assert_called_once_with(
255
        template_path,
256
        None,
257
        False,
258
        replay=False,
259
        overwrite_if_exists=False,
260
        output_dir='.',
261
        config_file=user_config_path,
262
        default_config=False,
263
        extra_context=None,
264
        password=None,
265
    )
266
267
268
def test_default_user_config_overwrite(mocker, cli_runner, user_config_path):
269
    mock_cookiecutter = mocker.patch(
270
        'cookiecutter.cli.cookiecutter'
271
    )
272
273
    template_path = 'tests/fake-repo-pre/'
274
    result = cli_runner(
275
        template_path,
276
        '--config-file',
277
        user_config_path,
278
        '--default-config',
279
    )
280
281
    assert result.exit_code == 0
282
    mock_cookiecutter.assert_called_once_with(
283
        template_path,
284
        None,
285
        False,
286
        replay=False,
287
        overwrite_if_exists=False,
288
        output_dir='.',
289
        config_file=user_config_path,
290
        default_config=True,
291
        extra_context=None,
292
        password=None,
293
    )
294
295
296
def test_default_user_config(mocker, cli_runner):
297
    mock_cookiecutter = mocker.patch(
298
        'cookiecutter.cli.cookiecutter'
299
    )
300
301
    template_path = 'tests/fake-repo-pre/'
302
    result = cli_runner(template_path, '--default-config')
303
304
    assert result.exit_code == 0
305
    mock_cookiecutter.assert_called_once_with(
306
        template_path,
307
        None,
308
        False,
309
        replay=False,
310
        overwrite_if_exists=False,
311
        output_dir='.',
312
        config_file=None,
313
        default_config=True,
314
        extra_context=None,
315
        password=None,
316
    )
317
318
319
def test_echo_undefined_variable_error(tmpdir, cli_runner):
320
    output_dir = str(tmpdir.mkdir('output'))
321
    template_path = 'tests/undefined-variable/file-name/'
322
323
    result = cli_runner(
324
        '--no-input',
325
        '--default-config',
326
        '--output-dir',
327
        output_dir,
328
        template_path,
329
    )
330
331
    assert result.exit_code == 1
332
333
    error = "Unable to create file '{{cookiecutter.foobar}}'"
334
    assert error in result.output
335
336
    message = "Error message: 'dict object' has no attribute 'foobar'"
337
    assert message in result.output
338
339
    context = {
340
        'cookiecutter': {
341
            'github_username': 'hackebrot',
342
            'project_slug': 'testproject',
343
            '_template': template_path
344
        }
345
    }
346
    context_str = json.dumps(context, indent=4, sort_keys=True)
347
    assert context_str in result.output
348
349
350
def test_echo_unknown_extension_error(tmpdir, cli_runner):
351
    output_dir = str(tmpdir.mkdir('output'))
352
    template_path = 'tests/test-extensions/unknown/'
353
354
    result = cli_runner(
355
        '--no-input',
356
        '--default-config',
357
        '--output-dir',
358
        output_dir,
359
        template_path,
360
    )
361
362
    assert result.exit_code == 1
363
364
    assert 'Unable to load extension: ' in result.output
365
366
367
@pytest.mark.usefixtures('remove_fake_project_dir')
368
def test_cli_extra_context(cli_runner):
369
    result = cli_runner(
370
        'tests/fake-repo-pre/',
371
        '--no-input',
372
        '-v',
373
        'project_name=Awesomez',
374
    )
375
    assert result.exit_code == 0
376
    assert os.path.isdir('fake-project')
377
    with open(os.path.join('fake-project', 'README.rst')) as f:
378
        assert 'Project name: **Awesomez**' in f.read()
379
380
381
@pytest.mark.usefixtures('remove_fake_project_dir')
382
def test_cli_extra_context_invalid_format(cli_runner):
383
    result = cli_runner(
384
        'tests/fake-repo-pre/',
385
        '--no-input',
386
        '-v',
387
        'ExtraContextWithNoEqualsSoInvalid',
388
    )
389
    assert result.exit_code == 2
390
    assert 'Error: Invalid value for "extra_context"' in result.output
391
    assert 'should contain items of the form key=value' in result.output
392
393
394
@pytest.fixture
395
def debug_file(tmpdir):
396
    return tmpdir / 'fake-repo.log'
397
398
399
@pytest.mark.usefixtures('remove_fake_project_dir')
400
def test_debug_file_non_verbose(cli_runner, debug_file):
401
    assert not debug_file.exists()
402
403
    result = cli_runner(
404
        '--no-input',
405
        '--debug-file',
406
        str(debug_file),
407
        'tests/fake-repo-pre/',
408
    )
409
    assert result.exit_code == 0
410
411
    assert debug_file.exists()
412
413
    context_log = (
414
        "DEBUG cookiecutter.main: context_file is "
415
        "tests/fake-repo-pre/cookiecutter.json"
416
    )
417
    assert context_log in debug_file.readlines(cr=False)
418
    assert context_log not in result.output
419
420
421
@pytest.mark.usefixtures('remove_fake_project_dir')
422
def test_debug_file_verbose(cli_runner, debug_file):
423
    assert not debug_file.exists()
424
425
    result = cli_runner(
426
        '--verbose',
427
        '--no-input',
428
        '--debug-file',
429
        str(debug_file),
430
        'tests/fake-repo-pre/',
431
    )
432
    assert result.exit_code == 0
433
434
    assert debug_file.exists()
435
436
    context_log = (
437
        "DEBUG cookiecutter.main: context_file is "
438
        "tests/fake-repo-pre/cookiecutter.json"
439
    )
440
    assert context_log in debug_file.readlines(cr=False)
441
    assert context_log in result.output
442