Passed
Push — master ( 19f40f...52daf0 )
by Andrey
01:36 queued 11s
created

test_keep_project_dir_on_failure()   A

Complexity

Conditions 2

Size

Total Lines 10
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 8
dl 0
loc 10
rs 10
c 0
b 0
f 0
cc 2
nop 2
1
"""Tests for `generate_files` function and related errors raising.
2
3
Use the global clean_system fixture and run additional teardown code to remove
4
some special folders.
5
"""
6
from pathlib import Path
7
8
import pytest
9
from binaryornot.check import is_binary
10
11
from cookiecutter import exceptions, generate
12
13
14
@pytest.mark.parametrize('invalid_dirname', ['', '{foo}', '{{foo', 'bar}}'])
15
def test_ensure_dir_is_templated_raises(invalid_dirname):
16
    """Verify `ensure_dir_is_templated` raises on wrong directories names input."""
17
    with pytest.raises(exceptions.NonTemplatedInputDirException):
18
        generate.ensure_dir_is_templated(invalid_dirname)
19
20
21
def test_generate_files_nontemplated_exception(tmp_path):
22
    """
23
    Verify `generate_files` raises when no directories to render exist.
24
25
    Note: Check `tests/test-generate-files-nontemplated` location to understand.
26
    """
27
    with pytest.raises(exceptions.NonTemplatedInputDirException):
28
        generate.generate_files(
29
            context={'cookiecutter': {'food': 'pizza'}},
30
            repo_dir='tests/test-generate-files-nontemplated',
31
            output_dir=tmp_path,
32
        )
33
34
35
def test_generate_files(tmp_path):
36
    """Verify directory name correctly rendered with unicode containing context."""
37
    generate.generate_files(
38
        context={'cookiecutter': {'food': 'pizzä'}},
39
        repo_dir='tests/test-generate-files',
40
        output_dir=tmp_path,
41
    )
42
43
    simple_file = Path(tmp_path, 'inputpizzä/simple.txt')
44
    assert simple_file.exists()
45
    assert simple_file.is_file()
46
47
    simple_text = open(simple_file, encoding='utf-8').read()
48
    assert simple_text == 'I eat pizzä'
49
50
51 View Code Duplication
def test_generate_files_with_linux_newline(tmp_path):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
52
    """Verify new line not removed by templating engine after folder generation."""
53
    generate.generate_files(
54
        context={'cookiecutter': {'food': 'pizzä'}},
55
        repo_dir='tests/test-generate-files',
56
        output_dir=tmp_path,
57
    )
58
59
    newline_file = Path(tmp_path, 'inputpizzä/simple-with-newline.txt')
60
    assert newline_file.is_file()
61
    assert newline_file.exists()
62
63
    with open(newline_file, encoding='utf-8', newline='') as f:
64
        simple_text = f.readline()
65
    assert simple_text == 'newline is LF\n'
66
    assert f.newlines == '\n'
67
68
69
def test_generate_files_with_jinja2_environment(tmp_path):
70
    """Extend StrictEnvironment with _jinja2_env_vars cookiecutter template option."""
71
    generate.generate_files(
72
        context={
73
            'cookiecutter': {
74
                'food': 'pizzä',
75
                '_jinja2_env_vars': {'lstrip_blocks': True, 'trim_blocks': True},
76
            }
77
        },
78
        repo_dir='tests/test-generate-files',
79
        output_dir=tmp_path,
80
    )
81
82
    conditions_file = tmp_path.joinpath('inputpizzä/simple-with-conditions.txt')
83
    assert conditions_file.is_file()
84
    assert conditions_file.exists()
85
86
    simple_text = conditions_file.open('rt', encoding='utf-8').read()
87
    assert simple_text == 'I eat pizzä\n'
88
89
90 View Code Duplication
def test_generate_files_with_trailing_newline_forced_to_linux_by_context(tmp_path):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
91
    """Verify new line not removed by templating engine after folder generation."""
92
    generate.generate_files(
93
        context={'cookiecutter': {'food': 'pizzä', '_new_lines': '\r\n'}},
94
        repo_dir='tests/test-generate-files',
95
        output_dir=tmp_path,
96
    )
97
98
    # assert 'Overwritting endline character with %s' in caplog.messages
99
    newline_file = Path(tmp_path, 'inputpizzä/simple-with-newline.txt')
100
    assert newline_file.is_file()
101
    assert newline_file.exists()
102
103
    with open(newline_file, encoding='utf-8', newline='') as f:
104
        simple_text = f.readline()
105
    assert simple_text == 'newline is LF\r\n'
106
    assert f.newlines == '\r\n'
107
108
109 View Code Duplication
def test_generate_files_with_windows_newline(tmp_path):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
110
    """Verify windows source line end not changed during files generation."""
111
    generate.generate_files(
112
        context={'cookiecutter': {'food': 'pizzä'}},
113
        repo_dir='tests/test-generate-files',
114
        output_dir=tmp_path,
115
    )
116
117
    newline_file = Path(tmp_path, 'inputpizzä/simple-with-newline-crlf.txt')
118
    assert newline_file.is_file()
119
    assert newline_file.exists()
120
121
    with open(newline_file, encoding='utf-8', newline='') as f:
122
        simple_text = f.readline()
123
    assert simple_text == 'newline is CRLF\r\n'
124
    assert f.newlines == '\r\n'
125
126
127 View Code Duplication
def test_generate_files_with_windows_newline_forced_to_linux_by_context(tmp_path):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
128
    """Verify windows line end changed to linux during files generation."""
129
    generate.generate_files(
130
        context={'cookiecutter': {'food': 'pizzä', '_new_lines': '\n'}},
131
        repo_dir='tests/test-generate-files',
132
        output_dir=tmp_path,
133
    )
134
135
    newline_file = Path(tmp_path, 'inputpizzä/simple-with-newline-crlf.txt')
136
    assert newline_file.is_file()
137
    assert newline_file.exists()
138
139
    with open(newline_file, encoding='utf-8', newline='') as f:
140
        simple_text = f.readline()
141
142
    assert simple_text == 'newline is CRLF\n'
143
    assert f.newlines == '\n'
144
145
146
def test_generate_files_binaries(tmp_path):
147
    """Verify binary files created during directory generation."""
148
    generate.generate_files(
149
        context={'cookiecutter': {'binary_test': 'binary_files'}},
150
        repo_dir='tests/test-generate-binaries',
151
        output_dir=tmp_path,
152
    )
153
154
    dst_dir = Path(tmp_path, 'inputbinary_files')
155
156
    assert is_binary(str(Path(dst_dir, 'logo.png')))
157
    assert is_binary(str(Path(dst_dir, '.DS_Store')))
158
    assert not is_binary(str(Path(dst_dir, 'readme.txt')))
159
    assert is_binary(str(Path(dst_dir, 'some_font.otf')))
160
    assert is_binary(str(Path(dst_dir, 'binary_files/logo.png')))
161
    assert is_binary(str(Path(dst_dir, 'binary_files/.DS_Store')))
162
    assert not is_binary(str(Path(dst_dir, 'binary_files/readme.txt')))
163
    assert is_binary(str(Path(dst_dir, 'binary_files/some_font.otf')))
164
    assert is_binary(str(Path(dst_dir, 'binary_files/binary_files/logo.png')))
165
166
167
def test_generate_files_absolute_path(tmp_path):
168
    """Verify usage of absolute path does not change files generation behaviour."""
169
    generate.generate_files(
170
        context={'cookiecutter': {'food': 'pizzä'}},
171
        repo_dir=Path('tests/test-generate-files').absolute(),
172
        output_dir=tmp_path,
173
    )
174
    assert Path(tmp_path, 'inputpizzä/simple.txt').is_file()
175
176
177
def test_generate_files_output_dir(tmp_path):
178
    """Verify `output_dir` option for `generate_files` changing location correctly."""
179
    output_dir = Path(tmp_path, 'custom_output_dir')
180
    output_dir.mkdir()
181
182
    project_dir = generate.generate_files(
183
        context={'cookiecutter': {'food': 'pizzä'}},
184
        repo_dir=Path('tests/test-generate-files').absolute(),
185
        output_dir=output_dir,
186
    )
187
188
    assert Path(output_dir, 'inputpizzä/simple.txt').exists()
189
    assert Path(output_dir, 'inputpizzä/simple.txt').is_file()
190
    assert Path(project_dir) == Path(tmp_path, 'custom_output_dir/inputpizzä')
191
192
193
def test_generate_files_permissions(tmp_path):
194
    """Verify generates files respect source files permissions.
195
196
    simple.txt and script.sh should retain their respective 0o644 and 0o755
197
    permissions.
198
    """
199
    generate.generate_files(
200
        context={'cookiecutter': {'permissions': 'permissions'}},
201
        repo_dir='tests/test-generate-files-permissions',
202
        output_dir=tmp_path,
203
    )
204
205
    assert Path(tmp_path, 'inputpermissions/simple.txt').exists()
206
    assert Path(tmp_path, 'inputpermissions/simple.txt').is_file()
207
208
    # Verify source simple.txt should still be 0o644
209
    tests_simple_file = Path(
210
        'tests',
211
        'test-generate-files-permissions',
212
        'input{{cookiecutter.permissions}}',
213
        'simple.txt',
214
    )
215
    tests_simple_file_mode = tests_simple_file.stat().st_mode
216
217
    input_simple_file = Path(tmp_path, 'inputpermissions', 'simple.txt')
218
    input_simple_file_mode = input_simple_file.stat().st_mode
219
    assert tests_simple_file_mode == input_simple_file_mode
220
221
    assert Path(tmp_path, 'inputpermissions/script.sh').exists()
222
    assert Path(tmp_path, 'inputpermissions/script.sh').is_file()
223
224
    # Verify source script.sh should still be 0o755
225
    tests_script_file = Path(
226
        'tests',
227
        'test-generate-files-permissions',
228
        'input{{cookiecutter.permissions}}',
229
        'script.sh',
230
    )
231
    tests_script_file_mode = tests_script_file.stat().st_mode
232
233
    input_script_file = Path(tmp_path, 'inputpermissions', 'script.sh')
234
    input_script_file_mode = input_script_file.stat().st_mode
235
    assert tests_script_file_mode == input_script_file_mode
236
237
238 View Code Duplication
def test_generate_files_with_overwrite_if_exists_with_skip_if_file_exists(tmp_path):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
239
    """Verify `skip_if_file_exist` has priority over `overwrite_if_exists`."""
240
    simple_file = Path(tmp_path, 'inputpizzä/simple.txt')
241
    simple_with_new_line_file = Path(tmp_path, 'inputpizzä/simple-with-newline.txt')
242
243
    Path(tmp_path, 'inputpizzä').mkdir(parents=True)
244
    with open(simple_file, 'w') as f:
245
        f.write('temp')
246
247
    generate.generate_files(
248
        context={'cookiecutter': {'food': 'pizzä'}},
249
        repo_dir='tests/test-generate-files',
250
        overwrite_if_exists=True,
251
        skip_if_file_exists=True,
252
        output_dir=tmp_path,
253
    )
254
255
    assert Path(simple_file).is_file()
256
    assert Path(simple_file).exists()
257
    assert Path(simple_with_new_line_file).is_file()
258
    assert Path(simple_with_new_line_file).exists()
259
260
    simple_text = open(simple_file, encoding='utf-8').read()
261
    assert simple_text == 'temp'
262
263
264 View Code Duplication
def test_generate_files_with_skip_if_file_exists(tmp_path):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
265
    """Verify existed files not removed if error raised with `skip_if_file_exists`."""
266
    simple_file = Path(tmp_path, 'inputpizzä/simple.txt')
267
    simple_with_new_line_file = Path(tmp_path, 'inputpizzä/simple-with-newline.txt')
268
269
    Path(tmp_path, 'inputpizzä').mkdir(parents=True)
270
    with open(simple_file, 'w') as f:
271
        f.write('temp')
272
273
    with pytest.raises(exceptions.OutputDirExistsException):
274
        generate.generate_files(
275
            context={'cookiecutter': {'food': 'pizzä'}},
276
            repo_dir='tests/test-generate-files',
277
            skip_if_file_exists=True,
278
            output_dir=tmp_path,
279
        )
280
281
    assert Path(simple_file).is_file()
282
    assert Path(simple_file).exists()
283
    assert not Path(simple_with_new_line_file).is_file()
284
    assert not Path(simple_with_new_line_file).exists()
285
286
    simple_text = open(simple_file, encoding='utf-8').read()
287
    assert simple_text == 'temp'
288
289
290 View Code Duplication
def test_generate_files_with_overwrite_if_exists(tmp_path):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
291
    """Verify overwrite_if_exists overwrites old files."""
292
    simple_file = Path(tmp_path, 'inputpizzä/simple.txt')
293
    simple_with_new_line_file = Path(tmp_path, 'inputpizzä/simple-with-newline.txt')
294
295
    Path(tmp_path, 'inputpizzä').mkdir(parents=True)
296
    with open(simple_file, 'w') as f:
297
        f.write('temp')
298
299
    generate.generate_files(
300
        context={'cookiecutter': {'food': 'pizzä'}},
301
        repo_dir='tests/test-generate-files',
302
        overwrite_if_exists=True,
303
        output_dir=tmp_path,
304
    )
305
306
    assert Path(simple_file).is_file()
307
    assert Path(simple_file).exists()
308
    assert Path(simple_with_new_line_file).is_file()
309
    assert Path(simple_with_new_line_file).exists()
310
311
    simple_text = open(simple_file, encoding='utf-8').read()
312
    assert simple_text == 'I eat pizzä'
313
314
315
@pytest.fixture
316
def undefined_context():
317
    """Fixture. Populate context variable for future tests."""
318
    return {
319
        'cookiecutter': {'project_slug': 'testproject', 'github_username': 'hackebrot'}
320
    }
321
322
323
def test_raise_undefined_variable_file_name(output_dir, undefined_context):
324
    """Verify correct error raised when file name cannot be rendered."""
325
    with pytest.raises(exceptions.UndefinedVariableInTemplate) as err:
326
        generate.generate_files(
327
            repo_dir='tests/undefined-variable/file-name/',
328
            output_dir=output_dir,
329
            context=undefined_context,
330
        )
331
    error = err.value
332
    assert "Unable to create file '{{cookiecutter.foobar}}'" == error.message
333
    assert error.context == undefined_context
334
335
    assert not Path(output_dir).joinpath('testproject').exists()
336
337
338 View Code Duplication
def test_raise_undefined_variable_file_name_existing_project(
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
339
    output_dir, undefined_context
340
):
341
    """Verify correct error raised when file name cannot be rendered."""
342
    testproj_path = Path(output_dir, 'testproject')
343
    testproj_path.mkdir()
344
345
    with pytest.raises(exceptions.UndefinedVariableInTemplate) as err:
346
        generate.generate_files(
347
            repo_dir='tests/undefined-variable/file-name/',
348
            output_dir=output_dir,
349
            context=undefined_context,
350
            overwrite_if_exists=True,
351
        )
352
    error = err.value
353
    assert "Unable to create file '{{cookiecutter.foobar}}'" == error.message
354
    assert error.context == undefined_context
355
356
    assert testproj_path.exists()
357
358
359
def test_raise_undefined_variable_file_content(output_dir, undefined_context):
360
    """Verify correct error raised when file content cannot be rendered."""
361
    with pytest.raises(exceptions.UndefinedVariableInTemplate) as err:
362
        generate.generate_files(
363
            repo_dir='tests/undefined-variable/file-content/',
364
            output_dir=output_dir,
365
            context=undefined_context,
366
        )
367
    error = err.value
368
    assert "Unable to create file 'README.rst'" == error.message
369
    assert error.context == undefined_context
370
371
    assert not Path(output_dir).joinpath('testproject').exists()
372
373
374
def test_raise_undefined_variable_dir_name(output_dir, undefined_context):
375
    """Verify correct error raised when directory name cannot be rendered."""
376
    with pytest.raises(exceptions.UndefinedVariableInTemplate) as err:
377
        generate.generate_files(
378
            repo_dir='tests/undefined-variable/dir-name/',
379
            output_dir=output_dir,
380
            context=undefined_context,
381
        )
382
    error = err.value
383
384
    directory = Path('testproject', '{{cookiecutter.foobar}}')
385
    msg = f"Unable to create directory '{directory}'"
386
    assert msg == error.message
387
388
    assert error.context == undefined_context
389
390
    assert not Path(output_dir).joinpath('testproject').exists()
391
392
393
def test_keep_project_dir_on_failure(output_dir, undefined_context):
394
    """Verify correct error raised when directory name cannot be rendered."""
395
    with pytest.raises(exceptions.UndefinedVariableInTemplate):
396
        generate.generate_files(
397
            repo_dir='tests/undefined-variable/dir-name/',
398
            output_dir=output_dir,
399
            context=undefined_context,
400
            keep_project_on_failure=True,
401
        )
402
    assert Path(output_dir).joinpath('testproject').exists()
403
404
405 View Code Duplication
def test_raise_undefined_variable_dir_name_existing_project(
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
406
    output_dir, undefined_context
407
):
408
    """Verify correct error raised when directory name cannot be rendered."""
409
    testproj_path = Path(output_dir, 'testproject')
410
    testproj_path.mkdir()
411
412
    with pytest.raises(exceptions.UndefinedVariableInTemplate) as err:
413
        generate.generate_files(
414
            repo_dir='tests/undefined-variable/dir-name/',
415
            output_dir=output_dir,
416
            context=undefined_context,
417
            overwrite_if_exists=True,
418
        )
419
    error = err.value
420
421
    directory = Path('testproject', '{{cookiecutter.foobar}}')
422
    msg = f"Unable to create directory '{directory}'"
423
    assert msg == error.message
424
425
    assert error.context == undefined_context
426
427
    assert testproj_path.exists()
428
429
430
def test_raise_undefined_variable_project_dir(tmp_path):
431
    """Verify correct error raised when directory name cannot be rendered."""
432
    with pytest.raises(exceptions.UndefinedVariableInTemplate) as err:
433
        generate.generate_files(
434
            repo_dir='tests/undefined-variable/dir-name/',
435
            output_dir=tmp_path,
436
            context={},
437
        )
438
    error = err.value
439
    msg = "Unable to create project directory '{{cookiecutter.project_slug}}'"
440
    assert msg == error.message
441
    assert error.context == {}
442
443
    assert not Path(tmp_path, 'testproject').exists()
444