test_pagure_flask_api_pr_flag.py 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173
  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. },
  227. "username": "Jenkins",
  228. },
  229. "message": "Flag added",
  230. "uid": "jenkins_build_pagure_100+seed",
  231. "avatar_url": "https://seccdn.libravatar.org/avatar/...",
  232. "user": "pingou",
  233. },
  234. )
  235. # One flag added
  236. self.session.commit()
  237. request = pagure.lib.query.search_pull_requests(
  238. self.session, project_id=1, requestid=1
  239. )
  240. self.assertEqual(len(request.flags), 1)
  241. self.assertEqual(request.flags[0].comment, "Tests running")
  242. self.assertEqual(request.flags[0].percent, None)
  243. # Check the notification sent
  244. mock_email.assert_called_once_with(
  245. "\nJenkins flagged the pull-request `test pull-request` "
  246. "as pending: Tests running\n\n"
  247. "http://localhost.localdomain/test/pull-request/1\n",
  248. "PR #1 - Jenkins: pending",
  249. "bar@pingou.com",
  250. assignee=None,
  251. in_reply_to="test-pull-request-" + pr_uid,
  252. mail_id="test-pull-request-" + pr_uid + "-1",
  253. project_name="test",
  254. reporter="pingou",
  255. user_from="Jenkins",
  256. )
  257. def test_updating_flag(self):
  258. """ Test the updating the flag of a PR. """
  259. headers = {"Authorization": "token aaabbbcccddd"}
  260. data = {
  261. "username": "Jenkins",
  262. "comment": "Tests running",
  263. "url": "http://jenkins.cloud.fedoraproject.org/",
  264. "uid": "jenkins_build_pagure_100+seed",
  265. }
  266. # Valid request
  267. output = self.app.post(
  268. "/api/0/test/pull-request/1/flag", data=data, headers=headers
  269. )
  270. self.assertEqual(output.status_code, 200)
  271. data = json.loads(output.get_data(as_text=True))
  272. data["flag"]["date_created"] = "1510742565"
  273. data["flag"]["date_updated"] = "1510742565"
  274. data["flag"]["pull_request_uid"] = "62b49f00d489452994de5010565fab81"
  275. data["avatar_url"] = "https://seccdn.libravatar.org/avatar/..."
  276. self.assertDictEqual(
  277. data,
  278. {
  279. "flag": {
  280. "comment": "Tests running",
  281. "date_created": "1510742565",
  282. "date_updated": "1510742565",
  283. "percent": None,
  284. "pull_request_uid": "62b49f00d489452994de5010565fab81",
  285. "status": "pending",
  286. "url": "http://jenkins.cloud.fedoraproject.org/",
  287. "user": {
  288. "default_email": "bar@pingou.com",
  289. "emails": ["bar@pingou.com", "foo@pingou.com"],
  290. "fullname": "PY C",
  291. "name": "pingou",
  292. },
  293. "username": "Jenkins",
  294. },
  295. "message": "Flag added",
  296. "uid": "jenkins_build_pagure_100+seed",
  297. "avatar_url": "https://seccdn.libravatar.org/avatar/...",
  298. "user": "pingou",
  299. },
  300. )
  301. # One flag added
  302. self.session.commit()
  303. request = pagure.lib.query.search_pull_requests(
  304. self.session, project_id=1, requestid=1
  305. )
  306. self.assertEqual(len(request.flags), 1)
  307. self.assertEqual(request.flags[0].comment, "Tests running")
  308. self.assertEqual(request.flags[0].percent, None)
  309. # Update flag - w/o providing the status
  310. data = {
  311. "username": "Jenkins",
  312. "percent": 100,
  313. "comment": "Tests passed",
  314. "url": "http://jenkins.cloud.fedoraproject.org/",
  315. "uid": "jenkins_build_pagure_100+seed",
  316. }
  317. output = self.app.post(
  318. "/api/0/test/pull-request/1/flag", data=data, headers=headers
  319. )
  320. self.assertEqual(output.status_code, 200)
  321. data = json.loads(output.get_data(as_text=True))
  322. data["flag"]["date_created"] = "1510742565"
  323. data["flag"]["date_updated"] = "1510742565"
  324. data["flag"]["pull_request_uid"] = "62b49f00d489452994de5010565fab81"
  325. data["avatar_url"] = "https://seccdn.libravatar.org/avatar/..."
  326. self.assertDictEqual(
  327. data,
  328. {
  329. "flag": {
  330. "comment": "Tests passed",
  331. "date_created": "1510742565",
  332. "date_updated": "1510742565",
  333. "percent": 100,
  334. "pull_request_uid": "62b49f00d489452994de5010565fab81",
  335. "status": "success",
  336. "url": "http://jenkins.cloud.fedoraproject.org/",
  337. "user": {
  338. "default_email": "bar@pingou.com",
  339. "emails": ["bar@pingou.com", "foo@pingou.com"],
  340. "fullname": "PY C",
  341. "name": "pingou",
  342. },
  343. "username": "Jenkins",
  344. },
  345. "message": "Flag updated",
  346. "uid": "jenkins_build_pagure_100+seed",
  347. "avatar_url": "https://seccdn.libravatar.org/avatar/...",
  348. "user": "pingou",
  349. },
  350. )
  351. # One flag added
  352. self.session.commit()
  353. request = pagure.lib.query.search_pull_requests(
  354. self.session, project_id=1, requestid=1
  355. )
  356. self.assertEqual(len(request.flags), 1)
  357. self.assertEqual(request.flags[0].comment, "Tests passed")
  358. self.assertEqual(request.flags[0].percent, 100)
  359. def test_adding_two_flags(self):
  360. """ Test the adding two flags to a PR. """
  361. headers = {"Authorization": "token aaabbbcccddd"}
  362. data = {
  363. "username": "Jenkins",
  364. "comment": "Tests passed",
  365. "status": "success",
  366. "percent": "100",
  367. "url": "http://jenkins.cloud.fedoraproject.org/",
  368. "uid": "jenkins_build_pagure_100+seed",
  369. }
  370. # Valid request
  371. output = self.app.post(
  372. "/api/0/test/pull-request/1/flag", data=data, headers=headers
  373. )
  374. self.assertEqual(output.status_code, 200)
  375. data = json.loads(output.get_data(as_text=True))
  376. data["flag"]["date_created"] = "1510742565"
  377. data["flag"]["date_updated"] = "1510742565"
  378. data["flag"]["pull_request_uid"] = "62b49f00d489452994de5010565fab81"
  379. data["avatar_url"] = "https://seccdn.libravatar.org/avatar/..."
  380. self.assertDictEqual(
  381. data,
  382. {
  383. "flag": {
  384. "comment": "Tests passed",
  385. "date_created": "1510742565",
  386. "date_updated": "1510742565",
  387. "percent": 100,
  388. "pull_request_uid": "62b49f00d489452994de5010565fab81",
  389. "status": "success",
  390. "url": "http://jenkins.cloud.fedoraproject.org/",
  391. "user": {
  392. "default_email": "bar@pingou.com",
  393. "emails": ["bar@pingou.com", "foo@pingou.com"],
  394. "fullname": "PY C",
  395. "name": "pingou",
  396. },
  397. "username": "Jenkins",
  398. },
  399. "message": "Flag added",
  400. "uid": "jenkins_build_pagure_100+seed",
  401. "avatar_url": "https://seccdn.libravatar.org/avatar/...",
  402. "user": "pingou",
  403. },
  404. )
  405. # One flag added
  406. self.session.commit()
  407. request = pagure.lib.query.search_pull_requests(
  408. self.session, project_id=1, requestid=1
  409. )
  410. self.assertEqual(len(request.flags), 1)
  411. self.assertEqual(request.flags[0].comment, "Tests passed")
  412. self.assertEqual(request.flags[0].percent, 100)
  413. data = {
  414. "username": "Jenkins",
  415. "comment": "Tests running again",
  416. "url": "http://jenkins.cloud.fedoraproject.org/",
  417. }
  418. # Valid request
  419. output = self.app.post(
  420. "/api/0/test/pull-request/1/flag", data=data, headers=headers
  421. )
  422. self.assertEqual(output.status_code, 200)
  423. data = json.loads(output.get_data(as_text=True))
  424. data["flag"]["date_created"] = "1510742565"
  425. data["flag"]["date_updated"] = "1510742565"
  426. data["flag"]["pull_request_uid"] = "62b49f00d489452994de5010565fab81"
  427. self.assertNotEqual(data["uid"], "jenkins_build_pagure_100+seed")
  428. data["uid"] = "jenkins_build_pagure_100+seed"
  429. data["avatar_url"] = "https://seccdn.libravatar.org/avatar/..."
  430. self.assertDictEqual(
  431. data,
  432. {
  433. "flag": {
  434. "comment": "Tests running again",
  435. "date_created": "1510742565",
  436. "date_updated": "1510742565",
  437. "percent": None,
  438. "pull_request_uid": "62b49f00d489452994de5010565fab81",
  439. "status": "pending",
  440. "url": "http://jenkins.cloud.fedoraproject.org/",
  441. "user": {
  442. "default_email": "bar@pingou.com",
  443. "emails": ["bar@pingou.com", "foo@pingou.com"],
  444. "fullname": "PY C",
  445. "name": "pingou",
  446. },
  447. "username": "Jenkins",
  448. },
  449. "message": "Flag added",
  450. "uid": "jenkins_build_pagure_100+seed",
  451. "avatar_url": "https://seccdn.libravatar.org/avatar/...",
  452. "user": "pingou",
  453. },
  454. )
  455. # Two flag added
  456. self.session.commit()
  457. request = pagure.lib.query.search_pull_requests(
  458. self.session, project_id=1, requestid=1
  459. )
  460. self.assertEqual(len(request.flags), 2)
  461. self.assertEqual(request.flags[0].comment, "Tests running again")
  462. self.assertEqual(request.flags[0].percent, None)
  463. self.assertEqual(request.flags[1].comment, "Tests passed")
  464. self.assertEqual(request.flags[1].percent, 100)
  465. @patch.dict(
  466. "pagure.config.config",
  467. {
  468. "FLAG_STATUSES_LABELS": {
  469. "pend!": "label-info",
  470. "succeed!": "label-success",
  471. "fail!": "label-danger",
  472. "what?": "label-warning",
  473. },
  474. "FLAG_PENDING": "pend!",
  475. "FLAG_SUCCESS": "succeed!",
  476. "FLAG_FAILURE": "fail!",
  477. },
  478. )
  479. def test_flagging_a_pull_request_while_having_custom_statuses(self):
  480. """ Test flagging a PR while having custom statuses. """
  481. headers = {"Authorization": "token aaabbbcccddd"}
  482. # No status and no percent => should use FLAG_PENDING
  483. send_data = {
  484. "username": "Jenkins",
  485. "comment": "Tests running",
  486. "url": "http://jenkins.cloud.fedoraproject.org/",
  487. "uid": "jenkins_build_pagure_100+seed",
  488. }
  489. output = self.app.post(
  490. "/api/0/test/pull-request/1/flag", data=send_data, headers=headers
  491. )
  492. data = json.loads(output.get_data(as_text=True))
  493. self.assertEqual(output.status_code, 200)
  494. self.assertEqual(data["flag"]["status"], "pend!")
  495. # No status and 50 % => should use FLAG_SUCCESS
  496. send_data["percent"] = 50
  497. output = self.app.post(
  498. "/api/0/test/pull-request/1/flag", data=send_data, headers=headers
  499. )
  500. data = json.loads(output.get_data(as_text=True))
  501. self.assertEqual(output.status_code, 200)
  502. self.assertEqual(data["flag"]["status"], "succeed!")
  503. # No status and 0 % => should use FLAG_FAILURE
  504. send_data["percent"] = 0
  505. output = self.app.post(
  506. "/api/0/test/pull-request/1/flag", data=send_data, headers=headers
  507. )
  508. data = json.loads(output.get_data(as_text=True))
  509. self.assertEqual(output.status_code, 200)
  510. self.assertEqual(data["flag"]["status"], "fail!")
  511. # Explicitly set status
  512. send_data["status"] = "what?"
  513. output = self.app.post(
  514. "/api/0/test/pull-request/1/flag", data=send_data, headers=headers
  515. )
  516. data = json.loads(output.get_data(as_text=True))
  517. self.assertEqual(output.status_code, 200)
  518. self.assertEqual(data["flag"]["status"], "what?")
  519. # Explicitly set wrong status
  520. send_data["status"] = "nooo....."
  521. output = self.app.post(
  522. "/api/0/test/pull-request/1/flag", data=send_data, headers=headers
  523. )
  524. data = json.loads(output.get_data(as_text=True))
  525. self.assertEqual(output.status_code, 400)
  526. self.assertDictEqual(
  527. data,
  528. {
  529. "error": "Invalid or incomplete input submitted",
  530. "error_code": "EINVALIDREQ",
  531. "errors": {"status": ["Not a valid choice"]},
  532. },
  533. )
  534. class PagureFlaskApiPRFlagUserTokentests(tests.Modeltests):
  535. """ Tests for the flask API of pagure for flagging pull-requests using
  536. an user token (ie: not restricted to a specific project).
  537. """
  538. maxDiff = None
  539. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  540. def setUp(self):
  541. """ Set up the environnment, ran before every tests. """
  542. super(PagureFlaskApiPRFlagUserTokentests, self).setUp()
  543. pagure.config.config["REQUESTS_FOLDER"] = None
  544. tests.create_projects(self.session)
  545. tests.create_tokens(self.session, project_id=None)
  546. tests.create_tokens_acl(self.session)
  547. # Create a pull-request
  548. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  549. forked_repo = pagure.lib.query.get_authorized_project(
  550. self.session, "test"
  551. )
  552. req = pagure.lib.query.new_pull_request(
  553. session=self.session,
  554. repo_from=forked_repo,
  555. branch_from="master",
  556. repo_to=repo,
  557. branch_to="master",
  558. title="test pull-request",
  559. user="pingou",
  560. )
  561. self.session.commit()
  562. self.assertEqual(req.id, 1)
  563. self.assertEqual(req.title, "test pull-request")
  564. # Check flags before
  565. self.session.commit()
  566. request = pagure.lib.query.search_pull_requests(
  567. self.session, project_id=1, requestid=1
  568. )
  569. self.assertEqual(len(request.flags), 0)
  570. def test_no_pr(self):
  571. """ Test flagging a non-existing PR. """
  572. headers = {"Authorization": "token aaabbbcccddd"}
  573. # Invalid project
  574. output = self.app.post(
  575. "/api/0/foo/pull-request/1/flag", headers=headers
  576. )
  577. self.assertEqual(output.status_code, 404)
  578. data = json.loads(output.get_data(as_text=True))
  579. self.assertDictEqual(
  580. data, {"error": "Project not found", "error_code": "ENOPROJECT"}
  581. )
  582. def test_no_pr_other_project(self):
  583. """ Test flagging a non-existing PR on a different project. """
  584. headers = {"Authorization": "token aaabbbcccddd"}
  585. # Valid token, wrong project
  586. output = self.app.post(
  587. "/api/0/test2/pull-request/1/flag", headers=headers
  588. )
  589. self.assertEqual(output.status_code, 404)
  590. data = json.loads(output.get_data(as_text=True))
  591. self.assertDictEqual(
  592. data, {"error": "Pull-Request not found", "error_code": "ENOREQ"}
  593. )
  594. def test_no_input(self):
  595. """ Test flagging an existing PR but without submitting any data. """
  596. headers = {"Authorization": "token aaabbbcccddd"}
  597. # No input
  598. output = self.app.post(
  599. "/api/0/test/pull-request/1/flag", headers=headers
  600. )
  601. self.assertEqual(output.status_code, 400)
  602. data = json.loads(output.get_data(as_text=True))
  603. self.assertDictEqual(
  604. data,
  605. {
  606. "error": "Invalid or incomplete input submitted",
  607. "error_code": "EINVALIDREQ",
  608. "errors": {
  609. "comment": ["This field is required."],
  610. "url": ["This field is required."],
  611. "username": ["This field is required."],
  612. },
  613. },
  614. )
  615. def test_no_comment(self):
  616. """ Test flagging an existing PR but without all the required info.
  617. """
  618. headers = {"Authorization": "token aaabbbcccddd"}
  619. data = {
  620. "username": "Jenkins",
  621. "percent": 100,
  622. "url": "http://jenkins.cloud.fedoraproject.org/",
  623. "uid": "jenkins_build_pagure_100+seed",
  624. }
  625. # Incomplete request
  626. output = self.app.post(
  627. "/api/0/test/pull-request/1/flag", data=data, headers=headers
  628. )
  629. self.assertEqual(output.status_code, 400)
  630. data = json.loads(output.get_data(as_text=True))
  631. self.assertDictEqual(
  632. data,
  633. {
  634. "error": "Invalid or incomplete input submitted",
  635. "error_code": "EINVALIDREQ",
  636. "errors": {"comment": ["This field is required."]},
  637. },
  638. )
  639. # No change
  640. self.session.commit()
  641. request = pagure.lib.query.search_pull_requests(
  642. self.session, project_id=1, requestid=1
  643. )
  644. self.assertEqual(len(request.flags), 0)
  645. def test_invalid_status(self):
  646. """ Test flagging an existing PR but with an invalid status.
  647. """
  648. headers = {"Authorization": "token aaabbbcccddd"}
  649. data = {
  650. "username": "Jenkins",
  651. "status": "failed",
  652. "comment": "Failed to run the tests",
  653. "url": "http://jenkins.cloud.fedoraproject.org/",
  654. "uid": "jenkins_build_pagure_100+seed",
  655. }
  656. # Invalid status submitted
  657. output = self.app.post(
  658. "/api/0/test/pull-request/1/flag", data=data, headers=headers
  659. )
  660. self.assertEqual(output.status_code, 400)
  661. data = json.loads(output.get_data(as_text=True))
  662. self.assertDictEqual(
  663. data,
  664. {
  665. "error": "Invalid or incomplete input submitted",
  666. "error_code": "EINVALIDREQ",
  667. "errors": {"status": ["Not a valid choice"]},
  668. },
  669. )
  670. # No change
  671. self.session.commit()
  672. request = pagure.lib.query.search_pull_requests(
  673. self.session, project_id=1, requestid=1
  674. )
  675. self.assertEqual(len(request.flags), 0)
  676. @patch("pagure.lib.notify.send_email")
  677. def test_flag_pr_no_status(self, mock_email):
  678. """ Test flagging an existing PR without providing a status.
  679. Also check that no notifications have been sent.
  680. """
  681. headers = {"Authorization": "token aaabbbcccddd"}
  682. data = {
  683. "username": "Jenkins",
  684. "percent": 0,
  685. "comment": "Tests failed",
  686. "url": "http://jenkins.cloud.fedoraproject.org/",
  687. "uid": "jenkins_build_pagure_100+seed",
  688. }
  689. # Valid request - w/o providing the status
  690. output = self.app.post(
  691. "/api/0/test/pull-request/1/flag", data=data, headers=headers
  692. )
  693. self.assertEqual(output.status_code, 200)
  694. data = json.loads(output.get_data(as_text=True))
  695. data["flag"]["date_created"] = "1510742565"
  696. data["flag"]["date_updated"] = "1510742565"
  697. data["flag"]["pull_request_uid"] = "62b49f00d489452994de5010565fab81"
  698. data["avatar_url"] = "https://seccdn.libravatar.org/avatar/..."
  699. self.assertDictEqual(
  700. data,
  701. {
  702. "flag": {
  703. "comment": "Tests failed",
  704. "date_created": "1510742565",
  705. "date_updated": "1510742565",
  706. "percent": 0,
  707. "pull_request_uid": "62b49f00d489452994de5010565fab81",
  708. "status": "failure",
  709. "url": "http://jenkins.cloud.fedoraproject.org/",
  710. "user": {
  711. "default_email": "bar@pingou.com",
  712. "emails": ["bar@pingou.com", "foo@pingou.com"],
  713. "fullname": "PY C",
  714. "name": "pingou",
  715. },
  716. "username": "Jenkins",
  717. },
  718. "message": "Flag added",
  719. "uid": "jenkins_build_pagure_100+seed",
  720. "avatar_url": "https://seccdn.libravatar.org/avatar/...",
  721. "user": "pingou",
  722. },
  723. )
  724. # One flag added
  725. self.session.commit()
  726. request = pagure.lib.query.search_pull_requests(
  727. self.session, project_id=1, requestid=1
  728. )
  729. self.assertEqual(len(request.flags), 1)
  730. self.assertEqual(request.flags[0].comment, "Tests failed")
  731. self.assertEqual(request.flags[0].percent, 0)
  732. # no notifications sent
  733. mock_email.assert_not_called()
  734. def test_editing_flag(self):
  735. """ Test flagging an existing PR without providing a status.
  736. """
  737. headers = {"Authorization": "token aaabbbcccddd"}
  738. data = {
  739. "username": "Jenkins",
  740. "status": "failure",
  741. "comment": "Tests failed",
  742. "url": "http://jenkins.cloud.fedoraproject.org/",
  743. "uid": "jenkins_build_pagure_100+seed",
  744. }
  745. # Valid request - w/o providing the status
  746. output = self.app.post(
  747. "/api/0/test/pull-request/1/flag", data=data, headers=headers
  748. )
  749. self.assertEqual(output.status_code, 200)
  750. data = json.loads(output.get_data(as_text=True))
  751. data["flag"]["date_created"] = "1510742565"
  752. data["flag"]["date_updated"] = "1510742565"
  753. data["flag"]["pull_request_uid"] = "62b49f00d489452994de5010565fab81"
  754. data["avatar_url"] = "https://seccdn.libravatar.org/avatar/..."
  755. self.assertDictEqual(
  756. data,
  757. {
  758. "flag": {
  759. "comment": "Tests failed",
  760. "date_created": "1510742565",
  761. "date_updated": "1510742565",
  762. "percent": None,
  763. "pull_request_uid": "62b49f00d489452994de5010565fab81",
  764. "status": "failure",
  765. "url": "http://jenkins.cloud.fedoraproject.org/",
  766. "user": {
  767. "default_email": "bar@pingou.com",
  768. "emails": ["bar@pingou.com", "foo@pingou.com"],
  769. "fullname": "PY C",
  770. "name": "pingou",
  771. },
  772. "username": "Jenkins",
  773. },
  774. "message": "Flag added",
  775. "uid": "jenkins_build_pagure_100+seed",
  776. "avatar_url": "https://seccdn.libravatar.org/avatar/...",
  777. "user": "pingou",
  778. },
  779. )
  780. # One flag added
  781. self.session.commit()
  782. request = pagure.lib.query.search_pull_requests(
  783. self.session, project_id=1, requestid=1
  784. )
  785. self.assertEqual(len(request.flags), 1)
  786. self.assertEqual(request.flags[0].comment, "Tests failed")
  787. self.assertEqual(request.flags[0].percent, None)
  788. # Update flag
  789. data = {
  790. "username": "Jenkins",
  791. "percent": 100,
  792. "comment": "Tests passed",
  793. "url": "http://jenkins.cloud.fedoraproject.org/",
  794. "uid": "jenkins_build_pagure_100+seed",
  795. "status": "success",
  796. }
  797. output = self.app.post(
  798. "/api/0/test/pull-request/1/flag", data=data, headers=headers
  799. )
  800. self.assertEqual(output.status_code, 200)
  801. data = json.loads(output.get_data(as_text=True))
  802. data["flag"]["date_created"] = "1510742565"
  803. data["flag"]["date_updated"] = "1510742565"
  804. data["flag"]["pull_request_uid"] = "62b49f00d489452994de5010565fab81"
  805. data["avatar_url"] = "https://seccdn.libravatar.org/avatar/..."
  806. self.assertDictEqual(
  807. data,
  808. {
  809. "flag": {
  810. "comment": "Tests passed",
  811. "date_created": "1510742565",
  812. "date_updated": "1510742565",
  813. "percent": 100,
  814. "pull_request_uid": "62b49f00d489452994de5010565fab81",
  815. "status": "success",
  816. "url": "http://jenkins.cloud.fedoraproject.org/",
  817. "user": {
  818. "default_email": "bar@pingou.com",
  819. "emails": ["bar@pingou.com", "foo@pingou.com"],
  820. "fullname": "PY C",
  821. "name": "pingou",
  822. },
  823. "username": "Jenkins",
  824. },
  825. "message": "Flag updated",
  826. "uid": "jenkins_build_pagure_100+seed",
  827. "avatar_url": "https://seccdn.libravatar.org/avatar/...",
  828. "user": "pingou",
  829. },
  830. )
  831. # Still only one flag
  832. self.session.commit()
  833. request = pagure.lib.query.search_pull_requests(
  834. self.session, project_id=1, requestid=1
  835. )
  836. self.assertEqual(len(request.flags), 1)
  837. self.assertEqual(request.flags[0].comment, "Tests passed")
  838. self.assertEqual(request.flags[0].percent, 100)
  839. class PagureFlaskApiGetPRFlagtests(tests.Modeltests):
  840. """ Tests for the flask API of pagure for retrieving pull-requests flags
  841. """
  842. maxDiff = None
  843. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  844. def setUp(self):
  845. """ Set up the environnment, ran before every tests. """
  846. super(PagureFlaskApiGetPRFlagtests, self).setUp()
  847. pagure.config.config["REQUESTS_FOLDER"] = None
  848. tests.create_projects(self.session)
  849. tests.create_tokens(self.session)
  850. tests.create_tokens_acl(self.session)
  851. # Create a pull-request
  852. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  853. forked_repo = pagure.lib.query.get_authorized_project(
  854. self.session, "test"
  855. )
  856. req = pagure.lib.query.new_pull_request(
  857. session=self.session,
  858. repo_from=forked_repo,
  859. branch_from="master",
  860. repo_to=repo,
  861. branch_to="master",
  862. title="test pull-request",
  863. user="pingou",
  864. )
  865. self.session.commit()
  866. self.assertEqual(req.id, 1)
  867. self.assertEqual(req.title, "test pull-request")
  868. # Check flags before
  869. self.session.commit()
  870. request = pagure.lib.query.search_pull_requests(
  871. self.session, project_id=1, requestid=1
  872. )
  873. self.assertEqual(len(request.flags), 0)
  874. def test_invalid_project(self):
  875. """ Test the retrieving the flags of a PR on an invalid project. """
  876. # Invalid project
  877. output = self.app.get("/api/0/foo/pull-request/1/flag")
  878. self.assertEqual(output.status_code, 404)
  879. data = json.loads(output.get_data(as_text=True))
  880. self.assertDictEqual(
  881. data, {"error": "Project not found", "error_code": "ENOPROJECT"}
  882. )
  883. def test_pr_disabled(self):
  884. """ Test the retrieving the flags of a PR when PRs are disabled. """
  885. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  886. settings = repo.settings
  887. settings["pull_requests"] = False
  888. repo.settings = settings
  889. self.session.add(repo)
  890. self.session.commit()
  891. # PRs disabled
  892. output = self.app.get("/api/0/test/pull-request/1/flag")
  893. self.assertEqual(output.status_code, 404)
  894. data = json.loads(output.get_data(as_text=True))
  895. self.assertDictEqual(
  896. data,
  897. {
  898. "error": "Pull-Request have been deactivated for this project",
  899. "error_code": "EPULLREQUESTSDISABLED",
  900. },
  901. )
  902. def test_no_pr(self):
  903. """ Test the retrieving the flags of a PR when the PR doesn't exist. """
  904. # No PR
  905. output = self.app.get("/api/0/test/pull-request/10/flag")
  906. self.assertEqual(output.status_code, 404)
  907. data = json.loads(output.get_data(as_text=True))
  908. self.assertDictEqual(
  909. data, {"error": "Pull-Request not found", "error_code": "ENOREQ"}
  910. )
  911. def test_no_flag(self):
  912. """ Test the retrieving the flags of a PR when the PR has no flags. """
  913. # No flag
  914. output = self.app.get("/api/0/test/pull-request/1/flag")
  915. self.assertEqual(output.status_code, 200)
  916. data = json.loads(output.get_data(as_text=True))
  917. self.assertDictEqual(data, {"flags": []})
  918. def test_get_flag(self):
  919. """ Test the retrieving the flags of a PR when the PR has one flag. """
  920. # Add a flag to the PR
  921. request = pagure.lib.query.search_pull_requests(
  922. self.session, project_id=1, requestid=1
  923. )
  924. msg = pagure.lib.query.add_pull_request_flag(
  925. session=self.session,
  926. request=request,
  927. username="jenkins",
  928. percent=None,
  929. comment="Build passes",
  930. status="success",
  931. url="http://jenkins.cloud.fedoraproject.org",
  932. uid="jenkins_build_pagure_34",
  933. user="foo",
  934. token="aaabbbcccddd",
  935. )
  936. self.assertEqual(msg, ("Flag added", "jenkins_build_pagure_34"))
  937. self.session.commit()
  938. self.assertEqual(len(request.flags), 1)
  939. self.assertEqual(request.flags[0].token_id, "aaabbbcccddd")
  940. # 1 flag
  941. output = self.app.get("/api/0/test/pull-request/1/flag")
  942. self.assertEqual(output.status_code, 200)
  943. data = json.loads(output.get_data(as_text=True))
  944. data["flags"][0]["date_created"] = "1541413645"
  945. data["flags"][0]["date_updated"] = "1541413645"
  946. data["flags"][0][
  947. "pull_request_uid"
  948. ] = "72a61033c2fc464aa9ef514c057aa62c"
  949. self.assertDictEqual(
  950. data,
  951. {
  952. "flags": [
  953. {
  954. "comment": "Build passes",
  955. "date_created": "1541413645",
  956. "date_updated": "1541413645",
  957. "percent": None,
  958. "pull_request_uid": "72a61033c2fc464aa9ef514c057aa62c",
  959. "status": "success",
  960. "url": "http://jenkins.cloud.fedoraproject.org",
  961. "user": {"fullname": "foo bar", "name": "foo"},
  962. "username": "jenkins",
  963. }
  964. ]
  965. },
  966. )
  967. def test_get_flags(self):
  968. """ Test the retrieving the flags of a PR when the PR has one flag. """
  969. # Add two flags to the PR
  970. request = pagure.lib.query.search_pull_requests(
  971. self.session, project_id=1, requestid=1
  972. )
  973. msg = pagure.lib.query.add_pull_request_flag(
  974. session=self.session,
  975. request=request,
  976. username="jenkins",
  977. percent=None,
  978. comment="Build passes",
  979. status="success",
  980. url="http://jenkins.cloud.fedoraproject.org",
  981. uid="jenkins_build_pagure_34",
  982. user="foo",
  983. token="aaabbbcccddd",
  984. )
  985. self.assertEqual(msg, ("Flag added", "jenkins_build_pagure_34"))
  986. self.session.commit()
  987. msg = pagure.lib.query.add_pull_request_flag(
  988. session=self.session,
  989. request=request,
  990. username="travis",
  991. percent=None,
  992. comment="Build pending",
  993. status="pending",
  994. url="http://travis.io",
  995. uid="travis_build_pagure_34",
  996. user="foo",
  997. token="aaabbbcccddd",
  998. )
  999. self.assertEqual(msg, ("Flag added", "travis_build_pagure_34"))
  1000. self.session.commit()
  1001. self.assertEqual(len(request.flags), 2)
  1002. self.assertEqual(request.flags[1].token_id, "aaabbbcccddd")
  1003. self.assertEqual(request.flags[0].token_id, "aaabbbcccddd")
  1004. # 1 flag
  1005. output = self.app.get("/api/0/test/pull-request/1/flag")
  1006. self.assertEqual(output.status_code, 200)
  1007. data = json.loads(output.get_data(as_text=True))
  1008. data["flags"][0]["date_created"] = "1541413645"
  1009. data["flags"][0]["date_updated"] = "1541413645"
  1010. data["flags"][0][
  1011. "pull_request_uid"
  1012. ] = "72a61033c2fc464aa9ef514c057aa62c"
  1013. data["flags"][1]["date_created"] = "1541413645"
  1014. data["flags"][1]["date_updated"] = "1541413645"
  1015. data["flags"][1][
  1016. "pull_request_uid"
  1017. ] = "72a61033c2fc464aa9ef514c057aa62c"
  1018. self.assertDictEqual(
  1019. data,
  1020. {
  1021. "flags": [
  1022. {
  1023. "comment": "Build pending",
  1024. "date_created": "1541413645",
  1025. "date_updated": "1541413645",
  1026. "percent": None,
  1027. "pull_request_uid": "72a61033c2fc464aa9ef514c057aa62c",
  1028. "status": "pending",
  1029. "url": "http://travis.io",
  1030. "user": {"fullname": "foo bar", "name": "foo"},
  1031. "username": "travis",
  1032. },
  1033. {
  1034. "comment": "Build passes",
  1035. "date_created": "1541413645",
  1036. "date_updated": "1541413645",
  1037. "percent": None,
  1038. "pull_request_uid": "72a61033c2fc464aa9ef514c057aa62c",
  1039. "status": "success",
  1040. "url": "http://jenkins.cloud.fedoraproject.org",
  1041. "user": {"fullname": "foo bar", "name": "foo"},
  1042. "username": "jenkins",
  1043. },
  1044. ]
  1045. },
  1046. )
  1047. if __name__ == "__main__":
  1048. unittest.main(verbosity=2)