test_pagure_flask_ui_pr_edit.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. # -*- coding: utf-8 -*-
  2. """
  3. Authors:
  4. Julen Landa Alustiza <jlanda@fedoraproject.org>
  5. """
  6. from __future__ import unicode_literals, absolute_import
  7. import sys
  8. import os
  9. import pagure_messages
  10. from fedora_messaging import api, testing
  11. from mock import ANY, patch
  12. sys.path.insert(
  13. 0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..")
  14. )
  15. import tests
  16. import pagure.lib.query
  17. import pygit2
  18. class PagureFlaskPrEditSimpletests(tests.Modeltests):
  19. def test_pr_edit_no_project(self):
  20. """Test the edit pull request endpoint"""
  21. output = self.app.get("/foo/pull-request/1/edit")
  22. self.assertEqual(output.status_code, 404)
  23. output_text = output.get_data(as_text=True)
  24. self.assertIn(
  25. "<title>Page not found :'( - Pagure</title>", output_text
  26. )
  27. self.assertIn("<h2>Page not found (404)</h2>", output_text)
  28. def test_pr_edit_no_git_repo(self):
  29. """Test the edit pull request endpoint"""
  30. tests.create_projects(self.session)
  31. output = self.app.get("/test/pull-request/1/edit")
  32. self.assertEqual(output.status_code, 404)
  33. output_text = output.get_data(as_text=True)
  34. self.assertIn(
  35. "<title>Page not found :'( - Pagure</title>", output_text
  36. )
  37. self.assertIn("<p>No git repo found</p>", output_text)
  38. def test_pr_edit_no_pull_requests_no_login(self):
  39. """Test the edit pull request endpoint"""
  40. tests.create_projects(self.session)
  41. tests.create_projects_git(os.path.join(self.path, "repos"), bare=True)
  42. output = self.app.get("/test/pull-request/1/edit")
  43. self.assertEqual(output.status_code, 302)
  44. def test_pr_edit_no_pull_requests(self):
  45. """Test the edit pull request endpoint"""
  46. tests.create_projects(self.session)
  47. tests.create_projects_git(os.path.join(self.path, "repos"), bare=True)
  48. user = tests.FakeUser()
  49. with tests.user_set(self.app.application, user):
  50. output = self.app.get("/test/pull-request/1/edit")
  51. self.assertEqual(output.status_code, 404)
  52. output_text = output.get_data(as_text=True)
  53. self.assertIn(
  54. "<title>Page not found :'( - Pagure</title>", output_text
  55. )
  56. self.assertIn("<p>Pull-request not found</p>", output_text)
  57. class PagureFlaskPrEdittests(tests.Modeltests):
  58. def setUp(self):
  59. super(PagureFlaskPrEdittests, self).setUp()
  60. tests.create_projects(self.session)
  61. tests.create_projects_git(os.path.join(self.path, "repos"), bare=True)
  62. # Create foo's fork of pingou's test project
  63. item = pagure.lib.model.Project(
  64. user_id=2, # foo
  65. name="test",
  66. description="test project #1",
  67. hook_token="aaabbb",
  68. is_fork=True,
  69. parent_id=1,
  70. )
  71. self.session.add(item)
  72. self.session.commit()
  73. # Create the fork's git repo
  74. repo_path = os.path.join(self.path, "repos", item.path)
  75. pygit2.init_repository(repo_path, bare=True)
  76. project = pagure.lib.query.get_authorized_project(self.session, "test")
  77. fork = pagure.lib.query.get_authorized_project(
  78. self.session, "test", user="foo"
  79. )
  80. tests.add_pull_request_git_repo(
  81. self.path,
  82. self.session,
  83. project,
  84. fork,
  85. user="foo",
  86. allow_rebase=True,
  87. )
  88. # Create a "main" branch in addition to the default "master" one
  89. repo_obj = pygit2.Repository(
  90. os.path.join(self.path, "repos", "test.git")
  91. )
  92. repo_obj.branches.local.create("main", repo_obj.head.peel())
  93. def tearDown(self):
  94. try:
  95. tests.clean_pull_requests_path()
  96. except:
  97. pass
  98. super(PagureFlaskPrEdittests, self).tearDown()
  99. def test_pr_edit_pull_request_unauthenticated(self):
  100. output = self.app.get("/test/pull-request/1/edit")
  101. self.assertEqual(output.status_code, 302)
  102. def test_pr_edit_pull_request_unauthorized(self):
  103. user = tests.FakeUser()
  104. with tests.user_set(self.app.application, user):
  105. output = self.app.get("/test/pull-request/1/edit")
  106. self.assertEqual(output.status_code, 403)
  107. output_text = output.get_data(as_text=True)
  108. self.assertIn("<title>403 Forbidden</title>", output_text)
  109. self.assertIn(
  110. "<p>You are not allowed to edit this pull-request</p>",
  111. output_text,
  112. )
  113. def test_pr_edit_pull_request_view_author(self):
  114. user = tests.FakeUser(username="foo")
  115. with tests.user_set(self.app.application, user):
  116. output = self.app.get("/test/pull-request/1/edit")
  117. self.assertEqual(output.status_code, 200)
  118. output_text = output.get_data(as_text=True)
  119. # Author is editing PR #1
  120. self.assertIn(
  121. "<title>Edit PR#1: PR from the feature branch - test - "
  122. "Pagure</title>",
  123. output_text,
  124. )
  125. # Author has a title input
  126. if self.get_wtforms_version() >= (2, 2):
  127. self.assertIn(
  128. '<input class="form-control" id="title" name="title" '
  129. 'required type="text" value="PR from the feature branch">',
  130. output_text,
  131. )
  132. else:
  133. self.assertIn(
  134. '<input class="form-control" id="title" name="title" '
  135. 'type="text" value="PR from the feature branch">',
  136. output_text,
  137. )
  138. # Author has an initial_commit textarea
  139. self.assertIn(
  140. '<textarea class="form-control width-100per" '
  141. 'id="initial_comment"\n '
  142. 'name="initial_comment"></textarea>',
  143. output_text,
  144. )
  145. # Author has an non-disabled allow_rebase input
  146. self.assertIn(
  147. '<input id="allow_rebase" name="allow_rebase" '
  148. 'type="checkbox" value="y" checked>',
  149. output_text,
  150. )
  151. def test_pr_edit_pull_request_post_author_no_csrf_token(self):
  152. user = tests.FakeUser(username="foo")
  153. with tests.user_set(self.app.application, user):
  154. data = {
  155. "title": "New title",
  156. "initial_comment": "New initial comment",
  157. "branch_to": "master",
  158. "allow_rebase": False,
  159. }
  160. output = self.app.post(
  161. "/test/pull-request/1/edit", data=data, follow_redirects=True
  162. )
  163. self.assertEqual(output.status_code, 200)
  164. output_text = output.get_data(as_text=True)
  165. # Without CSRF token, we finish again on the form with new
  166. # values.
  167. self.assertIn(
  168. "<title>Edit PR#1: PR from the feature branch - test - "
  169. "Pagure</title>",
  170. output_text,
  171. )
  172. if self.get_wtforms_version() >= (2, 2):
  173. self.assertIn(
  174. '<input class="form-control" id="title" name="title" '
  175. 'required type="text" value="New title">',
  176. output_text,
  177. )
  178. else:
  179. self.assertIn(
  180. '<input class="form-control" id="title" name="title" '
  181. 'type="text" value="New title">',
  182. output_text,
  183. )
  184. self.assertIn(
  185. '<textarea class="form-control width-100per" '
  186. 'id="initial_comment"\n '
  187. 'name="initial_comment">New initial comment</textarea>',
  188. output_text,
  189. )
  190. self.assertIn(
  191. '<input id="allow_rebase" name="allow_rebase" type="checkbox"'
  192. ' value="y" checked>',
  193. output_text,
  194. )
  195. request = pagure.lib.query.search_pull_requests(
  196. self.session, project_id=1, requestid=1
  197. )
  198. # DB model has not been changed
  199. self.assertEqual("PR from the feature branch", request.title)
  200. self.assertEqual(None, request.initial_comment)
  201. self.assertEqual(True, request.allow_rebase)
  202. @patch.dict(
  203. "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True}
  204. )
  205. def test_pr_edit_pull_request_post_author(self):
  206. user = tests.FakeUser(username="foo")
  207. with tests.user_set(self.app.application, user):
  208. data = {
  209. "title": "New title",
  210. "initial_comment": "New initial comment",
  211. "allow_rebase": False,
  212. "branch_to": "master",
  213. "csrf_token": self.get_csrf(),
  214. }
  215. with testing.mock_sends(
  216. pagure_messages.PullRequestInitialCommentEditedV1(
  217. topic="pagure.pull-request.initial_comment.edited",
  218. body={
  219. "pullrequest": {
  220. "id": 1,
  221. "uid": ANY,
  222. "title": "New title",
  223. "full_url": "http://localhost.localdomain/test/pull-request/1",
  224. "branch": "master",
  225. "project": {
  226. "id": 1,
  227. "name": "test",
  228. "fullname": "test",
  229. "url_path": "test",
  230. "full_url": "http://localhost.localdomain/test",
  231. "description": "test project #1",
  232. "namespace": None,
  233. "parent": None,
  234. "date_created": ANY,
  235. "date_modified": ANY,
  236. "user": {
  237. "name": "pingou",
  238. "fullname": "PY C",
  239. "url_path": "user/pingou",
  240. "full_url": "http://localhost.localdomain/user/pingou",
  241. },
  242. "access_users": {
  243. "owner": ["pingou"],
  244. "admin": [],
  245. "commit": [],
  246. "collaborator": [],
  247. "ticket": [],
  248. },
  249. "access_groups": {
  250. "admin": [],
  251. "commit": [],
  252. "collaborator": [],
  253. "ticket": [],
  254. },
  255. "tags": [],
  256. "priorities": {},
  257. "custom_keys": [],
  258. "close_status": [
  259. "Invalid",
  260. "Insufficient data",
  261. "Fixed",
  262. "Duplicate",
  263. ],
  264. "milestones": {},
  265. },
  266. "branch_from": "feature",
  267. "repo_from": {
  268. "id": 4,
  269. "name": "test",
  270. "fullname": "forks/foo/test",
  271. "url_path": "fork/foo/test",
  272. "full_url": "http://localhost.localdomain/fork/foo/test",
  273. "description": "test project #1",
  274. "namespace": None,
  275. "parent": {
  276. "id": 1,
  277. "name": "test",
  278. "fullname": "test",
  279. "url_path": "test",
  280. "description": "test project #1",
  281. "full_url": "http://localhost.localdomain/test",
  282. "namespace": None,
  283. "parent": None,
  284. "date_created": ANY,
  285. "date_modified": ANY,
  286. "user": {
  287. "name": "pingou",
  288. "fullname": "PY C",
  289. "url_path": "user/pingou",
  290. "full_url": "http://localhost.localdomain/user/pingou",
  291. },
  292. "access_users": {
  293. "owner": ["pingou"],
  294. "admin": [],
  295. "commit": [],
  296. "collaborator": [],
  297. "ticket": [],
  298. },
  299. "access_groups": {
  300. "admin": [],
  301. "commit": [],
  302. "collaborator": [],
  303. "ticket": [],
  304. },
  305. "tags": [],
  306. "priorities": {},
  307. "custom_keys": [],
  308. "close_status": [
  309. "Invalid",
  310. "Insufficient data",
  311. "Fixed",
  312. "Duplicate",
  313. ],
  314. "milestones": {},
  315. },
  316. "date_created": ANY,
  317. "date_modified": ANY,
  318. "user": {
  319. "name": "foo",
  320. "fullname": "foo bar",
  321. "full_url": "http://localhost.localdomain/user/foo",
  322. "url_path": "user/foo",
  323. },
  324. "access_users": {
  325. "owner": ["foo"],
  326. "admin": [],
  327. "commit": [],
  328. "collaborator": [],
  329. "ticket": [],
  330. },
  331. "access_groups": {
  332. "admin": [],
  333. "commit": [],
  334. "collaborator": [],
  335. "ticket": [],
  336. },
  337. "tags": [],
  338. "priorities": {},
  339. "custom_keys": [],
  340. "close_status": [],
  341. "milestones": {},
  342. },
  343. "remote_git": None,
  344. "date_created": ANY,
  345. "updated_on": ANY,
  346. "last_updated": ANY,
  347. "closed_at": None,
  348. "user": {
  349. "name": "foo",
  350. "fullname": "foo bar",
  351. "url_path": "user/foo",
  352. "full_url": "http://localhost.localdomain/user/foo",
  353. },
  354. "assignee": None,
  355. "status": "Open",
  356. "commit_start": None,
  357. "commit_stop": None,
  358. "closed_by": None,
  359. "initial_comment": "New initial comment",
  360. "cached_merge_status": "unknown",
  361. "threshold_reached": None,
  362. "tags": [],
  363. "comments": [],
  364. },
  365. "project": {
  366. "id": 1,
  367. "name": "test",
  368. "fullname": "test",
  369. "full_url": "http://localhost.localdomain/test",
  370. "url_path": "test",
  371. "description": "test project #1",
  372. "namespace": None,
  373. "parent": None,
  374. "date_created": ANY,
  375. "date_modified": ANY,
  376. "user": {
  377. "name": "pingou",
  378. "fullname": "PY C",
  379. "url_path": "user/pingou",
  380. "full_url": "http://localhost.localdomain/user/pingou",
  381. },
  382. "access_users": {
  383. "owner": ["pingou"],
  384. "admin": [],
  385. "commit": [],
  386. "collaborator": [],
  387. "ticket": [],
  388. },
  389. "access_groups": {
  390. "admin": [],
  391. "commit": [],
  392. "collaborator": [],
  393. "ticket": [],
  394. },
  395. "tags": [],
  396. "priorities": {},
  397. "custom_keys": [],
  398. "close_status": [
  399. "Invalid",
  400. "Insufficient data",
  401. "Fixed",
  402. "Duplicate",
  403. ],
  404. "milestones": {},
  405. },
  406. "agent": "foo",
  407. },
  408. )
  409. ):
  410. output = self.app.post(
  411. "/test/pull-request/1/edit",
  412. data=data,
  413. follow_redirects=True,
  414. )
  415. self.assertEqual(output.status_code, 200)
  416. output_text = output.get_data(as_text=True)
  417. # After successful edit, we end on pull_request view with new data
  418. self.assertIn(
  419. "<title>PR#1: New title - test\n - Pagure</title>", output_text
  420. )
  421. self.assertIn(
  422. '<span class="font-weight-bold">\n'
  423. " New title\n"
  424. " </span>",
  425. output_text,
  426. )
  427. self.assertIn("<p>New initial comment</p>", output_text)
  428. request = pagure.lib.query.search_pull_requests(
  429. self.session, project_id=1, requestid=1
  430. )
  431. # DB model has been changed
  432. self.assertEqual("New title", request.title)
  433. self.assertEqual("New initial comment", request.initial_comment)
  434. self.assertEqual(False, request.allow_rebase)
  435. def test_pr_edit_pull_request_view_committer(self):
  436. user = tests.FakeUser(username="pingou")
  437. with tests.user_set(self.app.application, user):
  438. output = self.app.get("/test/pull-request/1/edit")
  439. self.assertEqual(output.status_code, 200)
  440. output_text = output.get_data(as_text=True)
  441. # Committer is editing PR #1
  442. self.assertIn(
  443. "<title>Edit PR#1: PR from the feature branch - test - "
  444. "Pagure</title>",
  445. output_text,
  446. )
  447. # Committer has a title input
  448. if self.get_wtforms_version() >= (2, 2):
  449. self.assertIn(
  450. '<input class="form-control" id="title" name="title" '
  451. 'required type="text" value="PR from the feature branch">',
  452. output_text,
  453. )
  454. else:
  455. self.assertIn(
  456. '<input class="form-control" id="title" name="title" '
  457. 'type="text" value="PR from the feature branch">',
  458. output_text,
  459. )
  460. # Committer has an initial_commit textarea
  461. self.assertIn(
  462. '<textarea class="form-control width-100per" '
  463. 'id="initial_comment"\n'
  464. ' name="initial_comment"></textarea>',
  465. output_text,
  466. )
  467. # Committer has an disabled allow_rebase input
  468. self.assertIn(
  469. '<input id="allow_rebase" name="allow_rebase" type="checkbox"'
  470. ' value="y" checked disabled>',
  471. output_text,
  472. )
  473. def test_pr_edit_pull_request_post_committer(self):
  474. user = tests.FakeUser(username="pingou")
  475. with tests.user_set(self.app.application, user):
  476. data = {
  477. "title": "New title",
  478. "initial_comment": "New initial comment",
  479. "allow_rebase": False,
  480. "branch_to": "master",
  481. "csrf_token": self.get_csrf(),
  482. }
  483. output = self.app.post(
  484. "/test/pull-request/1/edit", data=data, follow_redirects=True
  485. )
  486. self.assertEqual(output.status_code, 200)
  487. output_text = output.get_data(as_text=True)
  488. # After successful edit, we end on pull_request view with new data
  489. self.assertIn(
  490. "<title>PR#1: New title - test\n - Pagure</title>", output_text
  491. )
  492. self.assertIn(
  493. '<span class="font-weight-bold">\n'
  494. " New title\n"
  495. " </span>",
  496. output_text,
  497. )
  498. self.assertIn("<p>New initial comment</p>", output_text)
  499. request = pagure.lib.query.search_pull_requests(
  500. self.session, project_id=1, requestid=1
  501. )
  502. # DB model has been changed
  503. self.assertEqual("New title", request.title)
  504. self.assertEqual("New initial comment", request.initial_comment)
  505. # But allow_rebase remains unchanged
  506. self.assertEqual(True, request.allow_rebase)
  507. def test_pr_edit_pull_request_invalid_branch_to(self):
  508. user = tests.FakeUser(username="pingou")
  509. with tests.user_set(self.app.application, user):
  510. data = {
  511. "title": "New title",
  512. "initial_comment": "New initial comment",
  513. "allow_rebase": False,
  514. "branch_to": "invalid",
  515. "csrf_token": self.get_csrf(),
  516. }
  517. output = self.app.post(
  518. "/test/pull-request/1/edit", data=data, follow_redirects=True
  519. )
  520. self.assertEqual(output.status_code, 200)
  521. output_text = output.get_data(as_text=True)
  522. # Edit failed - we're back on the same page
  523. self.assertIn(
  524. "<title>Edit PR#1: PR from the feature branch - test - Pagure"
  525. "</title>",
  526. output_text,
  527. )
  528. self.assertIn("Not a valid choice", output_text)
  529. request = pagure.lib.query.search_pull_requests(
  530. self.session, project_id=1, requestid=1
  531. )
  532. # DB model has not been changed
  533. self.assertEqual("PR from the feature branch", request.title)
  534. self.assertEqual(None, request.initial_comment)
  535. self.assertEqual("master", request.branch)
  536. # But allow_rebase remains unchanged
  537. self.assertEqual(True, request.allow_rebase)
  538. def test_pr_edit_pull_request_valid_branch_to(self):
  539. user = tests.FakeUser(username="pingou")
  540. with tests.user_set(self.app.application, user):
  541. data = {
  542. "title": "New title",
  543. "initial_comment": "New initial comment",
  544. "allow_rebase": False,
  545. "branch_to": "main",
  546. "csrf_token": self.get_csrf(),
  547. }
  548. output = self.app.post(
  549. "/test/pull-request/1/edit", data=data, follow_redirects=True
  550. )
  551. self.assertEqual(output.status_code, 200)
  552. output_text = output.get_data(as_text=True)
  553. # After successful edit, we end on pull_request view with new data
  554. self.assertIn(
  555. "<title>PR#1: New title - test\n - Pagure</title>", output_text
  556. )
  557. self.assertIn(
  558. '<span class="font-weight-bold">\n'
  559. " New title\n"
  560. " </span>",
  561. output_text,
  562. )
  563. self.assertIn("<p>New initial comment</p>", output_text)
  564. request = pagure.lib.query.search_pull_requests(
  565. self.session, project_id=1, requestid=1
  566. )
  567. # DB model has been changed
  568. self.assertEqual("New title", request.title)
  569. self.assertEqual("New initial comment", request.initial_comment)
  570. self.assertEqual("main", request.branch)
  571. # But allow_rebase remains unchanged
  572. self.assertEqual(True, request.allow_rebase)