1#!/usr/bin/env python
2"""Test the cmds module"""
3from __future__ import absolute_import, division, unicode_literals
4
5try:
6    from unittest.mock import Mock, patch
7except ImportError:
8    from mock import Mock, patch
9
10import pytest
11
12from cola import cmds
13from cola.compat import uchr
14
15
16def test_Commit_strip_comments():
17    """Ensure that commit messages are stripped of comments"""
18
19    msg = 'subject\n\n#comment\nbody'
20    expect = 'subject\n\nbody\n'
21    actual = cmds.Commit.strip_comments(msg)
22    assert expect == actual
23
24
25def test_commit_strip_comments_unicode():
26    """Ensure that unicode is preserved in stripped commit messages"""
27
28    msg = uchr(0x1234) + '\n\n#comment\nbody'
29    expect = uchr(0x1234) + '\n\nbody\n'
30    actual = cmds.Commit.strip_comments(msg)
31    assert expect == actual
32
33
34def test_unix_path_win32():
35    path = r'Z:\Program Files\git-cola\bin\git-dag'
36    expect = '/Z/Program Files/git-cola/bin/git-dag'
37    actual = cmds.unix_path(path, is_win32=lambda: True)
38    assert expect == actual
39
40
41def test_unix_path_network_win32():
42    path = r'\\Z\Program Files\git-cola\bin\git-dag'
43    expect = '//Z/Program Files/git-cola/bin/git-dag'
44    actual = cmds.unix_path(path, is_win32=lambda: True)
45    assert expect == actual
46
47
48def test_unix_path_is_a_noop_on_sane_platforms():
49    path = r'/:we/don\t/need/no/stinking/badgers!'
50    expect = path
51    actual = cmds.unix_path(path, is_win32=lambda: False)
52    assert expect == actual
53
54
55def test_context_edit_command():
56    context = Mock()
57    model = context.model
58
59    cmd = cmds.EditModel(context)
60    cmd.new_diff_text = 'test_diff_text'
61    cmd.new_diff_type = 'test_diff_type'
62    cmd.new_mode = 'test_mode'
63    cmd.new_filename = 'test_filename'
64    cmd.do()
65
66    model.set_diff_text.assert_called_once_with('test_diff_text')
67    model.set_diff_type.assert_called_once_with('test_diff_type')
68    model.set_mode.assert_called_once_with('test_mode')
69    model.set_filename.assert_called_once_with('test_filename')
70    assert model.set_filename.call_count == 1
71
72
73@patch('cola.interaction.Interaction.confirm')
74def test_submodule_add(confirm):
75    # "git submodule" should not be called if the answer is "no"
76    context = Mock()
77    url = 'url'
78    path = ''
79    reference = ''
80    branch = ''
81    depth = 0
82    cmd = cmds.SubmoduleAdd(context, url, path, branch, depth, reference)
83
84    confirm.return_value = False
85    cmd.do()
86    assert not context.git.submodule.called
87
88    expect = ['--', 'url']
89    actual = cmd.get_args()
90    assert expect == actual
91
92    cmd.path = 'path'
93    expect = ['--', 'url', 'path']
94    actual = cmd.get_args()
95    assert expect == actual
96
97    cmd.reference = 'ref'
98    expect = ['--reference', 'ref', '--', 'url', 'path']
99    actual = cmd.get_args()
100    assert expect == actual
101
102    cmd.branch = 'branch'
103    expect = ['--branch', 'branch', '--reference', 'ref', '--', 'url', 'path']
104    actual = cmd.get_args()
105    assert expect == actual
106
107    cmd.reference = ''
108    cmd.branch = ''
109    cmd.depth = 1
110    expect = ['--depth', '1', '--', 'url', 'path']
111    actual = cmd.get_args()
112    assert expect == actual
113
114    # Run the command and assert that "git submodule" was called.
115    confirm.return_value = True
116    context.git.submodule.return_value = (0, '', '')
117    cmd.do()
118    context.git.submodule.assert_called_once_with('add', *expect)
119    assert context.model.update_file_status.called
120    assert context.model.update_submodules_list.called
121
122
123@patch('cola.version.check_git')
124@patch('cola.interaction.Interaction.confirm')
125def test_submodule_update(confirm, check_git):
126    context = Mock()
127    path = 'sub/path'
128    update_path_cmd = cmds.SubmoduleUpdate(context, path)
129    update_all_cmd = cmds.SubmodulesUpdate(context)
130
131    # Nothing is called when confirm() returns False.
132    confirm.return_value = False
133
134    update_path_cmd.do()
135    assert not context.git.submodule.called
136
137    update_all_cmd.do()
138    assert not context.git.submodule.called
139
140    # Confirm command execution.
141    confirm.return_value = True
142
143    # Test the old command-line arguments first
144    check_git.return_value = False
145
146    expect = ['update', '--', 'sub/path']
147    actual = update_path_cmd.get_args()
148    assert expect == actual
149
150    context.model.update_file_status = Mock()
151    context.git.submodule = Mock(return_value=(0, '', ''))
152    update_path_cmd.do()
153    context.git.submodule.assert_called_once_with(*expect)
154    assert context.model.update_file_status.called
155
156    expect = ['update']
157    actual = update_all_cmd.get_args()
158    assert expect == actual
159
160    context.model.update_file_status = Mock()
161    context.git.submodule = Mock(return_value=(0, '', ''))
162    update_all_cmd.do()
163    context.git.submodule.assert_called_once_with(*expect)
164    assert context.model.update_file_status.called
165
166    # Test the new command-line arguments (git v1.6.5+)
167    check_git.return_value = True
168
169    expect = ['update', '--recursive', '--', 'sub/path']
170    actual = update_path_cmd.get_args()
171    assert expect == actual
172
173    context.model.update_file_status = Mock()
174    context.git.submodule = Mock(return_value=(0, '', ''))
175    update_path_cmd.do()
176    context.git.submodule.assert_called_once_with(*expect)
177    assert context.model.update_file_status.called
178
179    expect = ['update', '--recursive']
180    actual = update_all_cmd.get_args()
181    assert expect == actual
182
183    context.model.update_file_status = Mock()
184    context.git.submodule = Mock(return_value=(0, '', ''))
185    update_all_cmd.do()
186    context.git.submodule.assert_called_once_with(*expect)
187    assert context.model.update_file_status.called
188
189
190@patch('cola.cmds.Interaction')
191@patch('cola.cmds.prefs')
192def test_undo_last_commit_confirms_action(prefs, interaction):
193    """Test the behavior around confirmation of UndoLastCommit actions"""
194    context = Mock()
195    context.model = Mock()
196    # First, test what happens when the commit is published and we say "yes".
197    prefs.check_published_commits = Mock(return_value=True)
198    context.model.is_commit_published = Mock(return_value=True)
199    interaction.confirm = Mock(return_value=True)
200
201    cmd = cmds.UndoLastCommit(context)
202    assert cmd.confirm()
203    context.model.is_commit_published.assert_called_once()
204    interaction.confirm.assert_called_once()
205
206    # Now, test what happens when we say "no".
207    interaction.confirm = Mock(return_value=False)
208    assert not cmd.confirm()
209    interaction.confirm.assert_called_once()
210
211    # Now check what happens when the commit is published but our preferences
212    # say to not check for published commits.
213    prefs.check_published_commits = Mock(return_value=False)
214    context.model.is_commit_published = Mock(return_value=True)
215    interaction.confirm = Mock(return_value=True)
216
217    assert cmd.confirm()
218    context.model.is_commit_published.assert_not_called()
219    interaction.confirm.assert_called_once()
220
221    # Lastly, check what when the commit is not published and we do check
222    # for published commits.
223    prefs.check_published_commits = Mock(return_value=True)
224    context.model.is_commit_published = Mock(return_value=False)
225    interaction.confirm = Mock(return_value=True)
226
227    assert cmd.confirm()
228    context.model.is_commit_published.assert_called_once()
229    interaction.confirm.assert_called_once()
230
231
232if __name__ == '__main__':
233    pytest.main([__file__])
234