Passed
Push — master ( a7bde6...b29ecb )
by
unknown
01:08
created

tests.test_cli.test_directory_repo()   A

Complexity

Conditions 2

Size

Total Lines 12
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

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