Completed
Push — vcs-error-messages ( 931585 )
by Michael
01:18
created

test_clone_handles_misspelt_repo()   A

Complexity

Conditions 2

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
c 1
b 0
f 0
dl 0
loc 16
rs 9.4285
1
# -*- coding: utf-8 -*-
2
import os
3
import subprocess
4
5
import pytest
6
7
from cookiecutter import exceptions, vcs
8
9
10
@pytest.fixture
11
def clone_dir(tmpdir):
12
    """Simulates creation of a directory called `clone_dir` inside of `tmpdir`.
13
    Returns a str to said directory.
14
    """
15
    return str(tmpdir.mkdir('clone_dir'))
16
17
18
def test_clone_should_raise_if_vcs_not_installed(mocker, clone_dir):
19
    """In `clone()`, a `VCSNotInstalled` exception should be raised if no VCS
20
    is installed.
21
    """
22
    mocker.patch(
23
        'cookiecutter.vcs.is_vcs_installed',
24
        autospec=True,
25
        return_value=False
26
    )
27
28
    repo_url = 'https://github.com/pytest-dev/cookiecutter-pytest-plugin.git'
29
30
    with pytest.raises(exceptions.VCSNotInstalled):
31
        vcs.clone(repo_url, clone_to_dir=clone_dir)
32
33
34
@pytest.mark.parametrize('which_return, result', [
35
    ('', False),
36
    (None, False),
37
    (False, False),
38
    ('/usr/local/bin/git', True),
39
])
40
def test_is_vcs_installed(mocker, which_return, result):
41
    mocker.patch(
42
        'cookiecutter.vcs.which',
43
        autospec=True,
44
        return_value=which_return
45
    )
46
    assert vcs.is_vcs_installed('git') == result
47
48
49
@pytest.mark.parametrize('repo_type, repo_url, repo_name', [
50
    ('git', 'https://github.com/hello/world.git', 'world'),
51
    ('hg', 'https://bitbucket.org/foo/bar', 'bar'),
52
])
53
def test_clone_should_invoke_git(
54
        mocker, clone_dir, repo_type, repo_url, repo_name):
55
    """When `clone()` is called with a git/hg repo, the corresponding VCS
56
    command should be run via `subprocess.check_output()`.
57
58
    This should take place:
59
    * In the correct dir
60
    * With the correct args.
61
    """
62
    mocker.patch(
63
        'cookiecutter.vcs.is_vcs_installed',
64
        autospec=True,
65
        return_value=True
66
    )
67
68
    mock_subprocess = mocker.patch(
69
        'cookiecutter.vcs.subprocess.check_output',
70
        autospec=True,
71
    )
72
    expected_repo_dir = os.path.normpath(os.path.join(clone_dir, repo_name))
73
74
    branch = 'foobar'
75
76
    repo_dir = vcs.clone(
77
        repo_url,
78
        checkout=branch,
79
        clone_to_dir=clone_dir,
80
        no_input=True
81
    )
82
83
    assert repo_dir == expected_repo_dir
84
85
    mock_subprocess.assert_any_call(
86
        [repo_type, 'clone', repo_url], cwd=clone_dir
87
    )
88
    mock_subprocess.assert_any_call(
89
        [repo_type, 'checkout', branch], cwd=expected_repo_dir
90
    )
91
92
93
def test_clone_should_abort_if_user_does_not_want_to_reclone(mocker, tmpdir):
94
    """In `clone()`, if user doesn't want to reclone, Cookiecutter should exit
95
    without cloning anything.
96
    """
97
    mocker.patch(
98
        'cookiecutter.vcs.is_vcs_installed',
99
        autospec=True,
100
        return_value=True
101
    )
102
    mocker.patch(
103
        'cookiecutter.vcs.prompt_and_delete_repo',
104
        side_effect=SystemExit,
105
        autospec=True
106
    )
107
    mock_subprocess = mocker.patch(
108
        'cookiecutter.vcs.subprocess.check_output',
109
        autospec=True,
110
    )
111
112
    clone_to_dir = tmpdir.mkdir('clone')
113
114
    # Create repo_dir to trigger prompt_and_delete_repo
115
    clone_to_dir.mkdir('cookiecutter-pytest-plugin')
116
117
    repo_url = 'https://github.com/pytest-dev/cookiecutter-pytest-plugin.git'
118
119
    with pytest.raises(SystemExit):
120
        vcs.clone(repo_url, clone_to_dir=str(clone_to_dir))
121
    assert not mock_subprocess.called
122
123
124
def test_clone_should_rstrip_trailing_slash_in_repo_url(mocker, clone_dir):
125
    """In `clone()`, repo URL's trailing slash should be stripped if one is
126
    present.
127
    """
128
    mocker.patch(
129
        'cookiecutter.vcs.is_vcs_installed',
130
        autospec=True,
131
        return_value=True
132
    )
133
134
    mock_subprocess = mocker.patch(
135
        'cookiecutter.vcs.subprocess.check_output',
136
        autospec=True,
137
    )
138
139
    vcs.clone(
140
        'https://github.com/foo/bar/',
141
        clone_to_dir=clone_dir,
142
        no_input=True
143
    )
144
145
    mock_subprocess.assert_called_once_with(
146
        ['git', 'clone', 'https://github.com/foo/bar'], cwd=clone_dir
147
    )
148
149
150
def test_clone_unknown_subprocess_error(mocker, clone_dir):
151
    mock_subprocess = mocker.patch(
152
        'cookiecutter.vcs.subprocess.check_output',
153
        autospec=True,
154
        side_effect=subprocess.CalledProcessError(
155
            -1,
156
            'cmd',
157
            output='Something went wrong'
158
        )
159
    )
160
161
    with pytest.raises(subprocess.CalledProcessError):
162
        vcs.clone(
163
            'https://github.com/pytest-dev/cookiecutter-pytest-plgin',
164
            clone_to_dir=clone_dir,
165
            no_input=True
166
        )
167
168
def test_clone_handles_misspelt_repo(mocker, clone_dir):
169
    mock_subprocess = mocker.patch(
170
        'cookiecutter.vcs.subprocess.check_output',
171
        autospec=True,
172
        side_effect=subprocess.CalledProcessError(
173
            -1,
174
            'cmd',
175
            output="fatal: repository 'https://github.com/pytest-dev/cookiecutter-pytest-plgin' not found"
176
        )
177
    )
178
179
    with pytest.raises(exceptions.RepositoryCloneFailed):
180
        vcs.clone(
181
            'https://github.com/pytest-dev/cookiecutter-pytest-plgin',
182
            clone_to_dir=clone_dir,
183
            no_input=True
184
        )
185
186
187
def test_clone_handles_branch_typo(mocker, clone_dir):
188
    mock_subprocess = mocker.patch(
189
        'cookiecutter.vcs.subprocess.check_output',
190
        autospec=True,
191
        side_effect=subprocess.CalledProcessError(
192
            -1,
193
            'cmd',
194
            output="error: pathspec 'unknown_branch' did not match any file(s) known to git."
195
        )
196
    )
197
    with pytest.raises(exceptions.RepositoryBranchNotFound):
198
        vcs.clone(
199
            'https://github.com/pytest-dev/cookiecutter-pytest-plugin',
200
            clone_to_dir=clone_dir,
201
            checkout='unknown_branch',
202
            no_input=True
203
        )
204