test_pagure_flask_api_pr_flag.py 42 KB

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