test_pagure_flask_api_pr_flag.py 44 KB

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