##// END OF EJS Templates
pull-requests: fixed tests.
ergo -
r1977:cd9c800f default
parent child Browse files
Show More
@@ -1,1112 +1,1110 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20 import mock
21 21 import pytest
22 22
23 23 import rhodecode
24 24 from rhodecode.lib.vcs.backends.base import MergeResponse, MergeFailureReason
25 25 from rhodecode.lib.vcs.nodes import FileNode
26 26 from rhodecode.lib import helpers as h
27 27 from rhodecode.model.changeset_status import ChangesetStatusModel
28 28 from rhodecode.model.db import (
29 29 PullRequest, ChangesetStatus, UserLog, Notification, ChangesetComment)
30 30 from rhodecode.model.meta import Session
31 31 from rhodecode.model.pull_request import PullRequestModel
32 32 from rhodecode.model.user import UserModel
33 33 from rhodecode.tests import (
34 34 assert_session_flash, TEST_USER_ADMIN_LOGIN, TEST_USER_REGULAR_LOGIN)
35 35 from rhodecode.tests.utils import AssertResponse
36 36
37 37
38 38 def route_path(name, params=None, **kwargs):
39 39 import urllib
40 40
41 41 base_url = {
42 42 'repo_changelog': '/{repo_name}/changelog',
43 43 'repo_changelog_file': '/{repo_name}/changelog/{commit_id}/{f_path}',
44 44 'pullrequest_show': '/{repo_name}/pull-request/{pull_request_id}',
45 45 'pullrequest_show_all': '/{repo_name}/pull-request',
46 46 'pullrequest_show_all_data': '/{repo_name}/pull-request-data',
47 47 'pullrequest_repo_refs': '/{repo_name}/pull-request/refs/{target_repo_name:.*?[^/]}',
48 48 'pullrequest_repo_destinations': '/{repo_name}/pull-request/repo-destinations',
49 49 'pullrequest_new': '/{repo_name}/pull-request/new',
50 50 'pullrequest_create': '/{repo_name}/pull-request/create',
51 51 'pullrequest_update': '/{repo_name}/pull-request/{pull_request_id}/update',
52 52 'pullrequest_merge': '/{repo_name}/pull-request/{pull_request_id}/merge',
53 53 'pullrequest_delete': '/{repo_name}/pull-request/{pull_request_id}/delete',
54 54 'pullrequest_comment_create': '/{repo_name}/pull-request/{pull_request_id}/comment',
55 55 'pullrequest_comment_delete': '/{repo_name}/pull-request/{pull_request_id}/comment/{comment_id}/delete',
56 56 }[name].format(**kwargs)
57 57
58 58 if params:
59 59 base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
60 60 return base_url
61 61
62 62
63 63 @pytest.mark.usefixtures('app', 'autologin_user')
64 64 @pytest.mark.backends("git", "hg")
65 65 class TestPullrequestsView(object):
66 66
67 67 def test_index(self, backend):
68 68 self.app.get(route_path(
69 69 'pullrequest_new',
70 70 repo_name=backend.repo_name))
71 71
72 72 def test_option_menu_create_pull_request_exists(self, backend):
73 73 repo_name = backend.repo_name
74 74 response = self.app.get(h.route_path('repo_summary', repo_name=repo_name))
75 75
76 76 create_pr_link = '<a href="%s">Create Pull Request</a>' % route_path(
77 77 'pullrequest_new', repo_name=repo_name)
78 78 response.mustcontain(create_pr_link)
79 79
80 80 def test_create_pr_form_with_raw_commit_id(self, backend):
81 81 repo = backend.repo
82 82
83 83 self.app.get(
84 84 route_path('pullrequest_new',
85 85 repo_name=repo.repo_name,
86 86 commit=repo.get_commit().raw_id),
87 87 status=200)
88 88
89 89 @pytest.mark.parametrize('pr_merge_enabled', [True, False])
90 90 def test_show(self, pr_util, pr_merge_enabled):
91 91 pull_request = pr_util.create_pull_request(
92 92 mergeable=pr_merge_enabled, enable_notifications=False)
93 93
94 94 response = self.app.get(route_path(
95 95 'pullrequest_show',
96 96 repo_name=pull_request.target_repo.scm_instance().name,
97 97 pull_request_id=pull_request.pull_request_id))
98 98
99 99 for commit_id in pull_request.revisions:
100 100 response.mustcontain(commit_id)
101 101
102 102 assert pull_request.target_ref_parts.type in response
103 103 assert pull_request.target_ref_parts.name in response
104 104 target_clone_url = pull_request.target_repo.clone_url()
105 105 assert target_clone_url in response
106 106
107 107 assert 'class="pull-request-merge"' in response
108 108 assert (
109 109 'Server-side pull request merging is disabled.'
110 110 in response) != pr_merge_enabled
111 111
112 112 def test_close_status_visibility(self, pr_util, user_util, csrf_token):
113 113 # Logout
114 114 response = self.app.post(
115 115 h.route_path('logout'),
116 116 params={'csrf_token': csrf_token})
117 117 # Login as regular user
118 118 response = self.app.post(h.route_path('login'),
119 119 {'username': TEST_USER_REGULAR_LOGIN,
120 120 'password': 'test12'})
121 121
122 122 pull_request = pr_util.create_pull_request(
123 123 author=TEST_USER_REGULAR_LOGIN)
124 124
125 125 response = self.app.get(route_path(
126 126 'pullrequest_show',
127 127 repo_name=pull_request.target_repo.scm_instance().name,
128 128 pull_request_id=pull_request.pull_request_id))
129 129
130 130 response.mustcontain('Server-side pull request merging is disabled.')
131 131
132 132 assert_response = response.assert_response()
133 133 # for regular user without a merge permissions, we don't see it
134 134 assert_response.no_element_exists('#close-pull-request-action')
135 135
136 136 user_util.grant_user_permission_to_repo(
137 137 pull_request.target_repo,
138 138 UserModel().get_by_username(TEST_USER_REGULAR_LOGIN),
139 139 'repository.write')
140 140 response = self.app.get(route_path(
141 141 'pullrequest_show',
142 142 repo_name=pull_request.target_repo.scm_instance().name,
143 143 pull_request_id=pull_request.pull_request_id))
144 144
145 145 response.mustcontain('Server-side pull request merging is disabled.')
146 146
147 147 assert_response = response.assert_response()
148 148 # now regular user has a merge permissions, we have CLOSE button
149 149 assert_response.one_element_exists('#close-pull-request-action')
150 150
151 151 def test_show_invalid_commit_id(self, pr_util):
152 152 # Simulating invalid revisions which will cause a lookup error
153 153 pull_request = pr_util.create_pull_request()
154 154 pull_request.revisions = ['invalid']
155 155 Session().add(pull_request)
156 156 Session().commit()
157 157
158 158 response = self.app.get(route_path(
159 159 'pullrequest_show',
160 160 repo_name=pull_request.target_repo.scm_instance().name,
161 161 pull_request_id=pull_request.pull_request_id))
162 162
163 163 for commit_id in pull_request.revisions:
164 164 response.mustcontain(commit_id)
165 165
166 166 def test_show_invalid_source_reference(self, pr_util):
167 167 pull_request = pr_util.create_pull_request()
168 168 pull_request.source_ref = 'branch:b:invalid'
169 169 Session().add(pull_request)
170 170 Session().commit()
171 171
172 172 self.app.get(route_path(
173 173 'pullrequest_show',
174 174 repo_name=pull_request.target_repo.scm_instance().name,
175 175 pull_request_id=pull_request.pull_request_id))
176 176
177 177 def test_edit_title_description(self, pr_util, csrf_token):
178 178 pull_request = pr_util.create_pull_request()
179 179 pull_request_id = pull_request.pull_request_id
180 180
181 181 response = self.app.post(
182 182 route_path('pullrequest_update',
183 183 repo_name=pull_request.target_repo.repo_name,
184 184 pull_request_id=pull_request_id),
185 185 params={
186 186 'edit_pull_request': 'true',
187 187 'title': 'New title',
188 188 'description': 'New description',
189 189 'csrf_token': csrf_token})
190 190
191 191 assert_session_flash(
192 192 response, u'Pull request title & description updated.',
193 193 category='success')
194 194
195 195 pull_request = PullRequest.get(pull_request_id)
196 196 assert pull_request.title == 'New title'
197 197 assert pull_request.description == 'New description'
198 198
199 199 def test_edit_title_description_closed(self, pr_util, csrf_token):
200 200 pull_request = pr_util.create_pull_request()
201 201 pull_request_id = pull_request.pull_request_id
202 202 pr_util.close()
203 203
204 204 response = self.app.post(
205 205 route_path('pullrequest_update',
206 206 repo_name=pull_request.target_repo.repo_name,
207 207 pull_request_id=pull_request_id),
208 208 params={
209 209 'edit_pull_request': 'true',
210 210 'title': 'New title',
211 211 'description': 'New description',
212 212 'csrf_token': csrf_token})
213 213
214 214 assert_session_flash(
215 215 response, u'Cannot update closed pull requests.',
216 216 category='error')
217 217
218 218 def test_update_invalid_source_reference(self, pr_util, csrf_token):
219 219 from rhodecode.lib.vcs.backends.base import UpdateFailureReason
220 220
221 221 pull_request = pr_util.create_pull_request()
222 222 pull_request.source_ref = 'branch:invalid-branch:invalid-commit-id'
223 223 Session().add(pull_request)
224 224 Session().commit()
225 225
226 226 pull_request_id = pull_request.pull_request_id
227 227
228 228 response = self.app.post(
229 229 route_path('pullrequest_update',
230 230 repo_name=pull_request.target_repo.repo_name,
231 231 pull_request_id=pull_request_id),
232 232 params={'update_commits': 'true',
233 233 'csrf_token': csrf_token})
234 234
235 235 expected_msg = PullRequestModel.UPDATE_STATUS_MESSAGES[
236 236 UpdateFailureReason.MISSING_SOURCE_REF]
237 237 assert_session_flash(response, expected_msg, category='error')
238 238
239 239 def test_missing_target_reference(self, pr_util, csrf_token):
240 240 from rhodecode.lib.vcs.backends.base import MergeFailureReason
241 241 pull_request = pr_util.create_pull_request(
242 242 approved=True, mergeable=True)
243 243 pull_request.target_ref = 'branch:invalid-branch:invalid-commit-id'
244 244 Session().add(pull_request)
245 245 Session().commit()
246 246
247 247 pull_request_id = pull_request.pull_request_id
248 248 pull_request_url = route_path(
249 249 'pullrequest_show',
250 250 repo_name=pull_request.target_repo.repo_name,
251 251 pull_request_id=pull_request_id)
252 252
253 253 response = self.app.get(pull_request_url)
254 254
255 255 assertr = AssertResponse(response)
256 256 expected_msg = PullRequestModel.MERGE_STATUS_MESSAGES[
257 257 MergeFailureReason.MISSING_TARGET_REF]
258 258 assertr.element_contains(
259 259 'span[data-role="merge-message"]', str(expected_msg))
260 260
261 261 def test_comment_and_close_pull_request_custom_message_approved(
262 262 self, pr_util, csrf_token, xhr_header):
263 263
264 264 pull_request = pr_util.create_pull_request(approved=True)
265 265 pull_request_id = pull_request.pull_request_id
266 266 author = pull_request.user_id
267 267 repo = pull_request.target_repo.repo_id
268 268
269 269 self.app.post(
270 270 route_path('pullrequest_comment_create',
271 271 repo_name=pull_request.target_repo.scm_instance().name,
272 272 pull_request_id=pull_request_id),
273 273 params={
274 274 'close_pull_request': '1',
275 275 'text': 'Closing a PR',
276 276 'csrf_token': csrf_token},
277 277 extra_environ=xhr_header,)
278 278
279 279 journal = UserLog.query()\
280 280 .filter(UserLog.user_id == author)\
281 281 .filter(UserLog.repository_id == repo) \
282 282 .order_by('user_log_id') \
283 283 .all()
284 284 assert journal[-1].action == 'repo.pull_request.close'
285 285
286 286 pull_request = PullRequest.get(pull_request_id)
287 287 assert pull_request.is_closed()
288 288
289 289 status = ChangesetStatusModel().get_status(
290 290 pull_request.source_repo, pull_request=pull_request)
291 291 assert status == ChangesetStatus.STATUS_APPROVED
292 292 comments = ChangesetComment().query() \
293 293 .filter(ChangesetComment.pull_request == pull_request) \
294 294 .order_by(ChangesetComment.comment_id.asc())\
295 295 .all()
296 296 assert comments[-1].text == 'Closing a PR'
297 297
298 298 def test_comment_force_close_pull_request_rejected(
299 299 self, pr_util, csrf_token, xhr_header):
300 300 pull_request = pr_util.create_pull_request()
301 301 pull_request_id = pull_request.pull_request_id
302 302 PullRequestModel().update_reviewers(
303 303 pull_request_id, [(1, ['reason'], False), (2, ['reason2'], False)],
304 304 pull_request.author)
305 305 author = pull_request.user_id
306 306 repo = pull_request.target_repo.repo_id
307 307
308 308 self.app.post(
309 309 route_path('pullrequest_comment_create',
310 310 repo_name=pull_request.target_repo.scm_instance().name,
311 311 pull_request_id=pull_request_id),
312 312 params={
313 313 'close_pull_request': '1',
314 314 'csrf_token': csrf_token},
315 315 extra_environ=xhr_header)
316 316
317 317 pull_request = PullRequest.get(pull_request_id)
318 318
319 319 journal = UserLog.query()\
320 320 .filter(UserLog.user_id == author, UserLog.repository_id == repo) \
321 321 .order_by('user_log_id') \
322 322 .all()
323 323 assert journal[-1].action == 'repo.pull_request.close'
324 324
325 325 # check only the latest status, not the review status
326 326 status = ChangesetStatusModel().get_status(
327 327 pull_request.source_repo, pull_request=pull_request)
328 328 assert status == ChangesetStatus.STATUS_REJECTED
329 329
330 330 def test_comment_and_close_pull_request(
331 331 self, pr_util, csrf_token, xhr_header):
332 332 pull_request = pr_util.create_pull_request()
333 333 pull_request_id = pull_request.pull_request_id
334 334
335 335 response = self.app.post(
336 336 route_path('pullrequest_comment_create',
337 337 repo_name=pull_request.target_repo.scm_instance().name,
338 338 pull_request_id=pull_request.pull_request_id),
339 339 params={
340 340 'close_pull_request': 'true',
341 341 'csrf_token': csrf_token},
342 342 extra_environ=xhr_header)
343 343
344 344 assert response.json
345 345
346 346 pull_request = PullRequest.get(pull_request_id)
347 347 assert pull_request.is_closed()
348 348
349 349 # check only the latest status, not the review status
350 350 status = ChangesetStatusModel().get_status(
351 351 pull_request.source_repo, pull_request=pull_request)
352 352 assert status == ChangesetStatus.STATUS_REJECTED
353 353
354 354 def test_create_pull_request(self, backend, csrf_token):
355 355 commits = [
356 356 {'message': 'ancestor'},
357 357 {'message': 'change'},
358 358 {'message': 'change2'},
359 359 ]
360 360 commit_ids = backend.create_master_repo(commits)
361 361 target = backend.create_repo(heads=['ancestor'])
362 362 source = backend.create_repo(heads=['change2'])
363 363
364 364 response = self.app.post(
365 365 route_path('pullrequest_create', repo_name=source.repo_name),
366 366 [
367 367 ('source_repo', source.repo_name),
368 368 ('source_ref', 'branch:default:' + commit_ids['change2']),
369 369 ('target_repo', target.repo_name),
370 370 ('target_ref', 'branch:default:' + commit_ids['ancestor']),
371 371 ('common_ancestor', commit_ids['ancestor']),
372 372 ('pullrequest_desc', 'Description'),
373 373 ('pullrequest_title', 'Title'),
374 374 ('__start__', 'review_members:sequence'),
375 375 ('__start__', 'reviewer:mapping'),
376 376 ('user_id', '1'),
377 377 ('__start__', 'reasons:sequence'),
378 378 ('reason', 'Some reason'),
379 379 ('__end__', 'reasons:sequence'),
380 380 ('mandatory', 'False'),
381 381 ('__end__', 'reviewer:mapping'),
382 382 ('__end__', 'review_members:sequence'),
383 383 ('__start__', 'revisions:sequence'),
384 384 ('revisions', commit_ids['change']),
385 385 ('revisions', commit_ids['change2']),
386 386 ('__end__', 'revisions:sequence'),
387 387 ('user', ''),
388 388 ('csrf_token', csrf_token),
389 389 ],
390 390 status=302)
391 391
392 392 location = response.headers['Location']
393 393 pull_request_id = location.rsplit('/', 1)[1]
394 394 assert pull_request_id != 'new'
395 395 pull_request = PullRequest.get(int(pull_request_id))
396 396
397 397 # check that we have now both revisions
398 398 assert pull_request.revisions == [commit_ids['change2'], commit_ids['change']]
399 399 assert pull_request.source_ref == 'branch:default:' + commit_ids['change2']
400 400 expected_target_ref = 'branch:default:' + commit_ids['ancestor']
401 401 assert pull_request.target_ref == expected_target_ref
402 402
403 403 def test_reviewer_notifications(self, backend, csrf_token):
404 404 # We have to use the app.post for this test so it will create the
405 405 # notifications properly with the new PR
406 406 commits = [
407 407 {'message': 'ancestor',
408 408 'added': [FileNode('file_A', content='content_of_ancestor')]},
409 409 {'message': 'change',
410 410 'added': [FileNode('file_a', content='content_of_change')]},
411 411 {'message': 'change-child'},
412 412 {'message': 'ancestor-child', 'parents': ['ancestor'],
413 413 'added': [
414 414 FileNode('file_B', content='content_of_ancestor_child')]},
415 415 {'message': 'ancestor-child-2'},
416 416 ]
417 417 commit_ids = backend.create_master_repo(commits)
418 418 target = backend.create_repo(heads=['ancestor-child'])
419 419 source = backend.create_repo(heads=['change'])
420 420
421 421 response = self.app.post(
422 422 route_path('pullrequest_create', repo_name=source.repo_name),
423 423 [
424 424 ('source_repo', source.repo_name),
425 425 ('source_ref', 'branch:default:' + commit_ids['change']),
426 426 ('target_repo', target.repo_name),
427 427 ('target_ref', 'branch:default:' + commit_ids['ancestor-child']),
428 428 ('common_ancestor', commit_ids['ancestor']),
429 429 ('pullrequest_desc', 'Description'),
430 430 ('pullrequest_title', 'Title'),
431 431 ('__start__', 'review_members:sequence'),
432 432 ('__start__', 'reviewer:mapping'),
433 433 ('user_id', '2'),
434 434 ('__start__', 'reasons:sequence'),
435 435 ('reason', 'Some reason'),
436 436 ('__end__', 'reasons:sequence'),
437 437 ('mandatory', 'False'),
438 438 ('__end__', 'reviewer:mapping'),
439 439 ('__end__', 'review_members:sequence'),
440 440 ('__start__', 'revisions:sequence'),
441 441 ('revisions', commit_ids['change']),
442 442 ('__end__', 'revisions:sequence'),
443 443 ('user', ''),
444 444 ('csrf_token', csrf_token),
445 445 ],
446 446 status=302)
447 447
448 448 location = response.headers['Location']
449 449
450 450 pull_request_id = location.rsplit('/', 1)[1]
451 451 assert pull_request_id != 'new'
452 452 pull_request = PullRequest.get(int(pull_request_id))
453 453
454 454 # Check that a notification was made
455 455 notifications = Notification.query()\
456 456 .filter(Notification.created_by == pull_request.author.user_id,
457 457 Notification.type_ == Notification.TYPE_PULL_REQUEST,
458 458 Notification.subject.contains(
459 459 "wants you to review pull request #%s" % pull_request_id))
460 460 assert len(notifications.all()) == 1
461 461
462 462 # Change reviewers and check that a notification was made
463 463 PullRequestModel().update_reviewers(
464 464 pull_request.pull_request_id, [(1, [], False)],
465 465 pull_request.author)
466 466 assert len(notifications.all()) == 2
467 467
468 468 def test_create_pull_request_stores_ancestor_commit_id(self, backend,
469 469 csrf_token):
470 470 commits = [
471 471 {'message': 'ancestor',
472 472 'added': [FileNode('file_A', content='content_of_ancestor')]},
473 473 {'message': 'change',
474 474 'added': [FileNode('file_a', content='content_of_change')]},
475 475 {'message': 'change-child'},
476 476 {'message': 'ancestor-child', 'parents': ['ancestor'],
477 477 'added': [
478 478 FileNode('file_B', content='content_of_ancestor_child')]},
479 479 {'message': 'ancestor-child-2'},
480 480 ]
481 481 commit_ids = backend.create_master_repo(commits)
482 482 target = backend.create_repo(heads=['ancestor-child'])
483 483 source = backend.create_repo(heads=['change'])
484 484
485 485 response = self.app.post(
486 486 route_path('pullrequest_create', repo_name=source.repo_name),
487 487 [
488 488 ('source_repo', source.repo_name),
489 489 ('source_ref', 'branch:default:' + commit_ids['change']),
490 490 ('target_repo', target.repo_name),
491 491 ('target_ref', 'branch:default:' + commit_ids['ancestor-child']),
492 492 ('common_ancestor', commit_ids['ancestor']),
493 493 ('pullrequest_desc', 'Description'),
494 494 ('pullrequest_title', 'Title'),
495 495 ('__start__', 'review_members:sequence'),
496 496 ('__start__', 'reviewer:mapping'),
497 497 ('user_id', '1'),
498 498 ('__start__', 'reasons:sequence'),
499 499 ('reason', 'Some reason'),
500 500 ('__end__', 'reasons:sequence'),
501 501 ('mandatory', 'False'),
502 502 ('__end__', 'reviewer:mapping'),
503 503 ('__end__', 'review_members:sequence'),
504 504 ('__start__', 'revisions:sequence'),
505 505 ('revisions', commit_ids['change']),
506 506 ('__end__', 'revisions:sequence'),
507 507 ('user', ''),
508 508 ('csrf_token', csrf_token),
509 509 ],
510 510 status=302)
511 511
512 512 location = response.headers['Location']
513 513
514 514 pull_request_id = location.rsplit('/', 1)[1]
515 515 assert pull_request_id != 'new'
516 516 pull_request = PullRequest.get(int(pull_request_id))
517 517
518 518 # target_ref has to point to the ancestor's commit_id in order to
519 519 # show the correct diff
520 520 expected_target_ref = 'branch:default:' + commit_ids['ancestor']
521 521 assert pull_request.target_ref == expected_target_ref
522 522
523 523 # Check generated diff contents
524 524 response = response.follow()
525 525 assert 'content_of_ancestor' not in response.body
526 526 assert 'content_of_ancestor-child' not in response.body
527 527 assert 'content_of_change' in response.body
528 528
529 529 def test_merge_pull_request_enabled(self, pr_util, csrf_token):
530 530 # Clear any previous calls to rcextensions
531 531 rhodecode.EXTENSIONS.calls.clear()
532 532
533 533 pull_request = pr_util.create_pull_request(
534 534 approved=True, mergeable=True)
535 535 pull_request_id = pull_request.pull_request_id
536 536 repo_name = pull_request.target_repo.scm_instance().name,
537 537
538 538 response = self.app.post(
539 539 route_path('pullrequest_merge',
540 540 repo_name=str(repo_name[0]),
541 541 pull_request_id=pull_request_id),
542 542 params={'csrf_token': csrf_token}).follow()
543 543
544 544 pull_request = PullRequest.get(pull_request_id)
545 545
546 546 assert response.status_int == 200
547 547 assert pull_request.is_closed()
548 548 assert_pull_request_status(
549 549 pull_request, ChangesetStatus.STATUS_APPROVED)
550 550
551 551 # Check the relevant log entries were added
552 552 user_logs = UserLog.query().order_by('-user_log_id').limit(3)
553 553 actions = [log.action for log in user_logs]
554 554 pr_commit_ids = PullRequestModel()._get_commit_ids(pull_request)
555 555 expected_actions = [
556 556 u'repo.pull_request.close',
557 557 u'repo.pull_request.merge',
558 558 u'repo.pull_request.comment.create'
559 559 ]
560 560 assert actions == expected_actions
561 561
562 562 user_logs = UserLog.query().order_by('-user_log_id').limit(4)
563 563 actions = [log for log in user_logs]
564 564 assert actions[-1].action == 'user.push'
565 565 assert actions[-1].action_data['commit_ids'] == pr_commit_ids
566 566
567 567 # Check post_push rcextension was really executed
568 568 push_calls = rhodecode.EXTENSIONS.calls['post_push']
569 569 assert len(push_calls) == 1
570 570 unused_last_call_args, last_call_kwargs = push_calls[0]
571 571 assert last_call_kwargs['action'] == 'push'
572 572 assert last_call_kwargs['pushed_revs'] == pr_commit_ids
573 573
574 574 def test_merge_pull_request_disabled(self, pr_util, csrf_token):
575 575 pull_request = pr_util.create_pull_request(mergeable=False)
576 576 pull_request_id = pull_request.pull_request_id
577 577 pull_request = PullRequest.get(pull_request_id)
578 578
579 579 response = self.app.post(
580 580 route_path('pullrequest_merge',
581 581 repo_name=pull_request.target_repo.scm_instance().name,
582 582 pull_request_id=pull_request.pull_request_id),
583 583 params={'csrf_token': csrf_token}).follow()
584 584
585 585 assert response.status_int == 200
586 586 response.mustcontain(
587 587 'Merge is not currently possible because of below failed checks.')
588 588 response.mustcontain('Server-side pull request merging is disabled.')
589 589
590 590 @pytest.mark.skip_backends('svn')
591 591 def test_merge_pull_request_not_approved(self, pr_util, csrf_token):
592 592 pull_request = pr_util.create_pull_request(mergeable=True)
593 593 pull_request_id = pull_request.pull_request_id
594 594 repo_name = pull_request.target_repo.scm_instance().name
595 595
596 596 response = self.app.post(
597 597 route_path('pullrequest_merge',
598 598 repo_name=repo_name,
599 599 pull_request_id=pull_request_id),
600 600 params={'csrf_token': csrf_token}).follow()
601 601
602 602 assert response.status_int == 200
603 603
604 604 response.mustcontain(
605 605 'Merge is not currently possible because of below failed checks.')
606 606 response.mustcontain('Pull request reviewer approval is pending.')
607 607
608 608 def test_merge_pull_request_renders_failure_reason(
609 609 self, user_regular, csrf_token, pr_util):
610 610 pull_request = pr_util.create_pull_request(mergeable=True, approved=True)
611 611 pull_request_id = pull_request.pull_request_id
612 612 repo_name = pull_request.target_repo.scm_instance().name
613 613
614 614 model_patcher = mock.patch.multiple(
615 615 PullRequestModel,
616 616 merge=mock.Mock(return_value=MergeResponse(
617 617 True, False, 'STUB_COMMIT_ID', MergeFailureReason.PUSH_FAILED)),
618 618 merge_status=mock.Mock(return_value=(True, 'WRONG_MESSAGE')))
619 619
620 620 with model_patcher:
621 621 response = self.app.post(
622 622 route_path('pullrequest_merge',
623 623 repo_name=repo_name,
624 624 pull_request_id=pull_request_id),
625 625 params={'csrf_token': csrf_token}, status=302)
626 626
627 627 assert_session_flash(response, PullRequestModel.MERGE_STATUS_MESSAGES[
628 628 MergeFailureReason.PUSH_FAILED])
629 629
630 630 def test_update_source_revision(self, backend, csrf_token):
631 631 commits = [
632 632 {'message': 'ancestor'},
633 633 {'message': 'change'},
634 634 {'message': 'change-2'},
635 635 ]
636 636 commit_ids = backend.create_master_repo(commits)
637 637 target = backend.create_repo(heads=['ancestor'])
638 638 source = backend.create_repo(heads=['change'])
639 639
640 640 # create pr from a in source to A in target
641 641 pull_request = PullRequest()
642 642 pull_request.source_repo = source
643 643 # TODO: johbo: Make sure that we write the source ref this way!
644 644 pull_request.source_ref = 'branch:{branch}:{commit_id}'.format(
645 645 branch=backend.default_branch_name, commit_id=commit_ids['change'])
646 646 pull_request.target_repo = target
647 647
648 648 pull_request.target_ref = 'branch:{branch}:{commit_id}'.format(
649 649 branch=backend.default_branch_name,
650 650 commit_id=commit_ids['ancestor'])
651 651 pull_request.revisions = [commit_ids['change']]
652 652 pull_request.title = u"Test"
653 653 pull_request.description = u"Description"
654 654 pull_request.author = UserModel().get_by_username(
655 655 TEST_USER_ADMIN_LOGIN)
656 656 Session().add(pull_request)
657 657 Session().commit()
658 658 pull_request_id = pull_request.pull_request_id
659 659
660 660 # source has ancestor - change - change-2
661 661 backend.pull_heads(source, heads=['change-2'])
662 662
663 663 # update PR
664 664 self.app.post(
665 665 route_path('pullrequest_update',
666 666 repo_name=target.repo_name,
667 667 pull_request_id=pull_request_id),
668 668 params={'update_commits': 'true',
669 669 'csrf_token': csrf_token})
670 670
671 671 # check that we have now both revisions
672 672 pull_request = PullRequest.get(pull_request_id)
673 673 assert pull_request.revisions == [
674 674 commit_ids['change-2'], commit_ids['change']]
675 675
676 676 # TODO: johbo: this should be a test on its own
677 677 response = self.app.get(route_path(
678 678 'pullrequest_new',
679 679 repo_name=target.repo_name))
680 680 assert response.status_int == 200
681 681 assert 'Pull request updated to' in response.body
682 682 assert 'with 1 added, 0 removed commits.' in response.body
683 683
684 684 def test_update_target_revision(self, backend, csrf_token):
685 685 commits = [
686 686 {'message': 'ancestor'},
687 687 {'message': 'change'},
688 688 {'message': 'ancestor-new', 'parents': ['ancestor']},
689 689 {'message': 'change-rebased'},
690 690 ]
691 691 commit_ids = backend.create_master_repo(commits)
692 692 target = backend.create_repo(heads=['ancestor'])
693 693 source = backend.create_repo(heads=['change'])
694 694
695 695 # create pr from a in source to A in target
696 696 pull_request = PullRequest()
697 697 pull_request.source_repo = source
698 698 # TODO: johbo: Make sure that we write the source ref this way!
699 699 pull_request.source_ref = 'branch:{branch}:{commit_id}'.format(
700 700 branch=backend.default_branch_name, commit_id=commit_ids['change'])
701 701 pull_request.target_repo = target
702 702 # TODO: johbo: Target ref should be branch based, since tip can jump
703 703 # from branch to branch
704 704 pull_request.target_ref = 'branch:{branch}:{commit_id}'.format(
705 705 branch=backend.default_branch_name,
706 706 commit_id=commit_ids['ancestor'])
707 707 pull_request.revisions = [commit_ids['change']]
708 708 pull_request.title = u"Test"
709 709 pull_request.description = u"Description"
710 710 pull_request.author = UserModel().get_by_username(
711 711 TEST_USER_ADMIN_LOGIN)
712 712 Session().add(pull_request)
713 713 Session().commit()
714 714 pull_request_id = pull_request.pull_request_id
715 715
716 716 # target has ancestor - ancestor-new
717 717 # source has ancestor - ancestor-new - change-rebased
718 718 backend.pull_heads(target, heads=['ancestor-new'])
719 719 backend.pull_heads(source, heads=['change-rebased'])
720 720
721 721 # update PR
722 722 self.app.post(
723 723 route_path('pullrequest_update',
724 724 repo_name=target.repo_name,
725 725 pull_request_id=pull_request_id),
726 726 params={'update_commits': 'true',
727 727 'csrf_token': csrf_token},
728 728 status=200)
729 729
730 730 # check that we have now both revisions
731 731 pull_request = PullRequest.get(pull_request_id)
732 732 assert pull_request.revisions == [commit_ids['change-rebased']]
733 733 assert pull_request.target_ref == 'branch:{branch}:{commit_id}'.format(
734 734 branch=backend.default_branch_name,
735 735 commit_id=commit_ids['ancestor-new'])
736 736
737 737 # TODO: johbo: This should be a test on its own
738 738 response = self.app.get(route_path(
739 739 'pullrequest_new',
740 740 repo_name=target.repo_name))
741 741 assert response.status_int == 200
742 742 assert 'Pull request updated to' in response.body
743 743 assert 'with 1 added, 1 removed commits.' in response.body
744 744
745 745 def test_update_of_ancestor_reference(self, backend, csrf_token):
746 746 commits = [
747 747 {'message': 'ancestor'},
748 748 {'message': 'change'},
749 749 {'message': 'change-2'},
750 750 {'message': 'ancestor-new', 'parents': ['ancestor']},
751 751 {'message': 'change-rebased'},
752 752 ]
753 753 commit_ids = backend.create_master_repo(commits)
754 754 target = backend.create_repo(heads=['ancestor'])
755 755 source = backend.create_repo(heads=['change'])
756 756
757 757 # create pr from a in source to A in target
758 758 pull_request = PullRequest()
759 759 pull_request.source_repo = source
760 760 # TODO: johbo: Make sure that we write the source ref this way!
761 761 pull_request.source_ref = 'branch:{branch}:{commit_id}'.format(
762 762 branch=backend.default_branch_name,
763 763 commit_id=commit_ids['change'])
764 764 pull_request.target_repo = target
765 765 # TODO: johbo: Target ref should be branch based, since tip can jump
766 766 # from branch to branch
767 767 pull_request.target_ref = 'branch:{branch}:{commit_id}'.format(
768 768 branch=backend.default_branch_name,
769 769 commit_id=commit_ids['ancestor'])
770 770 pull_request.revisions = [commit_ids['change']]
771 771 pull_request.title = u"Test"
772 772 pull_request.description = u"Description"
773 773 pull_request.author = UserModel().get_by_username(
774 774 TEST_USER_ADMIN_LOGIN)
775 775 Session().add(pull_request)
776 776 Session().commit()
777 777 pull_request_id = pull_request.pull_request_id
778 778
779 779 # target has ancestor - ancestor-new
780 780 # source has ancestor - ancestor-new - change-rebased
781 781 backend.pull_heads(target, heads=['ancestor-new'])
782 782 backend.pull_heads(source, heads=['change-rebased'])
783 783
784 784 # update PR
785 785 self.app.post(
786 786 route_path('pullrequest_update',
787 787 repo_name=target.repo_name,
788 788 pull_request_id=pull_request_id),
789 789 params={'update_commits': 'true',
790 790 'csrf_token': csrf_token},
791 791 status=200)
792 792
793 793 # Expect the target reference to be updated correctly
794 794 pull_request = PullRequest.get(pull_request_id)
795 795 assert pull_request.revisions == [commit_ids['change-rebased']]
796 796 expected_target_ref = 'branch:{branch}:{commit_id}'.format(
797 797 branch=backend.default_branch_name,
798 798 commit_id=commit_ids['ancestor-new'])
799 799 assert pull_request.target_ref == expected_target_ref
800 800
801 801 def test_remove_pull_request_branch(self, backend_git, csrf_token):
802 802 branch_name = 'development'
803 803 commits = [
804 804 {'message': 'initial-commit'},
805 805 {'message': 'old-feature'},
806 806 {'message': 'new-feature', 'branch': branch_name},
807 807 ]
808 808 repo = backend_git.create_repo(commits)
809 809 commit_ids = backend_git.commit_ids
810 810
811 811 pull_request = PullRequest()
812 812 pull_request.source_repo = repo
813 813 pull_request.target_repo = repo
814 814 pull_request.source_ref = 'branch:{branch}:{commit_id}'.format(
815 815 branch=branch_name, commit_id=commit_ids['new-feature'])
816 816 pull_request.target_ref = 'branch:{branch}:{commit_id}'.format(
817 817 branch=backend_git.default_branch_name,
818 818 commit_id=commit_ids['old-feature'])
819 819 pull_request.revisions = [commit_ids['new-feature']]
820 820 pull_request.title = u"Test"
821 821 pull_request.description = u"Description"
822 822 pull_request.author = UserModel().get_by_username(
823 823 TEST_USER_ADMIN_LOGIN)
824 824 Session().add(pull_request)
825 825 Session().commit()
826 826
827 827 vcs = repo.scm_instance()
828 828 vcs.remove_ref('refs/heads/{}'.format(branch_name))
829 829
830 830 response = self.app.get(route_path(
831 831 'pullrequest_show',
832 832 repo_name=repo.repo_name,
833 833 pull_request_id=pull_request.pull_request_id))
834 834
835 835 assert response.status_int == 200
836 836 assert_response = AssertResponse(response)
837 837 assert_response.element_contains(
838 838 '#changeset_compare_view_content .alert strong',
839 839 'Missing commits')
840 840 assert_response.element_contains(
841 841 '#changeset_compare_view_content .alert',
842 842 'This pull request cannot be displayed, because one or more'
843 843 ' commits no longer exist in the source repository.')
844 844
845 845 def test_strip_commits_from_pull_request(
846 846 self, backend, pr_util, csrf_token):
847 847 commits = [
848 848 {'message': 'initial-commit'},
849 849 {'message': 'old-feature'},
850 850 {'message': 'new-feature', 'parents': ['initial-commit']},
851 851 ]
852 852 pull_request = pr_util.create_pull_request(
853 853 commits, target_head='initial-commit', source_head='new-feature',
854 854 revisions=['new-feature'])
855 855
856 856 vcs = pr_util.source_repository.scm_instance()
857 857 if backend.alias == 'git':
858 858 vcs.strip(pr_util.commit_ids['new-feature'], branch_name='master')
859 859 else:
860 860 vcs.strip(pr_util.commit_ids['new-feature'])
861 861
862 862 response = self.app.get(route_path(
863 863 'pullrequest_show',
864 864 repo_name=pr_util.target_repository.repo_name,
865 865 pull_request_id=pull_request.pull_request_id))
866 866
867 867 assert response.status_int == 200
868 868 assert_response = AssertResponse(response)
869 869 assert_response.element_contains(
870 870 '#changeset_compare_view_content .alert strong',
871 871 'Missing commits')
872 872 assert_response.element_contains(
873 873 '#changeset_compare_view_content .alert',
874 874 'This pull request cannot be displayed, because one or more'
875 875 ' commits no longer exist in the source repository.')
876 876 assert_response.element_contains(
877 877 '#update_commits',
878 878 'Update commits')
879 879
880 880 def test_strip_commits_and_update(
881 881 self, backend, pr_util, csrf_token):
882 882 commits = [
883 883 {'message': 'initial-commit'},
884 884 {'message': 'old-feature'},
885 885 {'message': 'new-feature', 'parents': ['old-feature']},
886 886 ]
887 887 pull_request = pr_util.create_pull_request(
888 888 commits, target_head='old-feature', source_head='new-feature',
889 889 revisions=['new-feature'], mergeable=True)
890 890
891 891 vcs = pr_util.source_repository.scm_instance()
892 892 if backend.alias == 'git':
893 893 vcs.strip(pr_util.commit_ids['new-feature'], branch_name='master')
894 894 else:
895 895 vcs.strip(pr_util.commit_ids['new-feature'])
896 896
897 897 response = self.app.post(
898 898 route_path('pullrequest_update',
899 899 repo_name=pull_request.target_repo.repo_name,
900 900 pull_request_id=pull_request.pull_request_id),
901 901 params={'update_commits': 'true',
902 902 'csrf_token': csrf_token})
903 903
904 904 assert response.status_int == 200
905 905 assert response.body == 'true'
906 906
907 907 # Make sure that after update, it won't raise 500 errors
908 908 response = self.app.get(route_path(
909 909 'pullrequest_show',
910 910 repo_name=pr_util.target_repository.repo_name,
911 911 pull_request_id=pull_request.pull_request_id))
912 912
913 913 assert response.status_int == 200
914 914 assert_response = AssertResponse(response)
915 915 assert_response.element_contains(
916 916 '#changeset_compare_view_content .alert strong',
917 917 'Missing commits')
918 918
919 919 def test_branch_is_a_link(self, pr_util):
920 920 pull_request = pr_util.create_pull_request()
921 921 pull_request.source_ref = 'branch:origin:1234567890abcdef'
922 922 pull_request.target_ref = 'branch:target:abcdef1234567890'
923 923 Session().add(pull_request)
924 924 Session().commit()
925 925
926 926 response = self.app.get(route_path(
927 927 'pullrequest_show',
928 928 repo_name=pull_request.target_repo.scm_instance().name,
929 929 pull_request_id=pull_request.pull_request_id))
930 930 assert response.status_int == 200
931 931 assert_response = AssertResponse(response)
932 932
933 933 origin = assert_response.get_element('.pr-origininfo .tag')
934 934 origin_children = origin.getchildren()
935 935 assert len(origin_children) == 1
936 936 target = assert_response.get_element('.pr-targetinfo .tag')
937 937 target_children = target.getchildren()
938 938 assert len(target_children) == 1
939 939
940 940 expected_origin_link = route_path(
941 941 'repo_changelog',
942 942 repo_name=pull_request.source_repo.scm_instance().name,
943 943 params=dict(branch='origin'))
944 944 expected_target_link = route_path(
945 945 'repo_changelog',
946 946 repo_name=pull_request.target_repo.scm_instance().name,
947 947 params=dict(branch='target'))
948 948 assert origin_children[0].attrib['href'] == expected_origin_link
949 949 assert origin_children[0].text == 'branch: origin'
950 950 assert target_children[0].attrib['href'] == expected_target_link
951 951 assert target_children[0].text == 'branch: target'
952 952
953 953 def test_bookmark_is_not_a_link(self, pr_util):
954 954 pull_request = pr_util.create_pull_request()
955 955 pull_request.source_ref = 'bookmark:origin:1234567890abcdef'
956 956 pull_request.target_ref = 'bookmark:target:abcdef1234567890'
957 957 Session().add(pull_request)
958 958 Session().commit()
959 959
960 960 response = self.app.get(route_path(
961 961 'pullrequest_show',
962 962 repo_name=pull_request.target_repo.scm_instance().name,
963 963 pull_request_id=pull_request.pull_request_id))
964 964 assert response.status_int == 200
965 965 assert_response = AssertResponse(response)
966 966
967 967 origin = assert_response.get_element('.pr-origininfo .tag')
968 968 assert origin.text.strip() == 'bookmark: origin'
969 969 assert origin.getchildren() == []
970 970
971 971 target = assert_response.get_element('.pr-targetinfo .tag')
972 972 assert target.text.strip() == 'bookmark: target'
973 973 assert target.getchildren() == []
974 974
975 975 def test_tag_is_not_a_link(self, pr_util):
976 976 pull_request = pr_util.create_pull_request()
977 977 pull_request.source_ref = 'tag:origin:1234567890abcdef'
978 978 pull_request.target_ref = 'tag:target:abcdef1234567890'
979 979 Session().add(pull_request)
980 980 Session().commit()
981 981
982 982 response = self.app.get(route_path(
983 983 'pullrequest_show',
984 984 repo_name=pull_request.target_repo.scm_instance().name,
985 985 pull_request_id=pull_request.pull_request_id))
986 986 assert response.status_int == 200
987 987 assert_response = AssertResponse(response)
988 988
989 989 origin = assert_response.get_element('.pr-origininfo .tag')
990 990 assert origin.text.strip() == 'tag: origin'
991 991 assert origin.getchildren() == []
992 992
993 993 target = assert_response.get_element('.pr-targetinfo .tag')
994 994 assert target.text.strip() == 'tag: target'
995 995 assert target.getchildren() == []
996 996
997 997 @pytest.mark.parametrize('mergeable', [True, False])
998 998 def test_shadow_repository_link(
999 999 self, mergeable, pr_util, http_host_only_stub):
1000 1000 """
1001 1001 Check that the pull request summary page displays a link to the shadow
1002 1002 repository if the pull request is mergeable. If it is not mergeable
1003 1003 the link should not be displayed.
1004 1004 """
1005 1005 pull_request = pr_util.create_pull_request(
1006 1006 mergeable=mergeable, enable_notifications=False)
1007 1007 target_repo = pull_request.target_repo.scm_instance()
1008 1008 pr_id = pull_request.pull_request_id
1009 1009 shadow_url = '{host}/{repo}/pull-request/{pr_id}/repository'.format(
1010 1010 host=http_host_only_stub, repo=target_repo.name, pr_id=pr_id)
1011 1011
1012 1012 response = self.app.get(route_path(
1013 1013 'pullrequest_show',
1014 1014 repo_name=target_repo.name,
1015 1015 pull_request_id=pr_id))
1016 1016
1017 1017 assertr = AssertResponse(response)
1018 1018 if mergeable:
1019 assertr.element_value_contains(
1020 'div.pr-mergeinfo input', shadow_url)
1021 assertr.element_value_contains(
1022 'div.pr-mergeinfo input', 'pr-merge')
1019 assertr.element_value_contains('input.pr-mergeinfo', shadow_url)
1020 assertr.element_value_contains('input.pr-mergeinfo ', 'pr-merge')
1023 1021 else:
1024 assertr.no_element_exists('div.pr-mergeinfo')
1022 assertr.no_element_exists('.pr-mergeinfo')
1025 1023
1026 1024
1027 1025 @pytest.mark.usefixtures('app')
1028 1026 @pytest.mark.backends("git", "hg")
1029 1027 class TestPullrequestsControllerDelete(object):
1030 1028 def test_pull_request_delete_button_permissions_admin(
1031 1029 self, autologin_user, user_admin, pr_util):
1032 1030 pull_request = pr_util.create_pull_request(
1033 1031 author=user_admin.username, enable_notifications=False)
1034 1032
1035 1033 response = self.app.get(route_path(
1036 1034 'pullrequest_show',
1037 1035 repo_name=pull_request.target_repo.scm_instance().name,
1038 1036 pull_request_id=pull_request.pull_request_id))
1039 1037
1040 1038 response.mustcontain('id="delete_pullrequest"')
1041 1039 response.mustcontain('Confirm to delete this pull request')
1042 1040
1043 1041 def test_pull_request_delete_button_permissions_owner(
1044 1042 self, autologin_regular_user, user_regular, pr_util):
1045 1043 pull_request = pr_util.create_pull_request(
1046 1044 author=user_regular.username, enable_notifications=False)
1047 1045
1048 1046 response = self.app.get(route_path(
1049 1047 'pullrequest_show',
1050 1048 repo_name=pull_request.target_repo.scm_instance().name,
1051 1049 pull_request_id=pull_request.pull_request_id))
1052 1050
1053 1051 response.mustcontain('id="delete_pullrequest"')
1054 1052 response.mustcontain('Confirm to delete this pull request')
1055 1053
1056 1054 def test_pull_request_delete_button_permissions_forbidden(
1057 1055 self, autologin_regular_user, user_regular, user_admin, pr_util):
1058 1056 pull_request = pr_util.create_pull_request(
1059 1057 author=user_admin.username, enable_notifications=False)
1060 1058
1061 1059 response = self.app.get(route_path(
1062 1060 'pullrequest_show',
1063 1061 repo_name=pull_request.target_repo.scm_instance().name,
1064 1062 pull_request_id=pull_request.pull_request_id))
1065 1063 response.mustcontain(no=['id="delete_pullrequest"'])
1066 1064 response.mustcontain(no=['Confirm to delete this pull request'])
1067 1065
1068 1066 def test_pull_request_delete_button_permissions_can_update_cannot_delete(
1069 1067 self, autologin_regular_user, user_regular, user_admin, pr_util,
1070 1068 user_util):
1071 1069
1072 1070 pull_request = pr_util.create_pull_request(
1073 1071 author=user_admin.username, enable_notifications=False)
1074 1072
1075 1073 user_util.grant_user_permission_to_repo(
1076 1074 pull_request.target_repo, user_regular,
1077 1075 'repository.write')
1078 1076
1079 1077 response = self.app.get(route_path(
1080 1078 'pullrequest_show',
1081 1079 repo_name=pull_request.target_repo.scm_instance().name,
1082 1080 pull_request_id=pull_request.pull_request_id))
1083 1081
1084 1082 response.mustcontain('id="open_edit_pullrequest"')
1085 1083 response.mustcontain('id="delete_pullrequest"')
1086 1084 response.mustcontain(no=['Confirm to delete this pull request'])
1087 1085
1088 1086 def test_delete_comment_returns_404_if_comment_does_not_exist(
1089 1087 self, autologin_user, pr_util, user_admin):
1090 1088
1091 1089 pull_request = pr_util.create_pull_request(
1092 1090 author=user_admin.username, enable_notifications=False)
1093 1091
1094 1092 self.app.get(route_path(
1095 1093 'pullrequest_comment_delete',
1096 1094 repo_name=pull_request.target_repo.scm_instance().name,
1097 1095 pull_request_id=pull_request.pull_request_id,
1098 1096 comment_id=1024404), status=404)
1099 1097
1100 1098
1101 1099 def assert_pull_request_status(pull_request, expected_status):
1102 1100 status = ChangesetStatusModel().calculated_review_status(
1103 1101 pull_request=pull_request)
1104 1102 assert status == expected_status
1105 1103
1106 1104
1107 1105 @pytest.mark.parametrize('route', ['pullrequest_new', 'pullrequest_create'])
1108 1106 @pytest.mark.usefixtures("autologin_user")
1109 1107 def test_forbidde_to_repo_summary_for_svn_repositories(backend_svn, app, route):
1110 1108 response = app.get(
1111 1109 route_path(route, repo_name=backend_svn.repo_name), status=404)
1112 1110
General Comments 0
You need to be logged in to leave comments. Login now