Passed
Push — master ( d9bd72...0347a6 )
by
unknown
01:07
created

test_make_sure_path_exists_correctly_handle_os_error()   A

Complexity

Conditions 1

Size

Total Lines 14
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 6
dl 0
loc 14
rs 10
c 0
b 0
f 0
cc 1
nop 1
1
# -*- coding: utf-8 -*-
2
3
"""Tests for `cookiecutter.utils` module."""
4
import stat
5
import sys
6
from pathlib import Path
7
8
import pytest
9
10
from cookiecutter import utils
11
12
13
def make_readonly(path):
14
    """Change the access permissions to readonly for a given file."""
15
    mode = Path.stat(path).st_mode
16
    Path.chmod(path, mode & ~stat.S_IWRITE)
17
18
19
@pytest.mark.skipif(
20
    sys.version_info[0] == 3 and sys.version_info[1] == 6 and sys.version_info[2] == 1,
21
    reason="Outdated pypy3 version on Travis CI/CD",
22
)
23
def test_rmtree(tmp_path):
24
    """Verify `utils.rmtree` remove files marked as read-only."""
25
    with open(Path(tmp_path, 'bar'), "w") as f:
26
        f.write("Test data")
27
    make_readonly(Path(tmp_path, 'bar'))
28
29
    utils.rmtree(tmp_path)
30
31
    assert not Path(tmp_path).exists()
32
33
34
@pytest.mark.skipif(
35
    sys.version_info[0] == 3 and sys.version_info[1] == 6 and sys.version_info[2] == 1,
36
    reason="Outdated pypy3 version on Travis CI/CD",
37
)
38
def test_make_sure_path_exists(tmp_path):
39
    """Verify correct True/False response from `utils.make_sure_path_exists`.
40
41
    Should return True if directory exist or created.
42
    Should return False if impossible to create directory (for example protected)
43
    """
44
    existing_directory = tmp_path
45
    directory_to_create = Path(tmp_path, "not_yet_created")
46
47
    assert utils.make_sure_path_exists(existing_directory)
48
    assert utils.make_sure_path_exists(directory_to_create)
49
50
    # Ensure by base system methods.
51
    assert existing_directory.is_dir()
52
    assert existing_directory.exists()
53
    assert directory_to_create.is_dir()
54
    assert directory_to_create.exists()
55
56
57
def test_make_sure_path_exists_correctly_handle_os_error(mocker):
58
    """Verify correct True/False response from `utils.make_sure_path_exists`.
59
60
    Should return True if directory exist or created.
61
    Should return False if impossible to create directory (for example protected)
62
    """
63
64
    def raiser(*args, **kwargs):
65
        raise OSError()
66
67
    mocker.patch("os.makedirs", raiser)
68
    uncreatable_directory = Path('protected_path')
69
70
    assert not utils.make_sure_path_exists(uncreatable_directory)
71
72
73
@pytest.mark.skipif(
74
    sys.version_info[0] == 3 and sys.version_info[1] == 6 and sys.version_info[2] == 1,
75
    reason="Outdated pypy3 version on Travis CI/CD",
76
)
77
def test_work_in(tmp_path):
78
    """Verify returning to original folder after `utils.work_in` use."""
79
    cwd = Path.cwd()
80
    ch_to = tmp_path
81
82
    assert ch_to != Path.cwd()
83
84
    # Under context manager we should work in tmp_path.
85
    with utils.work_in(ch_to):
86
        assert ch_to == Path.cwd()
87
88
    # Make sure we return to the correct folder
89
    assert cwd == Path.cwd()
90
91
92
def test_prompt_should_ask_and_rm_repo_dir(mocker, tmp_path):
93
    """In `prompt_and_delete()`, if the user agrees to delete/reclone the \
94
    repo, the repo should be deleted."""
95
    mock_read_user = mocker.patch(
96
        'cookiecutter.utils.read_user_yes_no', return_value=True
97
    )
98
    repo_dir = Path(tmp_path, 'repo')
99
    repo_dir.mkdir()
100
101
    deleted = utils.prompt_and_delete(str(repo_dir))
102
103
    assert mock_read_user.called
104
    assert not repo_dir.exists()
105
    assert deleted
106
107
108
def test_prompt_should_ask_and_exit_on_user_no_answer(mocker, tmp_path):
109
    """In `prompt_and_delete()`, if the user decline to delete/reclone the \
110
    repo, cookiecutter should exit."""
111
    mock_read_user = mocker.patch(
112
        'cookiecutter.utils.read_user_yes_no', return_value=False,
113
    )
114
    mock_sys_exit = mocker.patch('sys.exit', return_value=True)
115
    repo_dir = Path(tmp_path, 'repo')
116
    repo_dir.mkdir()
117
118
    deleted = utils.prompt_and_delete(str(repo_dir))
119
120
    assert mock_read_user.called
121
    assert repo_dir.exists()
122
    assert not deleted
123
    assert mock_sys_exit.called
124
125
126
def test_prompt_should_ask_and_rm_repo_file(mocker, tmp_path):
127
    """In `prompt_and_delete()`, if the user agrees to delete/reclone a \
128
    repo file, the repo should be deleted."""
129
    mock_read_user = mocker.patch(
130
        'cookiecutter.utils.read_user_yes_no', return_value=True, autospec=True
131
    )
132
133
    repo_file = tmp_path.joinpath('repo.zip')
134
    repo_file.write_text('this is zipfile content')
135
136
    deleted = utils.prompt_and_delete(str(repo_file))
137
138
    assert mock_read_user.called
139
    assert not repo_file.exists()
140
    assert deleted
141
142
143
def test_prompt_should_ask_and_keep_repo_on_no_reuse(mocker, tmp_path):
144
    """In `prompt_and_delete()`, if the user wants to keep their old \
145
    cloned template repo, it should not be deleted."""
146
    mock_read_user = mocker.patch(
147
        'cookiecutter.utils.read_user_yes_no', return_value=False, autospec=True
148
    )
149
    repo_dir = Path(tmp_path, 'repo')
150
    repo_dir.mkdir()
151
152
    with pytest.raises(SystemExit):
153
        utils.prompt_and_delete(str(repo_dir))
154
155
    assert mock_read_user.called
156
    assert repo_dir.exists()
157
158
159
def test_prompt_should_ask_and_keep_repo_on_reuse(mocker, tmp_path):
160
    """In `prompt_and_delete()`, if the user wants to keep their old \
161
    cloned template repo, it should not be deleted."""
162
163
    def answer(question, default):
164
        if 'okay to delete' in question:
165
            return False
166
        else:
167
            return True
168
169
    mock_read_user = mocker.patch(
170
        'cookiecutter.utils.read_user_yes_no', side_effect=answer, autospec=True
171
    )
172
    repo_dir = Path(tmp_path, 'repo')
173
    repo_dir.mkdir()
174
175
    deleted = utils.prompt_and_delete(str(repo_dir))
176
177
    assert mock_read_user.called
178
    assert repo_dir.exists()
179
    assert not deleted
180
181
182
def test_prompt_should_not_ask_if_no_input_and_rm_repo_dir(mocker, tmp_path):
183
    """Prompt should not ask if no input and rm dir.
184
185
    In `prompt_and_delete()`, if `no_input` is True, the call to
186
    `prompt.read_user_yes_no()` should be suppressed.
187
    """
188
    mock_read_user = mocker.patch(
189
        'cookiecutter.prompt.read_user_yes_no', return_value=True, autospec=True
190
    )
191
    repo_dir = Path(tmp_path, 'repo')
192
    repo_dir.mkdir()
193
194
    deleted = utils.prompt_and_delete(str(repo_dir), no_input=True)
195
196
    assert not mock_read_user.called
197
    assert not repo_dir.exists()
198
    assert deleted
199
200
201
def test_prompt_should_not_ask_if_no_input_and_rm_repo_file(mocker, tmp_path):
202
    """Prompt should not ask if no input and rm file.
203
204
    In `prompt_and_delete()`, if `no_input` is True, the call to
205
    `prompt.read_user_yes_no()` should be suppressed.
206
    """
207
    mock_read_user = mocker.patch(
208
        'cookiecutter.prompt.read_user_yes_no', return_value=True, autospec=True
209
    )
210
211
    repo_file = tmp_path.joinpath('repo.zip')
212
    repo_file.write_text('this is zipfile content')
213
214
    deleted = utils.prompt_and_delete(str(repo_file), no_input=True)
215
216
    assert not mock_read_user.called
217
    assert not repo_file.exists()
218
    assert deleted
219