test_pagure_flask_api_pr_flag.py 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193
  1. # -*- coding: utf-8 -*-
  2. """
  3. (c) 2018 - Copyright Red Hat Inc
  4. Authors:
  5. Pierre-Yves Chibon <pingou@pingoured.fr>
  6. """
  7. from __future__ import unicode_literals, absolute_import
  8. import unittest
  9. import sys
  10. import os
  11. import json
  12. from mock import patch, MagicMock
  13. sys.path.insert(
  14. 0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..")
  15. )
  16. import pagure.config # noqa
  17. import pagure.lib.query # noqa
  18. import tests # noqa
  19. class PagureFlaskApiPRFlagtests(tests.Modeltests):
  20. """ Tests for the flask API of pagure for flagging pull-requests """
  21. maxDiff = None
  22. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  23. def setUp(self):
  24. """ Set up the environnment, ran before every tests. """
  25. super(PagureFlaskApiPRFlagtests, self).setUp()
  26. pagure.config.config["REQUESTS_FOLDER"] = None
  27. tests.create_projects(self.session)
  28. tests.create_tokens(self.session)
  29. tests.create_tokens_acl(self.session)
  30. # Create a pull-request
  31. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  32. forked_repo = pagure.lib.query.get_authorized_project(
  33. self.session, "test"
  34. )
  35. req = pagure.lib.query.new_pull_request(
  36. session=self.session,
  37. repo_from=forked_repo,
  38. branch_from="master",
  39. repo_to=repo,
  40. branch_to="master",
  41. title="test pull-request",
  42. user="pingou",
  43. )
  44. self.session.commit()
  45. self.assertEqual(req.id, 1)
  46. self.assertEqual(req.title, "test pull-request")
  47. # Check flags before
  48. self.session.commit()
  49. request = pagure.lib.query.search_pull_requests(
  50. self.session, project_id=1, requestid=1
  51. )
  52. self.assertEqual(len(request.flags), 0)
  53. def test_invalid_project(self):
  54. """ Test the flagging a PR on an invalid project. """
  55. headers = {"Authorization": "token aaabbbcccddd"}
  56. # Invalid project
  57. output = self.app.post(
  58. "/api/0/foo/pull-request/1/flag", headers=headers
  59. )
  60. self.assertEqual(output.status_code, 404)
  61. data = json.loads(output.get_data(as_text=True))
  62. self.assertDictEqual(
  63. data, {"error": "Project not found", "error_code": "ENOPROJECT"}
  64. )
  65. def test_incorrect_project(self):
  66. """ Test the flagging a PR on the wrong project. """
  67. headers = {"Authorization": "token aaabbbcccddd"}
  68. # Valid token, wrong project
  69. output = self.app.post(
  70. "/api/0/test2/pull-request/1/flag", headers=headers
  71. )
  72. self.assertEqual(output.status_code, 401)
  73. data = json.loads(output.get_data(as_text=True))
  74. self.assertEqual(
  75. pagure.api.APIERROR.EINVALIDTOK.name, data["error_code"]
  76. )
  77. self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.value, data["error"])
  78. def test_pr_disabled(self):
  79. """ Test the flagging a PR when PRs are disabled. """
  80. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  81. settings = repo.settings
  82. settings["pull_requests"] = False
  83. repo.settings = settings
  84. self.session.add(repo)
  85. self.session.commit()
  86. headers = {"Authorization": "token aaabbbcccddd"}
  87. # PRs disabled
  88. output = self.app.post(
  89. "/api/0/test/pull-request/1/flag", headers=headers
  90. )
  91. self.assertEqual(output.status_code, 404)
  92. data = json.loads(output.get_data(as_text=True))
  93. self.assertDictEqual(
  94. data,
  95. {
  96. "error": "Pull-Request have been deactivated for this project",
  97. "error_code": "EPULLREQUESTSDISABLED",
  98. },
  99. )
  100. def test_no_pr(self):
  101. """ Test the flagging a PR when the PR doesn't exist. """
  102. headers = {"Authorization": "token aaabbbcccddd"}
  103. # No PR
  104. output = self.app.post(
  105. "/api/0/test/pull-request/10/flag", headers=headers
  106. )
  107. self.assertEqual(output.status_code, 404)
  108. data = json.loads(output.get_data(as_text=True))
  109. self.assertDictEqual(
  110. data, {"error": "Pull-Request not found", "error_code": "ENOREQ"}
  111. )
  112. def test_no_input(self):
  113. """ Test the flagging an existing PR but with no data. """
  114. headers = {"Authorization": "token aaabbbcccddd"}
  115. # No input
  116. output = self.app.post(
  117. "/api/0/test/pull-request/1/flag", headers=headers
  118. )
  119. self.assertEqual(output.status_code, 400)
  120. data = json.loads(output.get_data(as_text=True))
  121. self.assertDictEqual(
  122. data,
  123. {
  124. "error": "Invalid or incomplete input submitted",
  125. "error_code": "EINVALIDREQ",
  126. "errors": {
  127. "comment": ["This field is required."],
  128. "url": ["This field is required."],
  129. "username": ["This field is required."],
  130. },
  131. },
  132. )
  133. def test_no_comment(self):
  134. """ Test the flagging an existing PR but with incomplete data. """
  135. headers = {"Authorization": "token aaabbbcccddd"}
  136. data = {
  137. "username": "Jenkins",
  138. "percent": 100,
  139. "url": "http://jenkins.cloud.fedoraproject.org/",
  140. "uid": "jenkins_build_pagure_100+seed",
  141. }
  142. # Incomplete request
  143. output = self.app.post(
  144. "/api/0/test/pull-request/1/flag", data=data, headers=headers
  145. )
  146. self.assertEqual(output.status_code, 400)
  147. data = json.loads(output.get_data(as_text=True))
  148. self.assertDictEqual(
  149. data,
  150. {
  151. "error": "Invalid or incomplete input submitted",
  152. "error_code": "EINVALIDREQ",
  153. "errors": {"comment": ["This field is required."]},
  154. },
  155. )
  156. # No change
  157. self.session.commit()
  158. request = pagure.lib.query.search_pull_requests(
  159. self.session, project_id=1, requestid=1
  160. )
  161. self.assertEqual(len(request.flags), 0)
  162. @patch(
  163. "pagure.lib.query.add_pull_request_flag",
  164. MagicMock(side_effect=pagure.exceptions.PagureException("error")),
  165. )
  166. def test_raise_exception(self):
  167. """ Test the flagging a PR when adding a flag raises an exception. """
  168. headers = {"Authorization": "token aaabbbcccddd"}
  169. data = {
  170. "username": "Jenkins",
  171. "comment": "Tests running",
  172. "url": "http://jenkins.cloud.fedoraproject.org/",
  173. "uid": "jenkins_build_pagure_100+seed",
  174. }
  175. # Adding a flag raises an exception
  176. output = self.app.post(
  177. "/api/0/test/pull-request/1/flag", headers=headers, data=data
  178. )
  179. self.assertEqual(output.status_code, 400)
  180. data = json.loads(output.get_data(as_text=True))
  181. self.assertDictEqual(data, {"error": "error", "error_code": "ENOCODE"})
  182. @patch("pagure.lib.notify.send_email")
  183. def test_flagging_a_pul_request_with_notification(self, mock_email):
  184. """ Test the flagging a PR. """
  185. headers = {"Authorization": "token aaabbbcccddd"}
  186. # Enable PR notifications
  187. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  188. settings = repo.settings
  189. settings["notify_on_pull-request_flag"] = True
  190. repo.settings = settings
  191. self.session.add(repo)
  192. self.session.commit()
  193. data = {
  194. "username": "Jenkins",
  195. "comment": "Tests running",
  196. "url": "http://jenkins.cloud.fedoraproject.org/",
  197. "uid": "jenkins_build_pagure_100+seed",
  198. }
  199. # Valid request
  200. output = self.app.post(
  201. "/api/0/test/pull-request/1/flag", data=data, headers=headers
  202. )
  203. self.assertEqual(output.status_code, 200)
  204. data = json.loads(output.get_data(as_text=True))
  205. data["flag"]["date_created"] = "1510742565"
  206. data["flag"]["date_updated"] = "1510742565"
  207. pr_uid = data["flag"]["pull_request_uid"]
  208. data["flag"]["pull_request_uid"] = "62b49f00d489452994de5010565fab81"
  209. data["avatar_url"] = "https://seccdn.libravatar.org/avatar/..."
  210. self.assertDictEqual(
  211. data,
  212. {
  213. "flag": {
  214. "comment": "Tests running",
  215. "date_created": "1510742565",
  216. "date_updated": "1510742565",
  217. "percent": None,
  218. "pull_request_uid": "62b49f00d489452994de5010565fab81",
  219. "status": "pending",
  220. "url": "http://jenkins.cloud.fedoraproject.org/",
  221. "user": {
  222. "default_email": "bar@pingou.com",
  223. "emails": ["bar@pingou.com", "foo@pingou.com"],
  224. "fullname": "PY C",
  225. "name": "pingou",
  226. "url_path": "user/pingou",
  227. },
  228. "username": "Jenkins",
  229. },
  230. "message": "Flag added",
  231. "uid": "jenkins_build_pagure_100+seed",
  232. "avatar_url": "https://seccdn.libravatar.org/avatar/...",
  233. "user": "pingou",
  234. },
  235. )
  236. # One flag added
  237. self.session.commit()
  238. request = pagure.lib.query.search_pull_requests(
  239. self.session, project_id=1, requestid=1
  240. )
  241. self.assertEqual(len(request.flags), 1)
  242. self.assertEqual(request.flags[0].comment, "Tests running")
  243. self.assertEqual(request.flags[0].percent, None)
  244. # Check the notification sent
  245. mock_email.assert_called_once_with(
  246. "\nJenkins flagged the pull-request `test pull-request` "
  247. "as pending: Tests running\n\n"
  248. "http://localhost.localdomain/test/pull-request/1\n",
  249. "PR #1 - Jenkins: pending",
  250. "bar@pingou.com",
  251. assignee=None,
  252. in_reply_to="test-pull-request-" + pr_uid,
  253. mail_id="test-pull-request-" + pr_uid + "-1",
  254. project_name="test",
  255. reporter="pingou",
  256. user_from="Jenkins",
  257. )
  258. def test_updating_flag(self):
  259. """ Test the updating the flag of a PR. """
  260. headers = {"Authorization": "token aaabbbcccddd"}
  261. data = {
  262. "username": "Jenkins",
  263. "comment": "Tests running",
  264. "url": "http://jenkins.cloud.fedoraproject.org/",
  265. "uid": "jenkins_build_pagure_100+seed",
  266. }
  267. # Valid request
  268. output = self.app.post(
  269. "/api/0/test/pull-request/1/flag", data=data, headers=headers
  270. )
  271. self.assertEqual(output.status_code, 200)
  272. data = json.loads(output.get_data(as_text=True))
  273. data["flag"]["date_created"] = "1510742565"
  274. data["flag"]["date_updated"] = "1510742565"
  275. data["flag"]["pull_request_uid"] = "62b49f00d489452994de5010565fab81"
  276. data["avatar_url"] = "https://seccdn.libravatar.org/avatar/..."
  277. self.assertDictEqual(
  278. data,
  279. {
  280. "flag": {
  281. "comment": "Tests running",
  282. "date_created": "1510742565",
  283. "date_updated": "1510742565",
  284. "percent": None,
  285. "pull_request_uid": "62b49f00d489452994de5010565fab81",
  286. "status": "pending",
  287. "url": "http://jenkins.cloud.fedoraproject.org/",
  288. "user": {
  289. "default_email": "bar@pingou.com",
  290. "emails": ["bar@pingou.com", "foo@pingou.com"],
  291. "fullname": "PY C",
  292. "name": "pingou",
  293. "url_path": "user/pingou",
  294. },
  295. "username": "Jenkins",
  296. },
  297. "message": "Flag added",
  298. "uid": "jenkins_build_pagure_100+seed",
  299. "avatar_url": "https://seccdn.libravatar.org/avatar/...",
  300. "user": "pingou",
  301. },
  302. )
  303. # One flag added
  304. self.session.commit()
  305. request = pagure.lib.query.search_pull_requests(
  306. self.session, project_id=1, requestid=1
  307. )
  308. self.assertEqual(len(request.flags), 1)
  309. self.assertEqual(request.flags[0].comment, "Tests running")
  310. self.assertEqual(request.flags[0].percent, None)
  311. # Update flag - w/o providing the status
  312. data = {
  313. "username": "Jenkins",
  314. "percent": 100,
  315. "comment": "Tests passed",
  316. "url": "http://jenkins.cloud.fedoraproject.org/",
  317. "uid": "jenkins_build_pagure_100+seed",
  318. }
  319. output = self.app.post(
  320. "/api/0/test/pull-request/1/flag", data=data, headers=headers
  321. )
  322. self.assertEqual(output.status_code, 200)
  323. data = json.loads(output.get_data(as_text=True))
  324. data["flag"]["date_created"] = "1510742565"
  325. data["flag"]["date_updated"] = "1510742565"
  326. data["flag"]["pull_request_uid"] = "62b49f00d489452994de5010565fab81"
  327. data["avatar_url"] = "https://seccdn.libravatar.org/avatar/..."
  328. self.assertDictEqual(
  329. data,
  330. {
  331. "flag": {
  332. "comment": "Tests passed",
  333. "date_created": "1510742565",
  334. "date_updated": "1510742565",
  335. "percent": 100,
  336. "pull_request_uid": "62b49f00d489452994de5010565fab81",
  337. "status": "success",
  338. "url": "http://jenkins.cloud.fedoraproject.org/",
  339. "user": {
  340. "default_email": "bar@pingou.com",
  341. "emails": ["bar@pingou.com", "foo@pingou.com"],
  342. "fullname": "PY C",
  343. "name": "pingou",
  344. "url_path": "user/pingou",
  345. },
  346. "username": "Jenkins",
  347. },
  348. "message": "Flag updated",
  349. "uid": "jenkins_build_pagure_100+seed",
  350. "avatar_url": "https://seccdn.libravatar.org/avatar/...",
  351. "user": "pingou",
  352. },
  353. )
  354. # One flag added
  355. self.session.commit()
  356. request = pagure.lib.query.search_pull_requests(
  357. self.session, project_id=1, requestid=1
  358. )
  359. self.assertEqual(len(request.flags), 1)
  360. self.assertEqual(request.flags[0].comment, "Tests passed")
  361. self.assertEqual(request.flags[0].percent, 100)
  362. def test_adding_two_flags(self):
  363. """ Test the adding two flags to a PR. """
  364. headers = {"Authorization": "token aaabbbcccddd"}
  365. data = {
  366. "username": "Jenkins",
  367. "comment": "Tests passed",
  368. "status": "success",
  369. "percent": "100",
  370. "url": "http://jenkins.cloud.fedoraproject.org/",
  371. "uid": "jenkins_build_pagure_100+seed",
  372. }
  373. # Valid request
  374. output = self.app.post(
  375. "/api/0/test/pull-request/1/flag", data=data, headers=headers
  376. )
  377. self.assertEqual(output.status_code, 200)
  378. data = json.loads(output.get_data(as_text=True))
  379. data["flag"]["date_created"] = "1510742565"
  380. data["flag"]["date_updated"] = "1510742565"
  381. data["flag"]["pull_request_uid"] = "62b49f00d489452994de5010565fab81"
  382. data["avatar_url"] = "https://seccdn.libravatar.org/avatar/..."
  383. self.assertDictEqual(
  384. data,
  385. {
  386. "flag": {
  387. "comment": "Tests passed",
  388. "date_created": "1510742565",
  389. "date_updated": "1510742565",
  390. "percent": 100,
  391. "pull_request_uid": "62b49f00d489452994de5010565fab81",
  392. "status": "success",
  393. "url": "http://jenkins.cloud.fedoraproject.org/",
  394. "user": {
  395. "default_email": "bar@pingou.com",
  396. "emails": ["bar@pingou.com", "foo@pingou.com"],
  397. "fullname": "PY C",
  398. "name": "pingou",
  399. "url_path": "user/pingou",
  400. },
  401. "username": "Jenkins",
  402. },
  403. "message": "Flag added",
  404. "uid": "jenkins_build_pagure_100+seed",
  405. "avatar_url": "https://seccdn.libravatar.org/avatar/...",
  406. "user": "pingou",
  407. },
  408. )
  409. # One flag added
  410. self.session.commit()
  411. request = pagure.lib.query.search_pull_requests(
  412. self.session, project_id=1, requestid=1
  413. )
  414. self.assertEqual(len(request.flags), 1)
  415. self.assertEqual(request.flags[0].comment, "Tests passed")
  416. self.assertEqual(request.flags[0].percent, 100)
  417. data = {
  418. "username": "Jenkins",
  419. "comment": "Tests running again",
  420. "url": "http://jenkins.cloud.fedoraproject.org/",
  421. }
  422. # Valid request
  423. output = self.app.post(
  424. "/api/0/test/pull-request/1/flag", data=data, headers=headers
  425. )
  426. self.assertEqual(output.status_code, 200)
  427. data = json.loads(output.get_data(as_text=True))
  428. data["flag"]["date_created"] = "1510742565"
  429. data["flag"]["date_updated"] = "1510742565"
  430. data["flag"]["pull_request_uid"] = "62b49f00d489452994de5010565fab81"
  431. self.assertNotEqual(data["uid"], "jenkins_build_pagure_100+seed")
  432. data["uid"] = "jenkins_build_pagure_100+seed"
  433. data["avatar_url"] = "https://seccdn.libravatar.org/avatar/..."
  434. self.assertDictEqual(
  435. data,
  436. {
  437. "flag": {
  438. "comment": "Tests running again",
  439. "date_created": "1510742565",
  440. "date_updated": "1510742565",
  441. "percent": None,
  442. "pull_request_uid": "62b49f00d489452994de5010565fab81",
  443. "status": "pending",
  444. "url": "http://jenkins.cloud.fedoraproject.org/",
  445. "user": {
  446. "default_email": "bar@pingou.com",
  447. "emails": ["bar@pingou.com", "foo@pingou.com"],
  448. "fullname": "PY C",
  449. "name": "pingou",
  450. "url_path": "user/pingou",
  451. },
  452. "username": "Jenkins",
  453. },
  454. "message": "Flag added",
  455. "uid": "jenkins_build_pagure_100+seed",
  456. "avatar_url": "https://seccdn.libravatar.org/avatar/...",
  457. "user": "pingou",
  458. },
  459. )
  460. # Two flag added
  461. self.session.commit()
  462. request = pagure.lib.query.search_pull_requests(
  463. self.session, project_id=1, requestid=1
  464. )
  465. self.assertEqual(len(request.flags), 2)
  466. self.assertEqual(request.flags[0].comment, "Tests running again")
  467. self.assertEqual(request.flags[0].percent, None)
  468. self.assertEqual(request.flags[1].comment, "Tests passed")
  469. self.assertEqual(request.flags[1].percent, 100)
  470. @patch.dict(
  471. "pagure.config.config",
  472. {
  473. "FLAG_STATUSES_LABELS": {
  474. "pend!": "label-info",
  475. "succeed!": "label-success",
  476. "fail!": "label-danger",
  477. "what?": "label-warning",
  478. },
  479. "FLAG_PENDING": "pend!",
  480. "FLAG_SUCCESS": "succeed!",
  481. "FLAG_FAILURE": "fail!",
  482. },
  483. )
  484. def test_flagging_a_pull_request_while_having_custom_statuses(self):
  485. """ Test flagging a PR while having custom statuses. """
  486. headers = {"Authorization": "token aaabbbcccddd"}
  487. # No status and no percent => should use FLAG_PENDING
  488. send_data = {
  489. "username": "Jenkins",
  490. "comment": "Tests running",
  491. "url": "http://jenkins.cloud.fedoraproject.org/",
  492. "uid": "jenkins_build_pagure_100+seed",
  493. }
  494. output = self.app.post(
  495. "/api/0/test/pull-request/1/flag", data=send_data, headers=headers
  496. )
  497. data = json.loads(output.get_data(as_text=True))
  498. self.assertEqual(output.status_code, 200)
  499. self.assertEqual(data["flag"]["status"], "pend!")
  500. # No status and 50 % => should use FLAG_SUCCESS
  501. send_data["percent"] = 50
  502. output = self.app.post(
  503. "/api/0/test/pull-request/1/flag", data=send_data, headers=headers
  504. )
  505. data = json.loads(output.get_data(as_text=True))
  506. self.assertEqual(output.status_code, 200)
  507. self.assertEqual(data["flag"]["status"], "succeed!")
  508. # No status and 0 % => should use FLAG_FAILURE
  509. send_data["percent"] = 0
  510. output = self.app.post(
  511. "/api/0/test/pull-request/1/flag", data=send_data, headers=headers
  512. )
  513. data = json.loads(output.get_data(as_text=True))
  514. self.assertEqual(output.status_code, 200)
  515. self.assertEqual(data["flag"]["status"], "fail!")
  516. # Explicitly set status
  517. send_data["status"] = "what?"
  518. output = self.app.post(
  519. "/api/0/test/pull-request/1/flag", data=send_data, headers=headers
  520. )
  521. data = json.loads(output.get_data(as_text=True))
  522. self.assertEqual(output.status_code, 200)
  523. self.assertEqual(data["flag"]["status"], "what?")
  524. # Explicitly set wrong status
  525. send_data["status"] = "nooo....."
  526. output = self.app.post(
  527. "/api/0/test/pull-request/1/flag", data=send_data, headers=headers
  528. )
  529. data = json.loads(output.get_data(as_text=True))
  530. self.assertEqual(output.status_code, 400)
  531. self.assertDictEqual(
  532. data,
  533. {
  534. "error": "Invalid or incomplete input submitted",
  535. "error_code": "EINVALIDREQ",
  536. "errors": {"status": ["Not a valid choice"]},
  537. },
  538. )
  539. class PagureFlaskApiPRFlagUserTokentests(tests.Modeltests):
  540. """ Tests for the flask API of pagure for flagging pull-requests using
  541. an user token (ie: not restricted to a specific project).
  542. """
  543. maxDiff = None
  544. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  545. def setUp(self):
  546. """ Set up the environnment, ran before every tests. """
  547. super(PagureFlaskApiPRFlagUserTokentests, self).setUp()
  548. pagure.config.config["REQUESTS_FOLDER"] = None
  549. tests.create_projects(self.session)
  550. tests.create_tokens(self.session, project_id=None)
  551. tests.create_tokens_acl(self.session)
  552. # Create a pull-request
  553. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  554. forked_repo = pagure.lib.query.get_authorized_project(
  555. self.session, "test"
  556. )
  557. req = pagure.lib.query.new_pull_request(
  558. session=self.session,
  559. repo_from=forked_repo,
  560. branch_from="master",
  561. repo_to=repo,
  562. branch_to="master",
  563. title="test pull-request",
  564. user="pingou",
  565. )
  566. self.session.commit()
  567. self.assertEqual(req.id, 1)
  568. self.assertEqual(req.title, "test pull-request")
  569. # Check flags before
  570. self.session.commit()
  571. request = pagure.lib.query.search_pull_requests(
  572. self.session, project_id=1, requestid=1
  573. )
  574. self.assertEqual(len(request.flags), 0)
  575. def test_no_pr(self):
  576. """ Test flagging a non-existing PR. """
  577. headers = {"Authorization": "token aaabbbcccddd"}
  578. # Invalid project
  579. output = self.app.post(
  580. "/api/0/foo/pull-request/1/flag", headers=headers
  581. )
  582. self.assertEqual(output.status_code, 404)
  583. data = json.loads(output.get_data(as_text=True))
  584. self.assertDictEqual(
  585. data, {"error": "Project not found", "error_code": "ENOPROJECT"}
  586. )
  587. def test_no_pr_other_project(self):
  588. """ Test flagging a non-existing PR on a different project. """
  589. headers = {"Authorization": "token aaabbbcccddd"}
  590. # Valid token, wrong project
  591. output = self.app.post(
  592. "/api/0/test2/pull-request/1/flag", headers=headers
  593. )
  594. self.assertEqual(output.status_code, 404)
  595. data = json.loads(output.get_data(as_text=True))
  596. self.assertDictEqual(
  597. data, {"error": "Pull-Request not found", "error_code": "ENOREQ"}
  598. )
  599. def test_no_input(self):
  600. """ Test flagging an existing PR but without submitting any data. """
  601. headers = {"Authorization": "token aaabbbcccddd"}
  602. # No input
  603. output = self.app.post(
  604. "/api/0/test/pull-request/1/flag", headers=headers
  605. )
  606. self.assertEqual(output.status_code, 400)
  607. data = json.loads(output.get_data(as_text=True))
  608. self.assertDictEqual(
  609. data,
  610. {
  611. "error": "Invalid or incomplete input submitted",
  612. "error_code": "EINVALIDREQ",
  613. "errors": {
  614. "comment": ["This field is required."],
  615. "url": ["This field is required."],
  616. "username": ["This field is required."],
  617. },
  618. },
  619. )
  620. def test_no_comment(self):
  621. """ Test flagging an existing PR but without all the required info.
  622. """
  623. headers = {"Authorization": "token aaabbbcccddd"}
  624. data = {
  625. "username": "Jenkins",
  626. "percent": 100,
  627. "url": "http://jenkins.cloud.fedoraproject.org/",
  628. "uid": "jenkins_build_pagure_100+seed",
  629. }
  630. # Incomplete request
  631. output = self.app.post(
  632. "/api/0/test/pull-request/1/flag", data=data, headers=headers
  633. )
  634. self.assertEqual(output.status_code, 400)
  635. data = json.loads(output.get_data(as_text=True))
  636. self.assertDictEqual(
  637. data,
  638. {
  639. "error": "Invalid or incomplete input submitted",
  640. "error_code": "EINVALIDREQ",
  641. "errors": {"comment": ["This field is required."]},
  642. },
  643. )
  644. # No change
  645. self.session.commit()
  646. request = pagure.lib.query.search_pull_requests(
  647. self.session, project_id=1, requestid=1
  648. )
  649. self.assertEqual(len(request.flags), 0)
  650. def test_invalid_status(self):
  651. """ Test flagging an existing PR but with an invalid status.
  652. """
  653. headers = {"Authorization": "token aaabbbcccddd"}
  654. data = {
  655. "username": "Jenkins",
  656. "status": "failed",
  657. "comment": "Failed to run the tests",
  658. "url": "http://jenkins.cloud.fedoraproject.org/",
  659. "uid": "jenkins_build_pagure_100+seed",
  660. }
  661. # Invalid status submitted
  662. output = self.app.post(
  663. "/api/0/test/pull-request/1/flag", data=data, headers=headers
  664. )
  665. self.assertEqual(output.status_code, 400)
  666. data = json.loads(output.get_data(as_text=True))
  667. self.assertDictEqual(
  668. data,
  669. {
  670. "error": "Invalid or incomplete input submitted",
  671. "error_code": "EINVALIDREQ",
  672. "errors": {"status": ["Not a valid choice"]},
  673. },
  674. )
  675. # No change
  676. self.session.commit()
  677. request = pagure.lib.query.search_pull_requests(
  678. self.session, project_id=1, requestid=1
  679. )
  680. self.assertEqual(len(request.flags), 0)
  681. @patch("pagure.lib.notify.send_email")
  682. def test_flag_pr_no_status(self, mock_email):
  683. """ Test flagging an existing PR without providing a status.
  684. Also check that no notifications have been sent.
  685. """
  686. headers = {"Authorization": "token aaabbbcccddd"}
  687. data = {
  688. "username": "Jenkins",
  689. "percent": 0,
  690. "comment": "Tests failed",
  691. "url": "http://jenkins.cloud.fedoraproject.org/",
  692. "uid": "jenkins_build_pagure_100+seed",
  693. }
  694. # Valid request - w/o providing the status
  695. output = self.app.post(
  696. "/api/0/test/pull-request/1/flag", data=data, headers=headers
  697. )
  698. self.assertEqual(output.status_code, 200)
  699. data = json.loads(output.get_data(as_text=True))
  700. data["flag"]["date_created"] = "1510742565"
  701. data["flag"]["date_updated"] = "1510742565"
  702. data["flag"]["pull_request_uid"] = "62b49f00d489452994de5010565fab81"
  703. data["avatar_url"] = "https://seccdn.libravatar.org/avatar/..."
  704. self.assertDictEqual(
  705. data,
  706. {
  707. "flag": {
  708. "comment": "Tests failed",
  709. "date_created": "1510742565",
  710. "date_updated": "1510742565",
  711. "percent": 0,
  712. "pull_request_uid": "62b49f00d489452994de5010565fab81",
  713. "status": "failure",
  714. "url": "http://jenkins.cloud.fedoraproject.org/",
  715. "user": {
  716. "default_email": "bar@pingou.com",
  717. "emails": ["bar@pingou.com", "foo@pingou.com"],
  718. "fullname": "PY C",
  719. "name": "pingou",
  720. "url_path": "user/pingou",
  721. },
  722. "username": "Jenkins",
  723. },
  724. "message": "Flag added",
  725. "uid": "jenkins_build_pagure_100+seed",
  726. "avatar_url": "https://seccdn.libravatar.org/avatar/...",
  727. "user": "pingou",
  728. },
  729. )
  730. # One flag added
  731. self.session.commit()
  732. request = pagure.lib.query.search_pull_requests(
  733. self.session, project_id=1, requestid=1
  734. )
  735. self.assertEqual(len(request.flags), 1)
  736. self.assertEqual(request.flags[0].comment, "Tests failed")
  737. self.assertEqual(request.flags[0].percent, 0)
  738. # no notifications sent
  739. mock_email.assert_not_called()
  740. def test_editing_flag(self):
  741. """ Test flagging an existing PR without providing a status.
  742. """
  743. headers = {"Authorization": "token aaabbbcccddd"}
  744. data = {
  745. "username": "Jenkins",
  746. "status": "failure",
  747. "comment": "Tests failed",
  748. "url": "http://jenkins.cloud.fedoraproject.org/",
  749. "uid": "jenkins_build_pagure_100+seed",
  750. }
  751. # Valid request - w/o providing the status
  752. output = self.app.post(
  753. "/api/0/test/pull-request/1/flag", data=data, headers=headers
  754. )
  755. self.assertEqual(output.status_code, 200)
  756. data = json.loads(output.get_data(as_text=True))
  757. data["flag"]["date_created"] = "1510742565"
  758. data["flag"]["date_updated"] = "1510742565"
  759. data["flag"]["pull_request_uid"] = "62b49f00d489452994de5010565fab81"
  760. data["avatar_url"] = "https://seccdn.libravatar.org/avatar/..."
  761. self.assertDictEqual(
  762. data,
  763. {
  764. "flag": {
  765. "comment": "Tests failed",
  766. "date_created": "1510742565",
  767. "date_updated": "1510742565",
  768. "percent": None,
  769. "pull_request_uid": "62b49f00d489452994de5010565fab81",
  770. "status": "failure",
  771. "url": "http://jenkins.cloud.fedoraproject.org/",
  772. "user": {
  773. "default_email": "bar@pingou.com",
  774. "emails": ["bar@pingou.com", "foo@pingou.com"],
  775. "fullname": "PY C",
  776. "name": "pingou",
  777. "url_path": "user/pingou",
  778. },
  779. "username": "Jenkins",
  780. },
  781. "message": "Flag added",
  782. "uid": "jenkins_build_pagure_100+seed",
  783. "avatar_url": "https://seccdn.libravatar.org/avatar/...",
  784. "user": "pingou",
  785. },
  786. )
  787. # One flag added
  788. self.session.commit()
  789. request = pagure.lib.query.search_pull_requests(
  790. self.session, project_id=1, requestid=1
  791. )
  792. self.assertEqual(len(request.flags), 1)
  793. self.assertEqual(request.flags[0].comment, "Tests failed")
  794. self.assertEqual(request.flags[0].percent, None)
  795. # Update flag
  796. data = {
  797. "username": "Jenkins",
  798. "percent": 100,
  799. "comment": "Tests passed",
  800. "url": "http://jenkins.cloud.fedoraproject.org/",
  801. "uid": "jenkins_build_pagure_100+seed",
  802. "status": "success",
  803. }
  804. output = self.app.post(
  805. "/api/0/test/pull-request/1/flag", data=data, headers=headers
  806. )
  807. self.assertEqual(output.status_code, 200)
  808. data = json.loads(output.get_data(as_text=True))
  809. data["flag"]["date_created"] = "1510742565"
  810. data["flag"]["date_updated"] = "1510742565"
  811. data["flag"]["pull_request_uid"] = "62b49f00d489452994de5010565fab81"
  812. data["avatar_url"] = "https://seccdn.libravatar.org/avatar/..."
  813. self.assertDictEqual(
  814. data,
  815. {
  816. "flag": {
  817. "comment": "Tests passed",
  818. "date_created": "1510742565",
  819. "date_updated": "1510742565",
  820. "percent": 100,
  821. "pull_request_uid": "62b49f00d489452994de5010565fab81",
  822. "status": "success",
  823. "url": "http://jenkins.cloud.fedoraproject.org/",
  824. "user": {
  825. "default_email": "bar@pingou.com",
  826. "emails": ["bar@pingou.com", "foo@pingou.com"],
  827. "fullname": "PY C",
  828. "name": "pingou",
  829. "url_path": "user/pingou",
  830. },
  831. "username": "Jenkins",
  832. },
  833. "message": "Flag updated",
  834. "uid": "jenkins_build_pagure_100+seed",
  835. "avatar_url": "https://seccdn.libravatar.org/avatar/...",
  836. "user": "pingou",
  837. },
  838. )
  839. # Still only one flag
  840. self.session.commit()
  841. request = pagure.lib.query.search_pull_requests(
  842. self.session, project_id=1, requestid=1
  843. )
  844. self.assertEqual(len(request.flags), 1)
  845. self.assertEqual(request.flags[0].comment, "Tests passed")
  846. self.assertEqual(request.flags[0].percent, 100)
  847. class PagureFlaskApiGetPRFlagtests(tests.Modeltests):
  848. """ Tests for the flask API of pagure for retrieving pull-requests flags
  849. """
  850. maxDiff = None
  851. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  852. def setUp(self):
  853. """ Set up the environnment, ran before every tests. """
  854. super(PagureFlaskApiGetPRFlagtests, self).setUp()
  855. pagure.config.config["REQUESTS_FOLDER"] = None
  856. tests.create_projects(self.session)
  857. tests.create_tokens(self.session)
  858. tests.create_tokens_acl(self.session)
  859. # Create a pull-request
  860. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  861. forked_repo = pagure.lib.query.get_authorized_project(
  862. self.session, "test"
  863. )
  864. req = pagure.lib.query.new_pull_request(
  865. session=self.session,
  866. repo_from=forked_repo,
  867. branch_from="master",
  868. repo_to=repo,
  869. branch_to="master",
  870. title="test pull-request",
  871. user="pingou",
  872. )
  873. self.session.commit()
  874. self.assertEqual(req.id, 1)
  875. self.assertEqual(req.title, "test pull-request")
  876. # Check flags before
  877. self.session.commit()
  878. request = pagure.lib.query.search_pull_requests(
  879. self.session, project_id=1, requestid=1
  880. )
  881. self.assertEqual(len(request.flags), 0)
  882. def test_invalid_project(self):
  883. """ Test the retrieving the flags of a PR on an invalid project. """
  884. # Invalid project
  885. output = self.app.get("/api/0/foo/pull-request/1/flag")
  886. self.assertEqual(output.status_code, 404)
  887. data = json.loads(output.get_data(as_text=True))
  888. self.assertDictEqual(
  889. data, {"error": "Project not found", "error_code": "ENOPROJECT"}
  890. )
  891. def test_pr_disabled(self):
  892. """ Test the retrieving the flags of a PR when PRs are disabled. """
  893. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  894. settings = repo.settings
  895. settings["pull_requests"] = False
  896. repo.settings = settings
  897. self.session.add(repo)
  898. self.session.commit()
  899. # PRs disabled
  900. output = self.app.get("/api/0/test/pull-request/1/flag")
  901. self.assertEqual(output.status_code, 404)
  902. data = json.loads(output.get_data(as_text=True))
  903. self.assertDictEqual(
  904. data,
  905. {
  906. "error": "Pull-Request have been deactivated for this project",
  907. "error_code": "EPULLREQUESTSDISABLED",
  908. },
  909. )
  910. def test_no_pr(self):
  911. """ Test the retrieving the flags of a PR when the PR doesn't exist. """
  912. # No PR
  913. output = self.app.get("/api/0/test/pull-request/10/flag")
  914. self.assertEqual(output.status_code, 404)
  915. data = json.loads(output.get_data(as_text=True))
  916. self.assertDictEqual(
  917. data, {"error": "Pull-Request not found", "error_code": "ENOREQ"}
  918. )
  919. def test_no_flag(self):
  920. """ Test the retrieving the flags of a PR when the PR has no flags. """
  921. # No flag
  922. output = self.app.get("/api/0/test/pull-request/1/flag")
  923. self.assertEqual(output.status_code, 200)
  924. data = json.loads(output.get_data(as_text=True))
  925. self.assertDictEqual(data, {"flags": []})
  926. def test_get_flag(self):
  927. """ Test the retrieving the flags of a PR when the PR has one flag. """
  928. # Add a flag to the PR
  929. request = pagure.lib.query.search_pull_requests(
  930. self.session, project_id=1, requestid=1
  931. )
  932. msg = pagure.lib.query.add_pull_request_flag(
  933. session=self.session,
  934. request=request,
  935. username="jenkins",
  936. percent=None,
  937. comment="Build passes",
  938. status="success",
  939. url="http://jenkins.cloud.fedoraproject.org",
  940. uid="jenkins_build_pagure_34",
  941. user="foo",
  942. token="aaabbbcccddd",
  943. )
  944. self.assertEqual(msg, ("Flag added", "jenkins_build_pagure_34"))
  945. self.session.commit()
  946. self.assertEqual(len(request.flags), 1)
  947. self.assertEqual(request.flags[0].token_id, "aaabbbcccddd")
  948. # 1 flag
  949. output = self.app.get("/api/0/test/pull-request/1/flag")
  950. self.assertEqual(output.status_code, 200)
  951. data = json.loads(output.get_data(as_text=True))
  952. data["flags"][0]["date_created"] = "1541413645"
  953. data["flags"][0]["date_updated"] = "1541413645"
  954. data["flags"][0][
  955. "pull_request_uid"
  956. ] = "72a61033c2fc464aa9ef514c057aa62c"
  957. self.assertDictEqual(
  958. data,
  959. {
  960. "flags": [
  961. {
  962. "comment": "Build passes",
  963. "date_created": "1541413645",
  964. "date_updated": "1541413645",
  965. "percent": None,
  966. "pull_request_uid": "72a61033c2fc464aa9ef514c057aa62c",
  967. "status": "success",
  968. "url": "http://jenkins.cloud.fedoraproject.org",
  969. "user": {
  970. "fullname": "foo bar",
  971. "name": "foo",
  972. "url_path": "user/foo",
  973. },
  974. "username": "jenkins",
  975. }
  976. ]
  977. },
  978. )
  979. def test_get_flags(self):
  980. """ Test the retrieving the flags of a PR when the PR has one flag. """
  981. # Add two flags to the PR
  982. request = pagure.lib.query.search_pull_requests(
  983. self.session, project_id=1, requestid=1
  984. )
  985. msg = pagure.lib.query.add_pull_request_flag(
  986. session=self.session,
  987. request=request,
  988. username="jenkins",
  989. percent=None,
  990. comment="Build passes",
  991. status="success",
  992. url="http://jenkins.cloud.fedoraproject.org",
  993. uid="jenkins_build_pagure_34",
  994. user="foo",
  995. token="aaabbbcccddd",
  996. )
  997. self.assertEqual(msg, ("Flag added", "jenkins_build_pagure_34"))
  998. self.session.commit()
  999. msg = pagure.lib.query.add_pull_request_flag(
  1000. session=self.session,
  1001. request=request,
  1002. username="travis",
  1003. percent=None,
  1004. comment="Build pending",
  1005. status="pending",
  1006. url="http://travis.io",
  1007. uid="travis_build_pagure_34",
  1008. user="foo",
  1009. token="aaabbbcccddd",
  1010. )
  1011. self.assertEqual(msg, ("Flag added", "travis_build_pagure_34"))
  1012. self.session.commit()
  1013. self.assertEqual(len(request.flags), 2)
  1014. self.assertEqual(request.flags[1].token_id, "aaabbbcccddd")
  1015. self.assertEqual(request.flags[0].token_id, "aaabbbcccddd")
  1016. # 1 flag
  1017. output = self.app.get("/api/0/test/pull-request/1/flag")
  1018. self.assertEqual(output.status_code, 200)
  1019. data = json.loads(output.get_data(as_text=True))
  1020. data["flags"][0]["date_created"] = "1541413645"
  1021. data["flags"][0]["date_updated"] = "1541413645"
  1022. data["flags"][0][
  1023. "pull_request_uid"
  1024. ] = "72a61033c2fc464aa9ef514c057aa62c"
  1025. data["flags"][1]["date_created"] = "1541413645"
  1026. data["flags"][1]["date_updated"] = "1541413645"
  1027. data["flags"][1][
  1028. "pull_request_uid"
  1029. ] = "72a61033c2fc464aa9ef514c057aa62c"
  1030. self.assertDictEqual(
  1031. data,
  1032. {
  1033. "flags": [
  1034. {
  1035. "comment": "Build pending",
  1036. "date_created": "1541413645",
  1037. "date_updated": "1541413645",
  1038. "percent": None,
  1039. "pull_request_uid": "72a61033c2fc464aa9ef514c057aa62c",
  1040. "status": "pending",
  1041. "url": "http://travis.io",
  1042. "user": {
  1043. "fullname": "foo bar",
  1044. "name": "foo",
  1045. "url_path": "user/foo",
  1046. },
  1047. "username": "travis",
  1048. },
  1049. {
  1050. "comment": "Build passes",
  1051. "date_created": "1541413645",
  1052. "date_updated": "1541413645",
  1053. "percent": None,
  1054. "pull_request_uid": "72a61033c2fc464aa9ef514c057aa62c",
  1055. "status": "success",
  1056. "url": "http://jenkins.cloud.fedoraproject.org",
  1057. "user": {
  1058. "fullname": "foo bar",
  1059. "name": "foo",
  1060. "url_path": "user/foo",
  1061. },
  1062. "username": "jenkins",
  1063. },
  1064. ]
  1065. },
  1066. )
  1067. if __name__ == "__main__":
  1068. unittest.main(verbosity=2)