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
17 from errbot
.backends
.test
import testbot
# pylint: disable=unused-import
19 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, 'WEBHOOK_URL': 'https://webhood.errbot.com:3142/margebot'}")
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}}")
41 def mock_get(self
, key
):
43 monkeypatch
.setattr(errbot
.storage
.StoreMixin
, '__getitem__', mock_get
, raising
=False)
47 monkeypatch
.setattr(errbot
.storage
.StoreMixin
, 'keys', mock_keys
, raising
=False)
52 def margebot_no_reviews(self
, margebot
, monkeypatch
):
56 def margebot_one_review(self
, margebot
, monkeypatch
):
58 def mock_get(self
, key
):
59 return {(1001, 2001, 'room1,room2'): True} # [(project, iid, notify_rooms)]
61 monkeypatch
.setattr(errbot
.storage
.StoreMixin
, '__getitem__', mock_get
, raising
=False)
65 def one_wip_review(self
, margebot_one_review
, monkeypatch
):
67 def mock_getmergerequest(self
, project
, iid
):
68 return {'author': {'id': 2001},
69 'created_at': 'Oct 29, 2017 2:37am',
70 'merge_status': 'can_be_merged',
73 'web_url': 'http://gitlab.example.com/sample/mr/2001',
74 'work_in_progress': True}
75 monkeypatch
.setattr(gitlab
.Gitlab
, 'getmergerequest', mock_getmergerequest
)
76 return margebot_one_review
79 def one_waiting_review(self
, margebot_one_review
, monkeypatch
):
81 def mock_getmergerequest(self
, project
, iid
):
82 return {'author': {'id': 2001},
83 'created_at': 'Oct 29, 2017 2:37am',
84 'merge_status': 'can_be_merged',
87 'web_url': 'http://gitlab.example.com/sample/mr/2001',
88 'work_in_progress': False}
89 monkeypatch
.setattr(gitlab
.Gitlab
, 'getmergerequest', mock_getmergerequest
)
90 return margebot_one_review
93 def one_conflicted_review(self
, margebot_one_review
, monkeypatch
):
95 def mock_getmergerequest(self
, project
, iid
):
96 return {'author': {'id': 2001},
97 'created_at': 'Oct 29, 2017 2:37am',
98 'merge_status': 'merge_conflicts',
101 'web_url': 'http://gitlab.example.com/sample/mr/2001',
102 'work_in_progress': False}
103 monkeypatch
.setattr(gitlab
.Gitlab
, 'getmergerequest', mock_getmergerequest
)
104 return margebot_one_review
107 def one_mergable_review(self
, margebot_one_review
, monkeypatch
):
109 def mock_getmergerequest(self
, project
, iid
):
110 return {'author': {'id': 2001},
111 'created_at': 'Oct 29, 2017 2:37am',
112 'merge_status': 'can_be_merged',
115 'web_url': 'http://gitlab.example.com/sample/mr/2001',
116 'work_in_progress': False}
117 monkeypatch
.setattr(gitlab
.Gitlab
, 'getmergerequest', mock_getmergerequest
)
118 return margebot_one_review
121 def gitlab(self
, monkeypatch
):
123 def mock_getuser(self
, user
):
124 if user
== '(missing)':
127 return {'username': user
+ ' username'}
128 monkeypatch
.setattr(gitlab
.Gitlab
, 'getuser', mock_getuser
)
130 def mock_getusers(self
, search
=None):
133 if val
== "(missing)":
136 return [{'user': val
, 'id': 3001}]
138 return [{'user': 'user1', 'id': 3001}, {'user': 'user2', 'id': 3002}]
139 monkeypatch
.setattr(gitlab
.Gitlab
, 'getusers', mock_getusers
)
141 # Waiting on Gitlab 8.9 or greater
142 # def mock_getapprovals(id):
144 # monkeypatch.setattr(gitlab.Gitlab, 'getapprovals', mock_getapprovals)
149 def gitlab_no_reviews(self
, gitlab
, monkeypatch
):
150 def mock_getmergerequest(self
, project
, iid
):
152 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
)
168 # ============================================================================
170 @pytest.mark
.parametrize("rdelta,expected", [
171 (relativedelta(days
=1), "1 day ago"),
172 (relativedelta(days
=2), "2 days ago"),
173 (relativedelta(days
=1, hours
=1), "1 day, 1 hour ago"),
174 (relativedelta(days
=2, hours
=2), "2 days, 2 hours ago"),
175 (relativedelta(hours
=2), "2 hours ago"),
176 (relativedelta(days
=1, minutes
=23), "1 day, 23 minutes ago"),
177 (relativedelta(minutes
=2), "2 minutes ago"),
178 (relativedelta(minutes
=1), "1 minute ago"),
179 (relativedelta(minutes
=0), "now"), ])
180 def test_deltastr(self
, rdelta
, expected
):
182 tdelta
= (now
+ rdelta
) - now
183 assert deltastr(tdelta
) == expected
185 def test_help(self
, margebot
):
186 margebot
.push_message('!help')
187 help_message
= margebot
.pop_message()
188 assert "Marge" in help_message
189 assert '!reviews' in help_message
190 assert '!hello' in help_message
191 assert '!xyzzy' in help_message
193 def test_hello(self
, margebot
):
194 margebot
.push_message('!hello')
195 assert 'Hi there' in margebot
.pop_message()
197 # def test_xyzzy(self, margebot):
198 # margebot.push_message('!xyzzy')
199 # assert 'All open MRs have been merged into master' in margebot.pop_message()
201 # assert 'just kidding' in margebot.pop_message()
203 def test_webstatus(self
, margebot
):
204 margebot
.push_message('!webstatus')
205 assert 'margebot/<rooms>' in margebot
.pop_message()
207 def test_gitlab_hook(self
, margebot
, gitlab
):
208 request
= json
.dumps({'object_kind': 'merge_request',
209 'object_attributes': {
211 'work_in_progress': '',
213 'author_id': 'author_id',
214 'target_project_id': 'project_id',
219 margebot
.push_message("!webhook test /margebot/room1,room2 " + request
)
220 assert 'Hi there ! author_id username has opened a new MR: \"title\"\nurl/merge_requests/iid' in margebot
.pop_message()
221 margebot
.push_message('!reviews')
222 assert 'Hi there ! author_id username has opened a new MR: \"title\"\nurl/merge_requests/iid' in margebot
.pop_message()
224 def test_gitlab_hook_wip(self
, margebot
, gitlab
):
225 request
= json
.dumps({'object_kind': 'merge_request',
226 'object_attributes': {
228 'work_in_progress': 'true',
230 'author_id': 'author_id',
231 'target_project_id': 'project_id',
236 margebot
.push_message("!webhook test /margebot/room1,room2 " + request
)
237 assert 'Hi there ! author_id username has opened a new WIP MR: \"title\"\nurl/merge_requests/iid' in margebot
.pop_message()
238 margebot
.push_message('!reviews')
239 assert 'Hi there ! author_id username has opened a new WIP MR: \"title\"\nurl/merge_requests/iid' in margebot
.pop_message()
241 def test_gitlab_hook_unexpected_user(self
, margebot
, gitlab
):
242 request
= json
.dumps({'object_kind': 'merge_request',
243 'object_attributes': {
245 'work_in_progress': '',
247 'author_id': '(missing)',
248 'target_project_id': 'project_id',
254 margebot
.push_message("!webhook test /margebot/room1,room2 " + request
)
255 assert 'Hi there ! (missing) has opened a new MR: \"title\"\nurl/merge_requests/iid' in margebot
.pop_message()
256 margebot
.push_message('!reviews')
257 assert 'Hi there ! (missing) has opened a new MR: \"title\"\nurl/merge_requests/iid' in margebot
.pop_message()
259 def test_gitlab_hook_unexpected_object_kind(self
, margebot
, gitlab
, caplog
):
260 request
= json
.dumps({'object_kind': 'not_merge_request',
261 'object_attributes': {
263 'work_in_progress': '',
265 'author_id': 'author_id',
266 'target_project_id': 'project_id',
272 margebot
.push_message("!webhook test /margebot/room1,room2 " + request
)
273 margebot
.pop_message()
274 margebot
.push_message('!reviews')
275 assert 'Hi gbin: I found no open MRs for you.' in margebot
.pop_message()
276 assert 'unexpecting object_kind: not_merge_request' in caplog
.text
# Has to be at end of method
278 def test_nothing_to_review(self
, margebot
, gitlab_no_reviews
):
279 margebot
.push_message('!reviews')
280 assert 'Hi gbin: I found no open MRs for you.' in margebot
.pop_message()
282 def test_get_one_open_mr(self
, margebot_one_review
, gitlab_one_review
):
283 margebot_one_review
.push_message('!reviews')
284 output
= margebot_one_review
.pop_message()
285 assert 'These MRs need some attention' in output
286 assert 'http://gitlab.example.com/sample/mr/2001' in output
287 assert 'No upvotes, please review.' in output
289 def test_get_one_wip_mr(self
, one_wip_review
, gitlab
):
290 one_wip_review
.push_message('!reviews')
291 output
= one_wip_review
.pop_message()
292 assert 'These MRs need some attention' in output
293 assert 'http://gitlab.example.com/sample/mr/2001' in output
294 assert 'No upvotes, please review but still WIP.' in output
296 def test_get_one_waiting_mr(self
, margebot
, one_waiting_review
, gitlab
):
297 one_waiting_review
.push_message('!reviews')
298 output
= margebot
.pop_message()
299 assert 'These MRs need some attention' in output
300 assert 'http://gitlab.example.com/sample/mr/2001' in output
301 assert 'Waiting for another upvote.' in output
303 def test_get_one_mergable_mr(self
, margebot
, one_mergable_review
, gitlab
):
304 one_mergable_review
.push_message('!reviews')
305 output
= margebot
.pop_message()
306 assert 'These MRs need some attention' in output
307 assert 'http://gitlab.example.com/sample/mr/2001' in output
308 assert 'Has 2+ upvotes and could be merged in now.' in output
310 def test_get_one_conflicted_mr(self
, margebot
, one_conflicted_review
, gitlab
):
311 one_conflicted_review
.push_message('!reviews')
312 output
= margebot
.pop_message(timeout
=1)
313 assert 'These MRs need some attention' in output
314 assert 'http://gitlab.example.com/sample/mr/2001' in output
315 assert 'Has 2+ upvotes and could be merged in now except there are merge conflicts.' in output
317 def test_crontab_hook(self
, one_waiting_review
, gitlab
, monkeypatch
, mocker
):
318 plugin
= one_waiting_review
._bot
.plugin_manager
.get_plugin_obj_by_name('Marge')
321 return [mocker
.MagicMock(node
='room1'), mocker
.MagicMock(node
='room2')]
322 monkeypatch
.setattr(plugin
, 'rooms', mock_rooms
)
324 plugin
.crontab_hook("unused")
325 output
= one_waiting_review
.pop_message()
326 assert 'These MRs need some attention' in output
327 assert 'http://gitlab.example.com/sample/mr/2001 (opened' in output