4 # pragma pylint: disable=invalid-name
5 # pragma pylint: disable=missing-docstring
6 # pragma pylint: disable=no-else-return
7 # pragma pylint: disable=protected-access
8 # pragma pylint: disable=redefined-outer-name
9 # pragma pylint: disable=too-many-public-methods
10 # pragma pylint: disable=unused-argument
12 from datetime
import datetime
18 from errbot
.backends
.test
import testbot
# pylint: disable=unused-import
20 from dateutil
.relativedelta
import relativedelta
21 from plugins
.marge
import deltastr
24 class TestMarge(object):
28 Run 'py.test' from the margebot root directory
31 extra_plugin_dir
= "./plugins/"
32 loglevel
= logging
.INFO
35 def margebot(self
, testbot
, monkeypatch
, mocker
):
36 testbot
.push_message("!plugin config Marge {'CHATROOM_HOST': 'conference.test.com', 'GITLAB_HOST': 'gitlab.test.com', 'GITLAB_ADMIN_TOKEN': 'fake-token', 'CRONTAB': '0 * * * *', 'VERIFY_SSL': True, 'CRONTAB_SOAK_HOURS': 1}")
38 testbot
.push_message("!plugin config Webserver {'HOST': '0.0.0.0', 'PORT':3141, 'SSL': {'certificate': '', 'enabled': False, 'host': '0.0.0.0', 'key': '', 'port': 3142}}")
43 monkeypatch
.setattr(errbot
.storage
.StoreMixin
, 'keys', mock_keys
, raising
=False)
48 def margebot_no_reviews(self
, margebot
, monkeypatch
):
50 def mock_get(self
, key
):
53 monkeypatch
.setattr(errbot
.storage
.StoreMixin
, '__getitem__', mock_get
, raising
=False)
57 def margebot_one_review(self
, margebot
, monkeypatch
):
59 def mock_get(self
, key
):
60 return {(1001, 2001, 'room1,room2'): True} # [(project, iid, notify_rooms)]
62 monkeypatch
.setattr(errbot
.storage
.StoreMixin
, '__getitem__', mock_get
, raising
=False)
66 def one_wip_review(self
, margebot_one_review
, monkeypatch
):
68 def mock_getmergerequest(self
, project
, iid
):
69 return {'author': {'id': 2001},
70 'created_at': 'Oct 29, 2017 2:37am',
71 'merge_status': 'can_be_merged',
74 'web_url': 'http://gitlab.example.com/sample/mr/2001',
75 'work_in_progress': True}
76 monkeypatch
.setattr(gitlab
.Gitlab
, 'getmergerequest', mock_getmergerequest
)
77 return margebot_one_review
80 def one_waiting_review(self
, margebot_one_review
, monkeypatch
):
82 def mock_getmergerequest(self
, project
, iid
):
83 return {'author': {'id': 2001},
84 'created_at': 'Oct 29, 2017 2:37am',
85 'merge_status': 'can_be_merged',
88 'web_url': 'http://gitlab.example.com/sample/mr/2001',
89 'work_in_progress': False}
90 monkeypatch
.setattr(gitlab
.Gitlab
, 'getmergerequest', mock_getmergerequest
)
91 return margebot_one_review
94 def one_conflicted_review(self
, margebot_one_review
, monkeypatch
):
96 def mock_getmergerequest(self
, project
, iid
):
97 return {'author': {'id': 2001},
98 'created_at': 'Oct 29, 2017 2:37am',
99 'merge_status': 'merge_conflicts',
102 'web_url': 'http://gitlab.example.com/sample/mr/2001',
103 'work_in_progress': False}
104 monkeypatch
.setattr(gitlab
.Gitlab
, 'getmergerequest', mock_getmergerequest
)
105 return margebot_one_review
108 def one_mergable_review(self
, margebot_one_review
, monkeypatch
):
110 def mock_getmergerequest(self
, project
, iid
):
111 return {'author': {'id': 2001},
112 'created_at': 'Oct 29, 2017 2:37am',
113 'merge_status': 'can_be_merged',
116 'web_url': 'http://gitlab.example.com/sample/mr/2001',
117 'work_in_progress': False}
118 monkeypatch
.setattr(gitlab
.Gitlab
, 'getmergerequest', mock_getmergerequest
)
119 return margebot_one_review
122 def gitlab(self
, monkeypatch
):
124 def mock_getuser(self
, user
):
125 if user
== '(missing)':
128 return {'username': user
+ ' username'}
129 monkeypatch
.setattr(gitlab
.Gitlab
, 'getuser', mock_getuser
)
131 def mock_getusers(self
, search
=None):
134 if val
== "(missing)":
137 return [{'user': val
, 'id': 3001}]
139 return [{'user': 'user1', 'id': 3001}, {'user': 'user2', 'id': 3002}]
140 monkeypatch
.setattr(gitlab
.Gitlab
, 'getusers', mock_getusers
)
142 # Waiting on Gitlab 8.9 or greater
143 # def mock_getapprovals(id):
145 # monkeypatch.setattr(gitlab.Gitlab, 'getapprovals', mock_getapprovals)
150 def gitlab_no_reviews(self
, gitlab
, monkeypatch
):
151 def mock_getmergerequest(self
, project
, iid
):
153 monkeypatch
.setattr(gitlab
, 'getuser', mock_getmergerequest
)
156 def gitlab_one_review(self
, gitlab
, monkeypatch
):
157 def mock_getmergerequest(self
, project
, iid
):
158 return {'author': {'id': 2001},
159 'created_at': 'Oct 29, 2017 2:37am',
160 'merge_status': 'can_be_merged',
163 'web_url': 'http://gitlab.example.com/sample/mr/2001',
164 'work_in_progress': False}
165 monkeypatch
.setattr(gitlab
, 'getmergerequest', mock_getmergerequest
)
167 # ============================================================================
169 @pytest.mark
.parametrize("rdelta,expected", [
170 (relativedelta(days
=1), "1 day ago"),
171 (relativedelta(days
=2), "2 days ago"),
172 (relativedelta(days
=1, hours
=1), "1 day, 1 hour ago"),
173 (relativedelta(days
=2, hours
=2), "2 days, 2 hours ago"),
174 (relativedelta(hours
=2), "2 hours ago"),
175 (relativedelta(days
=1, minutes
=23), "1 day, 23 minutes ago"),
176 (relativedelta(minutes
=2), "2 minutes ago"),
177 (relativedelta(minutes
=1), "1 minute ago"),
178 (relativedelta(minutes
=0), "now"), ])
179 def test_deltastr(self
, rdelta
, expected
):
181 tdelta
= (now
+ rdelta
) - now
182 assert deltastr(tdelta
) == expected
184 def test_help(self
, margebot
):
185 margebot
.push_message('!help')
186 help_message
= margebot
.pop_message()
187 assert "Marge" in help_message
188 assert '!reviews' in help_message
189 assert '!hello' in help_message
190 assert '!xyzzy' in help_message
192 def test_hello(self
, margebot
):
193 margebot
.push_message('!hello')
194 assert 'Hi there' in margebot
.pop_message()
196 # def test_xyzzy(self, margebot):
197 # margebot.push_message('!xyzzy')
198 # assert 'All open MRs have been merged into master' in margebot.pop_message()
200 # assert 'just kidding' in margebot.pop_message()
202 def test_webstatus(self
, margebot
):
203 margebot
.push_message('!webstatus')
204 assert 'margebot/<rooms>' in margebot
.pop_message()
206 def test_gitlab_hook(self
, margebot
, gitlab
):
207 request
= json
.dumps({'object_kind': 'merge_request',
208 'object_attributes': {
210 'work_in_progress': '',
212 'author_id': 'author_id',
213 'target_project_id': 'project_id',
217 margebot
.push_message("!webhook test /margebot/room1,room2 " + request
)
218 assert 'New Review: author_id username has opened a new MR: \"title\"\nurl/merge_requests/iid' in margebot
.pop_message()
219 margebot
.push_message('!reviews')
220 assert 'New Review: author_id username has opened a new MR: \"title\"\nurl/merge_requests/iid' in margebot
.pop_message()
222 def test_gitlab_hook_wip(self
, margebot
, gitlab
):
223 request
= json
.dumps({'object_kind': 'merge_request',
224 'object_attributes': {
226 'work_in_progress': 'true',
228 'author_id': 'author_id',
229 'target_project_id': 'project_id',
233 margebot
.push_message("!webhook test /margebot/room1,room2 " + request
)
234 assert 'New Review: author_id username has opened a new WIP MR: \"title\"\nurl/merge_requests/iid' in margebot
.pop_message()
235 margebot
.push_message('!reviews')
236 assert 'New Review: author_id username has opened a new WIP MR: \"title\"\nurl/merge_requests/iid' in margebot
.pop_message()
238 def test_gitlab_hook_unexpected_user(self
, margebot
, gitlab
):
239 request
= json
.dumps({'object_kind': 'merge_request',
240 'object_attributes': {
242 'work_in_progress': '',
244 'author_id': '(missing)',
245 'target_project_id': 'project_id',
250 margebot
.push_message("!webhook test /margebot/room1,room2 " + request
)
251 assert 'New Review: (missing) has opened a new MR: \"title\"\nurl/merge_requests/iid' in margebot
.pop_message()
252 margebot
.push_message('!reviews')
253 assert 'New Review: (missing) has opened a new MR: \"title\"\nurl/merge_requests/iid' in margebot
.pop_message()
255 def test_gitlab_hook_unexpected_object_kind(self
, margebot_no_reviews
, gitlab
, caplog
):
256 request
= json
.dumps({'object_kind': 'not_merge_request',
257 'object_attributes': {
259 'work_in_progress': '',
261 'author_id': 'author_id',
262 'target_project_id': 'project_id',
267 margebot_no_reviews
.push_message("!webhook test /margebot/room1,room2 " + request
)
268 margebot_no_reviews
.pop_message()
269 margebot_no_reviews
.push_message('!reviews')
270 assert 'Hi gbin: I found no open MRs for you.' in margebot_no_reviews
.pop_message()
271 assert 'unexpecting object_kind: not_merge_request' in caplog
.text
# Has to be at end of method
273 def test_nothing_to_review(self
, margebot_no_reviews
, gitlab_no_reviews
):
274 margebot_no_reviews
.push_message('!reviews')
275 assert 'Hi gbin: I found no open MRs for you.' in margebot_no_reviews
.pop_message()
277 def test_get_one_open_mr(self
, margebot_one_review
, gitlab_one_review
):
278 margebot_one_review
.push_message('!reviews')
279 output
= margebot_one_review
.pop_message()
280 assert 'These MRs need some attention' in output
281 assert 'http://gitlab.example.com/sample/mr/2001' in output
282 assert 'No upvotes, please review.' in output
284 def test_get_one_wip_mr(self
, one_wip_review
, gitlab
):
285 one_wip_review
.push_message('!reviews')
286 output
= one_wip_review
.pop_message()
287 assert 'These MRs need some attention' in output
288 assert 'http://gitlab.example.com/sample/mr/2001' in output
289 assert 'No upvotes, please review but still WIP.' in output
291 def test_get_one_waiting_mr(self
, margebot
, one_waiting_review
, gitlab
):
292 one_waiting_review
.push_message('!reviews')
293 output
= margebot
.pop_message()
294 assert 'These MRs need some attention' in output
295 assert 'http://gitlab.example.com/sample/mr/2001' in output
296 assert 'Waiting for another upvote.' in output
298 def test_get_one_mergable_mr(self
, margebot
, one_mergable_review
, gitlab
):
299 one_mergable_review
.push_message('!reviews')
300 output
= margebot
.pop_message()
301 assert 'These MRs need some attention' in output
302 assert 'http://gitlab.example.com/sample/mr/2001' in output
303 assert 'Has 2+ upvotes and could be merged in now.' in output
305 def test_get_one_conflicted_mr(self
, margebot
, one_conflicted_review
, gitlab
):
306 one_conflicted_review
.push_message('!reviews')
307 output
= margebot
.pop_message(timeout
=1)
308 assert 'These MRs need some attention' in output
309 assert 'http://gitlab.example.com/sample/mr/2001' in output
310 assert 'Has 2+ upvotes and could be merged in now except there are merge conflicts.' in output
312 def test_crontab_hook(self
, one_waiting_review
, gitlab
, monkeypatch
, mocker
):
313 plugin
= one_waiting_review
._bot
.plugin_manager
.get_plugin_obj_by_name('Marge')
316 return [mocker
.MagicMock(node
='room1'), mocker
.MagicMock(node
='room2')]
317 monkeypatch
.setattr(plugin
, 'rooms', mock_rooms
)
319 plugin
.crontab_hook("unused")
320 output
= one_waiting_review
.pop_message()
321 assert 'These MRs need some attention' in output
322 assert 'http://gitlab.example.com/sample/mr/2001 (opened' in output