Issues (31)

tests/test_generate_files.py (1 issue)

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 = Path(simple_file).read_text(encoding='utf-8')
48
    assert simple_text == 'I eat pizzä'
49
50
51 View Code Duplication
def test_generate_files_with_linux_newline(tmp_path):
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 Path(newline_file).open(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.read_text(encoding='utf-8')
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):
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 Path(newline_file).open(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):
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 Path(newline_file).open(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):
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 Path(newline_file).open(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').is_file()
206
207
    # Verify source simple.txt should still be 0o644
208
    tests_simple_file = Path(
209
        'tests',
210
        'test-generate-files-permissions',
211
        'input{{cookiecutter.permissions}}',
212
        'simple.txt',
213
    )
214
    tests_simple_file_mode = tests_simple_file.stat().st_mode
215
216
    input_simple_file = Path(tmp_path, 'inputpermissions', 'simple.txt')
217
    input_simple_file_mode = input_simple_file.stat().st_mode
218
    assert tests_simple_file_mode == input_simple_file_mode
219
220
    assert Path(tmp_path, 'inputpermissions/script.sh').exists()
221
    assert Path(tmp_path, 'inputpermissions/script.sh').is_file()
222
223
    # Verify source script.sh should still be 0o755
224
    tests_script_file = Path(
225
        'tests',
226
        'test-generate-files-permissions',
227
        'input{{cookiecutter.permissions}}',
228
        'script.sh',
229
    )
230
    tests_script_file_mode = tests_script_file.stat().st_mode
231
232
    input_script_file = Path(tmp_path, 'inputpermissions', 'script.sh')
233
    input_script_file_mode = input_script_file.stat().st_mode
234
    assert tests_script_file_mode == input_script_file_mode
235
236
237 View Code Duplication
def test_generate_files_with_overwrite_if_exists_with_skip_if_file_exists(tmp_path):
238
    """Verify `skip_if_file_exist` has priority over `overwrite_if_exists`."""
239
    simple_file = Path(tmp_path, 'inputpizzä/simple.txt')
240
    simple_with_new_line_file = Path(tmp_path, 'inputpizzä/simple-with-newline.txt')
241
242
    Path(tmp_path, 'inputpizzä').mkdir(parents=True)
243
    with Path(simple_file).open('w') as f:
244
        f.write('temp')
245
246
    generate.generate_files(
247
        context={'cookiecutter': {'food': 'pizzä'}},
248
        repo_dir='tests/test-generate-files',
249
        overwrite_if_exists=True,
250
        skip_if_file_exists=True,
251
        output_dir=tmp_path,
252
    )
253
254
    assert Path(simple_file).is_file()
255
    assert Path(simple_file).exists()
256
    assert Path(simple_with_new_line_file).is_file()
257
    assert Path(simple_with_new_line_file).exists()
258
259
    simple_text = Path(simple_file).read_text(encoding='utf-8')
260
    assert simple_text == 'temp'
261
262
263 View Code Duplication
def test_generate_files_with_skip_if_file_exists(tmp_path):
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
264
    """Verify existed files not removed if error raised with `skip_if_file_exists`."""
265
    simple_file = Path(tmp_path, 'inputpizzä/simple.txt')
266
    simple_with_new_line_file = Path(tmp_path, 'inputpizzä/simple-with-newline.txt')
267
268
    Path(tmp_path, 'inputpizzä').mkdir(parents=True)
269
    Path(simple_file).write_text('temp')
270
271
    with pytest.raises(exceptions.OutputDirExistsException):
272
        generate.generate_files(
273
            context={'cookiecutter': {'food': 'pizzä'}},
274
            repo_dir='tests/test-generate-files',
275
            skip_if_file_exists=True,
276
            output_dir=tmp_path,
277
        )
278
279
    assert Path(simple_file).is_file()
280
    assert not Path(simple_with_new_line_file).is_file()
281
    assert not Path(simple_with_new_line_file).exists()
282
283
    simple_text = Path(simple_file).read_text(encoding='utf-8')
284
    assert simple_text == 'temp'
285
286
287 View Code Duplication
def test_generate_files_with_overwrite_if_exists(tmp_path):
288
    """Verify overwrite_if_exists overwrites old files."""
289
    simple_file = Path(tmp_path, 'inputpizzä/simple.txt')
290
    simple_with_new_line_file = Path(tmp_path, 'inputpizzä/simple-with-newline.txt')
291
292
    Path(tmp_path, 'inputpizzä').mkdir(parents=True)
293
    Path(simple_file).write_text('temp')
294
295
    generate.generate_files(
296
        context={'cookiecutter': {'food': 'pizzä'}},
297
        repo_dir='tests/test-generate-files',
298
        overwrite_if_exists=True,
299
        output_dir=tmp_path,
300
    )
301
302
    assert Path(simple_file).is_file()
303
    assert Path(simple_file).exists()
304
    assert Path(simple_with_new_line_file).is_file()
305
    assert Path(simple_with_new_line_file).exists()
306
307
    simple_text = Path(simple_file).read_text(encoding='utf-8')
308
    assert simple_text == 'I eat pizzä'
309
310
311
@pytest.fixture
312
def undefined_context():
313
    """Fixture. Populate context variable for future tests."""
314
    return {
315
        'cookiecutter': {'project_slug': 'testproject', 'github_username': 'hackebrot'}
316
    }
317
318
319
def test_raise_undefined_variable_file_name(output_dir, undefined_context):
320
    """Verify correct error raised when file name cannot be rendered."""
321
    with pytest.raises(exceptions.UndefinedVariableInTemplate) as err:
322
        generate.generate_files(
323
            repo_dir='tests/undefined-variable/file-name/',
324
            output_dir=output_dir,
325
            context=undefined_context,
326
        )
327
    error = err.value
328
    assert "Unable to create file '{{cookiecutter.foobar}}'" == error.message
329
    assert error.context == undefined_context
330
331
    assert not Path(output_dir).joinpath('testproject').exists()
332
333
334 View Code Duplication
def test_raise_undefined_variable_file_name_existing_project(
335
    output_dir, undefined_context
336
):
337
    """Verify correct error raised when file name cannot be rendered."""
338
    testproj_path = Path(output_dir, 'testproject')
339
    testproj_path.mkdir()
340
341
    with pytest.raises(exceptions.UndefinedVariableInTemplate) as err:
342
        generate.generate_files(
343
            repo_dir='tests/undefined-variable/file-name/',
344
            output_dir=output_dir,
345
            context=undefined_context,
346
            overwrite_if_exists=True,
347
        )
348
    error = err.value
349
    assert "Unable to create file '{{cookiecutter.foobar}}'" == error.message
350
    assert error.context == undefined_context
351
352
    assert testproj_path.exists()
353
354
355
def test_raise_undefined_variable_file_content(output_dir, undefined_context):
356
    """Verify correct error raised when file content cannot be rendered."""
357
    with pytest.raises(exceptions.UndefinedVariableInTemplate) as err:
358
        generate.generate_files(
359
            repo_dir='tests/undefined-variable/file-content/',
360
            output_dir=output_dir,
361
            context=undefined_context,
362
        )
363
    error = err.value
364
    assert "Unable to create file 'README.rst'" == error.message
365
    assert error.context == undefined_context
366
367
    assert not Path(output_dir).joinpath('testproject').exists()
368
369
370
def test_raise_undefined_variable_dir_name(output_dir, undefined_context):
371
    """Verify correct error raised when directory name cannot be rendered."""
372
    with pytest.raises(exceptions.UndefinedVariableInTemplate) as err:
373
        generate.generate_files(
374
            repo_dir='tests/undefined-variable/dir-name/',
375
            output_dir=output_dir,
376
            context=undefined_context,
377
        )
378
    error = err.value
379
380
    directory = Path('testproject', '{{cookiecutter.foobar}}')
381
    msg = f"Unable to create directory '{directory}'"
382
    assert msg == error.message
383
384
    assert error.context == undefined_context
385
386
    assert not Path(output_dir).joinpath('testproject').exists()
387
388
389
def test_keep_project_dir_on_failure(output_dir, undefined_context):
390
    """Verify correct error raised when directory name cannot be rendered."""
391
    with pytest.raises(exceptions.UndefinedVariableInTemplate):
392
        generate.generate_files(
393
            repo_dir='tests/undefined-variable/dir-name/',
394
            output_dir=output_dir,
395
            context=undefined_context,
396
            keep_project_on_failure=True,
397
        )
398
    assert Path(output_dir).joinpath('testproject').exists()
399
400
401 View Code Duplication
def test_raise_undefined_variable_dir_name_existing_project(
402
    output_dir, undefined_context
403
):
404
    """Verify correct error raised when directory name cannot be rendered."""
405
    testproj_path = Path(output_dir, 'testproject')
406
    testproj_path.mkdir()
407
408
    with pytest.raises(exceptions.UndefinedVariableInTemplate) as err:
409
        generate.generate_files(
410
            repo_dir='tests/undefined-variable/dir-name/',
411
            output_dir=output_dir,
412
            context=undefined_context,
413
            overwrite_if_exists=True,
414
        )
415
    error = err.value
416
417
    directory = Path('testproject', '{{cookiecutter.foobar}}')
418
    msg = f"Unable to create directory '{directory}'"
419
    assert msg == error.message
420
421
    assert error.context == undefined_context
422
423
    assert testproj_path.exists()
424
425
426
def test_raise_undefined_variable_project_dir(tmp_path):
427
    """Verify correct error raised when directory name cannot be rendered."""
428
    with pytest.raises(exceptions.UndefinedVariableInTemplate) as err:
429
        generate.generate_files(
430
            repo_dir='tests/undefined-variable/dir-name/',
431
            output_dir=tmp_path,
432
            context={},
433
        )
434
    error = err.value
435
    msg = "Unable to create project directory '{{cookiecutter.project_slug}}'"
436
    assert msg == error.message
437
    assert error.context == {}
438
439
    assert not Path(tmp_path, 'testproject').exists()
440