Passed
Push — master ( c15633...7f6804 )
by Andrey
01:00
created

tests/test_generate_files.py (9 issues)

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