1
0

test_pagure_flask_api_issue.py 90 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872
  1. # -*- coding: utf-8 -*-
  2. """
  3. (c) 2015 - Copyright Red Hat Inc
  4. Authors:
  5. Pierre-Yves Chibon <pingou@pingoured.fr>
  6. """
  7. __requires__ = ['SQLAlchemy >= 0.8']
  8. import pkg_resources
  9. import copy
  10. import datetime
  11. import unittest
  12. import shutil
  13. import sys
  14. import time
  15. import os
  16. import json
  17. from mock import patch
  18. sys.path.insert(0, os.path.join(os.path.dirname(
  19. os.path.abspath(__file__)), '..'))
  20. import pagure
  21. import pagure.lib
  22. import tests
  23. FULL_ISSUE_LIST = [
  24. {
  25. "assignee": None,
  26. "blocks": [],
  27. "close_status": None,
  28. "closed_at": None,
  29. "comments": [],
  30. "content": "We should work on this",
  31. "custom_fields": [],
  32. "date_created": "1431414800",
  33. "depends": [],
  34. "id": 9,
  35. "last_updated": "1431414800",
  36. "milestone": "",
  37. "priority": None,
  38. "private": True,
  39. "status": "Open",
  40. "tags": [],
  41. "title": "Test issue",
  42. "user": {
  43. "fullname": "PY C",
  44. "name": "pingou"
  45. }
  46. },
  47. {
  48. "assignee": None,
  49. "blocks": [],
  50. "close_status": None,
  51. "closed_at": None,
  52. "comments": [],
  53. "content": "This issue needs attention",
  54. "custom_fields": [],
  55. "date_created": "1431414800",
  56. "depends": [],
  57. "id": 8,
  58. "last_updated": "1431414800",
  59. "milestone": "",
  60. "priority": None,
  61. "private": True,
  62. "status": "Open",
  63. "tags": [],
  64. "title": "test issue1",
  65. "user": {
  66. "fullname": "PY C",
  67. "name": "pingou"
  68. }
  69. },
  70. {
  71. "assignee": None,
  72. "blocks": [],
  73. "close_status": None,
  74. "closed_at": None,
  75. "comments": [],
  76. "content": "This issue needs attention",
  77. "custom_fields": [],
  78. "date_created": "1431414800",
  79. "depends": [],
  80. "id": 7,
  81. "last_updated": "1431414800",
  82. "milestone": "",
  83. "priority": None,
  84. "private": True,
  85. "status": "Open",
  86. "tags": [],
  87. "title": "test issue",
  88. "user": {
  89. "fullname": "PY C",
  90. "name": "pingou"
  91. }
  92. },
  93. {
  94. "assignee": None,
  95. "blocks": [],
  96. "close_status": None,
  97. "closed_at": None,
  98. "comments": [],
  99. "content": "This issue needs attention",
  100. "custom_fields": [],
  101. "date_created": "1431414800",
  102. "depends": [],
  103. "id": 6,
  104. "last_updated": "1431414800",
  105. "milestone": "",
  106. "priority": None,
  107. "private": False,
  108. "status": "Open",
  109. "tags": [],
  110. "title": "test issue",
  111. "user": {
  112. "fullname": "PY C",
  113. "name": "pingou"
  114. }
  115. },
  116. {
  117. "assignee": None,
  118. "blocks": [],
  119. "close_status": None,
  120. "closed_at": None,
  121. "comments": [],
  122. "content": "This issue needs attention",
  123. "custom_fields": [],
  124. "date_created": "1431414800",
  125. "depends": [],
  126. "id": 5,
  127. "last_updated": "1431414800",
  128. "milestone": "",
  129. "priority": None,
  130. "private": False,
  131. "status": "Open",
  132. "tags": [],
  133. "title": "test issue",
  134. "user": {
  135. "fullname": "PY C",
  136. "name": "pingou"
  137. }
  138. },
  139. {
  140. "assignee": None,
  141. "blocks": [],
  142. "close_status": None,
  143. "closed_at": None,
  144. "comments": [],
  145. "content": "This issue needs attention",
  146. "custom_fields": [],
  147. "date_created": "1431414800",
  148. "depends": [],
  149. "id": 4,
  150. "last_updated": "1431414800",
  151. "milestone": "",
  152. "priority": None,
  153. "private": False,
  154. "status": "Open",
  155. "tags": [],
  156. "title": "test issue",
  157. "user": {
  158. "fullname": "PY C",
  159. "name": "pingou"
  160. }
  161. },
  162. {
  163. "assignee": None,
  164. "blocks": [],
  165. "close_status": None,
  166. "closed_at": None,
  167. "comments": [],
  168. "content": "This issue needs attention",
  169. "custom_fields": [],
  170. "date_created": "1431414800",
  171. "depends": [],
  172. "id": 3,
  173. "last_updated": "1431414800",
  174. "milestone": "",
  175. "priority": None,
  176. "private": False,
  177. "status": "Open",
  178. "tags": [],
  179. "title": "test issue",
  180. "user": {
  181. "fullname": "PY C",
  182. "name": "pingou"
  183. }
  184. },
  185. {
  186. "assignee": None,
  187. "blocks": [],
  188. "close_status": None,
  189. "closed_at": None,
  190. "comments": [],
  191. "content": "This issue needs attention",
  192. "custom_fields": [],
  193. "date_created": "1431414800",
  194. "depends": [],
  195. "id": 2,
  196. "last_updated": "1431414800",
  197. "milestone": "milestone-1.0",
  198. "priority": None,
  199. "private": False,
  200. "status": "Open",
  201. "tags": [],
  202. "title": "test issue",
  203. "user": {
  204. "fullname": "PY C",
  205. "name": "pingou"
  206. }
  207. },
  208. {
  209. "assignee": None,
  210. "blocks": [],
  211. "close_status": None,
  212. "closed_at": None,
  213. "comments": [],
  214. "content": "This issue needs attention",
  215. "custom_fields": [],
  216. "date_created": "1431414800",
  217. "depends": [],
  218. "id": 1,
  219. "last_updated": "1431414800",
  220. "milestone": "",
  221. "priority": None,
  222. "private": False,
  223. "status": "Open",
  224. "tags": [],
  225. "title": "test issue",
  226. "user": {
  227. "fullname": "PY C",
  228. "name": "pingou"
  229. }
  230. }
  231. ]
  232. LCL_ISSUES = [
  233. {
  234. 'assignee': None,
  235. 'blocks': [],
  236. 'close_status': None,
  237. 'closed_at': None,
  238. 'comments': [],
  239. 'content': 'Description',
  240. 'custom_fields': [],
  241. 'date_created': '1431414800',
  242. 'depends': [],
  243. 'id': 2,
  244. 'last_updated': '1431414800',
  245. 'milestone': None,
  246. 'priority': None,
  247. 'private': False,
  248. 'status': 'Open',
  249. 'tags': [],
  250. 'title': 'Issue #2',
  251. 'user': {'fullname': 'PY C', 'name': 'pingou'}
  252. },
  253. {
  254. 'assignee': None,
  255. 'blocks': [],
  256. 'close_status': None,
  257. 'closed_at': None,
  258. 'comments': [],
  259. 'content': 'Description',
  260. 'custom_fields': [],
  261. 'date_created': '1431414800',
  262. 'depends': [],
  263. 'id': 1,
  264. 'last_updated': '1431414800',
  265. 'milestone': None,
  266. 'priority': None,
  267. 'private': False,
  268. 'status': 'Open',
  269. 'tags': [],
  270. 'title': 'Issue #1',
  271. 'user': {'fullname': 'PY C', 'name': 'pingou'}
  272. }
  273. ]
  274. class PagureFlaskApiIssuetests(tests.Modeltests):
  275. """ Tests for the flask API of pagure for issue """
  276. def setUp(self):
  277. """ Set up the environnment, ran before every tests. """
  278. super(PagureFlaskApiIssuetests, self).setUp()
  279. pagure.APP.config['TESTING'] = True
  280. pagure.SESSION = self.session
  281. pagure.api.SESSION = self.session
  282. pagure.api.issue.SESSION = self.session
  283. pagure.lib.SESSION = self.session
  284. pagure.APP.config['TICKETS_FOLDER'] = None
  285. self.app = pagure.APP.test_client()
  286. def test_api_new_issue(self):
  287. """ Test the api_new_issue method of the flask api. """
  288. tests.create_projects(self.session)
  289. tests.create_projects_git(
  290. os.path.join(self.path, 'tickets'), bare=True)
  291. tests.create_tokens(self.session)
  292. tests.create_tokens_acl(self.session)
  293. headers = {'Authorization': 'token aaabbbcccddd'}
  294. # Valid token, wrong project
  295. output = self.app.post('/api/0/test2/new_issue', headers=headers)
  296. self.assertEqual(output.status_code, 401)
  297. data = json.loads(output.data)
  298. self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.name,
  299. data['error_code'])
  300. self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.value, data['error'])
  301. # No input
  302. output = self.app.post('/api/0/test/new_issue', headers=headers)
  303. self.assertEqual(output.status_code, 400)
  304. data = json.loads(output.data)
  305. self.assertDictEqual(
  306. data,
  307. {
  308. "error": "Invalid or incomplete input submited",
  309. "error_code": "EINVALIDREQ",
  310. "errors": {
  311. "issue_content": ["This field is required."],
  312. "title": ["This field is required."],
  313. }
  314. }
  315. )
  316. data = {
  317. 'title': 'test issue'
  318. }
  319. # Invalid repo
  320. output = self.app.post(
  321. '/api/0/foo/new_issue', data=data, headers=headers)
  322. self.assertEqual(output.status_code, 404)
  323. data = json.loads(output.data)
  324. self.assertDictEqual(
  325. data,
  326. {
  327. "error": "Project not found",
  328. "error_code": "ENOPROJECT",
  329. }
  330. )
  331. # Incomplete request
  332. output = self.app.post(
  333. '/api/0/test/new_issue', data=data, headers=headers)
  334. self.assertEqual(output.status_code, 400)
  335. data = json.loads(output.data)
  336. self.assertDictEqual(
  337. data,
  338. {
  339. "error": "Invalid or incomplete input submited",
  340. "error_code": "EINVALIDREQ",
  341. "errors": {
  342. "issue_content": ["This field is required."],
  343. "title": ["This field is required."]
  344. }
  345. }
  346. )
  347. data = {
  348. 'title': 'test issue',
  349. 'issue_content': 'This issue needs attention',
  350. }
  351. # Valid request
  352. output = self.app.post(
  353. '/api/0/test/new_issue', data=data, headers=headers)
  354. self.assertEqual(output.status_code, 200)
  355. data = json.loads(output.data)
  356. data['issue']['date_created'] = '1431414800'
  357. data['issue']['last_updated'] = '1431414800'
  358. self.assertDictEqual(
  359. data,
  360. {
  361. "issue": FULL_ISSUE_LIST[8],
  362. "message": "Issue created"
  363. }
  364. )
  365. # Valid request with milestone
  366. data = {
  367. 'title': 'test issue',
  368. 'issue_content': 'This issue needs attention',
  369. 'milestone': ['milestone-1.0'],
  370. }
  371. output = self.app.post(
  372. '/api/0/test/new_issue', data=data, headers=headers)
  373. self.assertEqual(output.status_code, 200)
  374. data = json.loads(output.data)
  375. data['issue']['date_created'] = '1431414800'
  376. data['issue']['last_updated'] = '1431414800'
  377. self.assertDictEqual(
  378. data,
  379. {
  380. "issue": FULL_ISSUE_LIST[7],
  381. "message": "Issue created"
  382. }
  383. )
  384. # Valid request, with private='false'
  385. data = {
  386. 'title': 'test issue',
  387. 'issue_content': 'This issue needs attention',
  388. 'private': 'false',
  389. }
  390. output = self.app.post(
  391. '/api/0/test/new_issue', data=data, headers=headers)
  392. self.assertEqual(output.status_code, 200)
  393. data = json.loads(output.data)
  394. data['issue']['date_created'] = '1431414800'
  395. data['issue']['last_updated'] = '1431414800'
  396. self.assertDictEqual(
  397. data,
  398. {
  399. "issue": FULL_ISSUE_LIST[6],
  400. "message": "Issue created"
  401. }
  402. )
  403. # Valid request, with private=False
  404. data = {
  405. 'title': 'test issue',
  406. 'issue_content': 'This issue needs attention',
  407. 'private': False
  408. }
  409. output = self.app.post(
  410. '/api/0/test/new_issue', data=data, headers=headers)
  411. self.assertEqual(output.status_code, 200)
  412. data = json.loads(output.data)
  413. data['issue']['date_created'] = '1431414800'
  414. data['issue']['last_updated'] = '1431414800'
  415. self.assertDictEqual(
  416. data,
  417. {
  418. "issue": FULL_ISSUE_LIST[5],
  419. "message": "Issue created"
  420. }
  421. )
  422. # Valid request, with private='False'
  423. data = {
  424. 'title': 'test issue',
  425. 'issue_content': 'This issue needs attention',
  426. 'private': 'False'
  427. }
  428. output = self.app.post(
  429. '/api/0/test/new_issue', data=data, headers=headers)
  430. self.assertEqual(output.status_code, 200)
  431. data = json.loads(output.data)
  432. data['issue']['date_created'] = '1431414800'
  433. data['issue']['last_updated'] = '1431414800'
  434. self.assertDictEqual(
  435. data,
  436. {
  437. "issue": FULL_ISSUE_LIST[4],
  438. "message": "Issue created"
  439. }
  440. )
  441. # Valid request, with private=0
  442. data = {
  443. 'title': 'test issue',
  444. 'issue_content': 'This issue needs attention',
  445. 'private': 0
  446. }
  447. output = self.app.post(
  448. '/api/0/test/new_issue', data=data, headers=headers)
  449. self.assertEqual(output.status_code, 200)
  450. data = json.loads(output.data)
  451. data['issue']['date_created'] = '1431414800'
  452. data['issue']['last_updated'] = '1431414800'
  453. self.assertDictEqual(
  454. data,
  455. {
  456. "issue": FULL_ISSUE_LIST[3],
  457. "message": "Issue created"
  458. }
  459. )
  460. # Private issue: True
  461. data = {
  462. 'title': 'test issue',
  463. 'issue_content': 'This issue needs attention',
  464. 'private': True,
  465. }
  466. output = self.app.post(
  467. '/api/0/test/new_issue', data=data, headers=headers)
  468. self.assertEqual(output.status_code, 200)
  469. data = json.loads(output.data)
  470. data['issue']['date_created'] = '1431414800'
  471. data['issue']['last_updated'] = '1431414800'
  472. self.assertDictEqual(
  473. data,
  474. {
  475. "issue": FULL_ISSUE_LIST[2],
  476. "message": "Issue created"
  477. }
  478. )
  479. # Private issue: 1
  480. data = {
  481. 'title': 'test issue1',
  482. 'issue_content': 'This issue needs attention',
  483. 'private': 1,
  484. }
  485. output = self.app.post(
  486. '/api/0/test/new_issue', data=data, headers=headers)
  487. self.assertEqual(output.status_code, 200)
  488. data = json.loads(output.data)
  489. data['issue']['date_created'] = '1431414800'
  490. data['issue']['last_updated'] = '1431414800'
  491. exp = FULL_ISSUE_LIST[1]
  492. exp['id'] = 8
  493. self.assertDictEqual(
  494. data,
  495. {
  496. "issue": exp,
  497. "message": "Issue created"
  498. }
  499. )
  500. def test_api_new_issue_user_token(self):
  501. """ Test the api_new_issue method of the flask api. """
  502. tests.create_projects(self.session)
  503. tests.create_projects_git(
  504. os.path.join(self.path, 'tickets'), bare=True)
  505. tests.create_tokens(self.session, project_id=None)
  506. tests.create_tokens_acl(self.session)
  507. headers = {'Authorization': 'token aaabbbcccddd'}
  508. # Valid token, invalid request - No input
  509. output = self.app.post('/api/0/test2/new_issue', headers=headers)
  510. self.assertEqual(output.status_code, 400)
  511. data = json.loads(output.data)
  512. self.assertDictEqual(
  513. data,
  514. {
  515. "error": "Invalid or incomplete input submited",
  516. "error_code": "EINVALIDREQ",
  517. "errors": {
  518. "issue_content": ["This field is required."],
  519. "title": ["This field is required."],
  520. }
  521. }
  522. )
  523. # Another project, still an invalid request - No input
  524. output = self.app.post('/api/0/test/new_issue', headers=headers)
  525. self.assertEqual(output.status_code, 400)
  526. data = json.loads(output.data)
  527. self.assertDictEqual(
  528. data,
  529. {
  530. "error": "Invalid or incomplete input submited",
  531. "error_code": "EINVALIDREQ",
  532. "errors": {
  533. "issue_content": ["This field is required."],
  534. "title": ["This field is required."],
  535. }
  536. }
  537. )
  538. data = {
  539. 'title': 'test issue'
  540. }
  541. # Invalid repo
  542. output = self.app.post(
  543. '/api/0/foo/new_issue', data=data, headers=headers)
  544. self.assertEqual(output.status_code, 404)
  545. data = json.loads(output.data)
  546. self.assertDictEqual(
  547. data,
  548. {
  549. "error": "Project not found",
  550. "error_code": "ENOPROJECT",
  551. }
  552. )
  553. # Incomplete request
  554. output = self.app.post(
  555. '/api/0/test/new_issue', data=data, headers=headers)
  556. self.assertEqual(output.status_code, 400)
  557. data = json.loads(output.data)
  558. self.assertDictEqual(
  559. data,
  560. {
  561. "error": "Invalid or incomplete input submited",
  562. "error_code": "EINVALIDREQ",
  563. "errors": {
  564. "issue_content": ["This field is required."],
  565. "title": ["This field is required."]
  566. }
  567. }
  568. )
  569. data = {
  570. 'title': 'test issue',
  571. 'issue_content': 'This issue needs attention',
  572. }
  573. # Valid request
  574. output = self.app.post(
  575. '/api/0/test/new_issue', data=data, headers=headers)
  576. self.assertEqual(output.status_code, 200)
  577. data = json.loads(output.data)
  578. data['issue']['date_created'] = '1431414800'
  579. data['issue']['last_updated'] = '1431414800'
  580. self.assertDictEqual(
  581. data,
  582. {
  583. "issue": FULL_ISSUE_LIST[8],
  584. "message": "Issue created"
  585. }
  586. )
  587. # Valid request with milestone
  588. data = {
  589. 'title': 'test issue',
  590. 'issue_content': 'This issue needs attention',
  591. 'milestone': ['milestone-1.0'],
  592. }
  593. output = self.app.post(
  594. '/api/0/test/new_issue', data=data, headers=headers)
  595. self.assertEqual(output.status_code, 200)
  596. data = json.loads(output.data)
  597. data['issue']['date_created'] = '1431414800'
  598. data['issue']['last_updated'] = '1431414800'
  599. self.assertDictEqual(
  600. data,
  601. {
  602. "issue": FULL_ISSUE_LIST[7],
  603. "message": "Issue created"
  604. }
  605. )
  606. # Valid request, with private='false'
  607. data = {
  608. 'title': 'test issue',
  609. 'issue_content': 'This issue needs attention',
  610. 'private': 'false',
  611. }
  612. output = self.app.post(
  613. '/api/0/test/new_issue', data=data, headers=headers)
  614. self.assertEqual(output.status_code, 200)
  615. data = json.loads(output.data)
  616. data['issue']['date_created'] = '1431414800'
  617. data['issue']['last_updated'] = '1431414800'
  618. self.assertDictEqual(
  619. data,
  620. {
  621. "issue": FULL_ISSUE_LIST[6],
  622. "message": "Issue created"
  623. }
  624. )
  625. # Valid request, with private=False
  626. data = {
  627. 'title': 'test issue',
  628. 'issue_content': 'This issue needs attention',
  629. 'private': False
  630. }
  631. output = self.app.post(
  632. '/api/0/test/new_issue', data=data, headers=headers)
  633. self.assertEqual(output.status_code, 200)
  634. data = json.loads(output.data)
  635. data['issue']['date_created'] = '1431414800'
  636. data['issue']['last_updated'] = '1431414800'
  637. self.assertDictEqual(
  638. data,
  639. {
  640. "issue": FULL_ISSUE_LIST[5],
  641. "message": "Issue created"
  642. }
  643. )
  644. # Valid request, with private='False'
  645. data = {
  646. 'title': 'test issue',
  647. 'issue_content': 'This issue needs attention',
  648. 'private': 'False'
  649. }
  650. output = self.app.post(
  651. '/api/0/test/new_issue', data=data, headers=headers)
  652. self.assertEqual(output.status_code, 200)
  653. data = json.loads(output.data)
  654. data['issue']['date_created'] = '1431414800'
  655. data['issue']['last_updated'] = '1431414800'
  656. self.assertDictEqual(
  657. data,
  658. {
  659. "issue": FULL_ISSUE_LIST[4],
  660. "message": "Issue created"
  661. }
  662. )
  663. # Valid request, with private=0
  664. data = {
  665. 'title': 'test issue',
  666. 'issue_content': 'This issue needs attention',
  667. 'private': 0
  668. }
  669. output = self.app.post(
  670. '/api/0/test/new_issue', data=data, headers=headers)
  671. self.assertEqual(output.status_code, 200)
  672. data = json.loads(output.data)
  673. data['issue']['date_created'] = '1431414800'
  674. data['issue']['last_updated'] = '1431414800'
  675. self.assertDictEqual(
  676. data,
  677. {
  678. "issue": FULL_ISSUE_LIST[3],
  679. "message": "Issue created"
  680. }
  681. )
  682. # Private issue: True
  683. data = {
  684. 'title': 'test issue',
  685. 'issue_content': 'This issue needs attention',
  686. 'private': True,
  687. }
  688. output = self.app.post(
  689. '/api/0/test/new_issue', data=data, headers=headers)
  690. self.assertEqual(output.status_code, 200)
  691. data = json.loads(output.data)
  692. data['issue']['date_created'] = '1431414800'
  693. data['issue']['last_updated'] = '1431414800'
  694. self.assertDictEqual(
  695. data,
  696. {
  697. "issue": FULL_ISSUE_LIST[2],
  698. "message": "Issue created"
  699. }
  700. )
  701. # Private issue: 1
  702. data = {
  703. 'title': 'test issue1',
  704. 'issue_content': 'This issue needs attention',
  705. 'private': 1,
  706. }
  707. output = self.app.post(
  708. '/api/0/test/new_issue', data=data, headers=headers)
  709. self.assertEqual(output.status_code, 200)
  710. data = json.loads(output.data)
  711. data['issue']['date_created'] = '1431414800'
  712. data['issue']['last_updated'] = '1431414800'
  713. self.assertDictEqual(
  714. data,
  715. {
  716. "issue": FULL_ISSUE_LIST[1],
  717. "message": "Issue created"
  718. }
  719. )
  720. # Private issue: 'true'
  721. data = {
  722. 'title': 'test issue1',
  723. 'issue_content': 'This issue needs attention',
  724. 'private': 'true',
  725. }
  726. output = self.app.post(
  727. '/api/0/test/new_issue', data=data, headers=headers)
  728. self.assertEqual(output.status_code, 200)
  729. data = json.loads(output.data)
  730. data['issue']['date_created'] = '1431414800'
  731. data['issue']['last_updated'] = '1431414800'
  732. exp = FULL_ISSUE_LIST[1]
  733. exp['id'] = 9
  734. self.assertDictEqual(
  735. data,
  736. {
  737. "issue": exp,
  738. "message": "Issue created"
  739. }
  740. )
  741. def test_api_view_issues(self):
  742. """ Test the api_view_issues method of the flask api. """
  743. self.test_api_new_issue()
  744. # Invalid repo
  745. output = self.app.get('/api/0/foo/issues')
  746. self.assertEqual(output.status_code, 404)
  747. data = json.loads(output.data)
  748. self.assertDictEqual(
  749. data,
  750. {
  751. "error": "Project not found",
  752. "error_code": "ENOPROJECT",
  753. }
  754. )
  755. # List all opened issues
  756. output = self.app.get('/api/0/test/issues')
  757. self.assertEqual(output.status_code, 200)
  758. data = json.loads(output.data)
  759. for idx in range(len(data['issues'])):
  760. data['issues'][idx]['date_created'] = '1431414800'
  761. data['issues'][idx]['last_updated'] = '1431414800'
  762. self.assertDictEqual(
  763. data,
  764. {
  765. "args": {
  766. "assignee": None,
  767. "author": None,
  768. 'milestones': [],
  769. 'no_stones': None,
  770. 'priority': None,
  771. "since": None,
  772. "status": None,
  773. "tags": [],
  774. },
  775. "issues": FULL_ISSUE_LIST[3:],
  776. "total_issues": 6
  777. }
  778. )
  779. # Create private issue
  780. repo = pagure.get_authorized_project(self.session, 'test')
  781. msg = pagure.lib.new_issue(
  782. session=self.session,
  783. repo=repo,
  784. title='Test issue',
  785. content='We should work on this',
  786. user='pingou',
  787. ticketfolder=None,
  788. private=True,
  789. milestone=""
  790. )
  791. self.session.commit()
  792. self.assertEqual(msg.title, 'Test issue')
  793. # Access issues un-authenticated
  794. output = self.app.get('/api/0/test/issues')
  795. self.assertEqual(output.status_code, 200)
  796. data = json.loads(output.data)
  797. for idx in range(len(data['issues'])):
  798. data['issues'][idx]['date_created'] = '1431414800'
  799. data['issues'][idx]['last_updated'] = '1431414800'
  800. self.assertDictEqual(
  801. data,
  802. {
  803. "args": {
  804. "assignee": None,
  805. "author": None,
  806. 'milestones': [],
  807. 'no_stones': None,
  808. 'priority': None,
  809. "since": None,
  810. "status": None,
  811. "tags": []
  812. },
  813. "issues": FULL_ISSUE_LIST[3:],
  814. "total_issues": 6
  815. }
  816. )
  817. headers = {'Authorization': 'token aaabbbccc'}
  818. # Access issues authenticated but non-existing token
  819. output = self.app.get('/api/0/test/issues', headers=headers)
  820. self.assertEqual(output.status_code, 401)
  821. # Create a new token for another user
  822. item = pagure.lib.model.Token(
  823. id='bar_token',
  824. user_id=2,
  825. project_id=1,
  826. expiration=datetime.datetime.utcnow() + datetime.timedelta(
  827. days=30)
  828. )
  829. self.session.add(item)
  830. headers = {'Authorization': 'token bar_token'}
  831. # Access issues authenticated but wrong token
  832. output = self.app.get('/api/0/test/issues', headers=headers)
  833. self.assertEqual(output.status_code, 200)
  834. data = json.loads(output.data)
  835. for idx in range(len(data['issues'])):
  836. data['issues'][idx]['date_created'] = '1431414800'
  837. data['issues'][idx]['last_updated'] = '1431414800'
  838. self.assertDictEqual(
  839. data,
  840. {
  841. "args": {
  842. "assignee": None,
  843. "author": None,
  844. 'milestones': [],
  845. 'no_stones': None,
  846. 'priority': None,
  847. "since": None,
  848. "status": None,
  849. "tags": []
  850. },
  851. "issues": FULL_ISSUE_LIST[3:],
  852. "total_issues": 6
  853. }
  854. )
  855. headers = {'Authorization': 'token aaabbbcccddd'}
  856. # Access issues authenticated correctly
  857. output = self.app.get('/api/0/test/issues', headers=headers)
  858. self.assertEqual(output.status_code, 200)
  859. data = json.loads(output.data)
  860. for idx in range(len(data['issues'])):
  861. data['issues'][idx]['date_created'] = '1431414800'
  862. data['issues'][idx]['last_updated'] = '1431414800'
  863. self.assertDictEqual(
  864. data,
  865. {
  866. "args": {
  867. "assignee": None,
  868. "author": None,
  869. 'milestones': [],
  870. 'no_stones': None,
  871. 'priority': None,
  872. "since": None,
  873. "status": None,
  874. "tags": []
  875. },
  876. "issues": FULL_ISSUE_LIST,
  877. "total_issues": 9
  878. }
  879. )
  880. headers = {'Authorization': 'token aaabbbccc'}
  881. # Access issues authenticated but non-existing token
  882. output = self.app.get('/api/0/test/issues', headers=headers)
  883. self.assertEqual(output.status_code, 401)
  884. # Create a new token for another user
  885. item = pagure.lib.model.Token(
  886. id='bar_token',
  887. user_id=2,
  888. project_id=1,
  889. expiration=datetime.datetime.utcnow() + datetime.timedelta(
  890. days=30)
  891. )
  892. self.session.add(item)
  893. headers = {'Authorization': 'token bar_token'}
  894. # Access issues authenticated but wrong token
  895. output = self.app.get('/api/0/test/issues', headers=headers)
  896. self.assertEqual(output.status_code, 200)
  897. data = json.loads(output.data)
  898. for idx in range(len(data['issues'])):
  899. data['issues'][idx]['date_created'] = '1431414800'
  900. data['issues'][idx]['last_updated'] = '1431414800'
  901. self.assertDictEqual(
  902. data,
  903. {
  904. "args": {
  905. "assignee": None,
  906. "author": None,
  907. 'milestones': [],
  908. 'no_stones': None,
  909. 'priority': None,
  910. "since": None,
  911. "status": None,
  912. "tags": []
  913. },
  914. "issues": FULL_ISSUE_LIST[3:],
  915. "total_issues": 6
  916. }
  917. )
  918. headers = {'Authorization': 'token aaabbbcccddd'}
  919. # Access issues authenticated correctly
  920. output = self.app.get('/api/0/test/issues', headers=headers)
  921. self.assertEqual(output.status_code, 200)
  922. data = json.loads(output.data)
  923. for idx in range(len(data['issues'])):
  924. data['issues'][idx]['date_created'] = '1431414800'
  925. data['issues'][idx]['last_updated'] = '1431414800'
  926. self.assertDictEqual(
  927. data,
  928. {
  929. "args": {
  930. "assignee": None,
  931. "author": None,
  932. 'milestones': [],
  933. 'no_stones': None,
  934. 'priority': None,
  935. "since": None,
  936. "status": None,
  937. "tags": []
  938. },
  939. "issues": FULL_ISSUE_LIST,
  940. "total_issues": 9
  941. }
  942. )
  943. # List closed issue
  944. output = self.app.get('/api/0/test/issues?status=Closed', headers=headers)
  945. self.assertEqual(output.status_code, 200)
  946. data = json.loads(output.data)
  947. self.assertDictEqual(
  948. data,
  949. {
  950. "args": {
  951. "assignee": None,
  952. "author": None,
  953. 'milestones': [],
  954. 'no_stones': None,
  955. 'priority': None,
  956. "since": None,
  957. "status": "Closed",
  958. "tags": []
  959. },
  960. "total_issues": 0,
  961. "issues": []
  962. }
  963. )
  964. # List closed issue
  965. output = self.app.get('/api/0/test/issues?status=Invalid', headers=headers)
  966. self.assertEqual(output.status_code, 200)
  967. data = json.loads(output.data)
  968. self.assertDictEqual(
  969. data,
  970. {
  971. "args": {
  972. "assignee": None,
  973. "author": None,
  974. 'milestones': [],
  975. 'no_stones': None,
  976. 'priority': None,
  977. "since": None,
  978. "status": "Invalid",
  979. "tags": []
  980. },
  981. "total_issues": 0,
  982. "issues": []
  983. }
  984. )
  985. # List all issues
  986. output = self.app.get('/api/0/test/issues?status=All', headers=headers)
  987. self.assertEqual(output.status_code, 200)
  988. data = json.loads(output.data)
  989. for idx in range(len(data['issues'])):
  990. data['issues'][idx]['last_updated'] = '1431414800'
  991. data['issues'][idx]['date_created'] = '1431414800'
  992. self.assertDictEqual(
  993. data,
  994. {
  995. "args": {
  996. "assignee": None,
  997. "author": None,
  998. 'milestones': [],
  999. 'no_stones': None,
  1000. 'priority': None,
  1001. "since": None,
  1002. "status": "All",
  1003. "tags": []
  1004. },
  1005. "issues": FULL_ISSUE_LIST,
  1006. "total_issues": 9
  1007. }
  1008. )
  1009. def test_api_view_issues_milestone(self):
  1010. """ Test the api_view_issues method of the flask api when filtering
  1011. for a milestone.
  1012. """
  1013. tests.create_projects(self.session)
  1014. tests.create_projects_git(
  1015. os.path.join(self.path, 'tickets'), bare=True)
  1016. tests.create_tokens(self.session)
  1017. tests.create_tokens_acl(self.session)
  1018. repo = pagure.get_authorized_project(self.session, 'test')
  1019. # Create 2 tickets but only 1 has a milestone
  1020. start = datetime.datetime.utcnow().strftime('%s')
  1021. issue = pagure.lib.model.Issue(
  1022. id=pagure.lib.get_next_id(self.session, repo.id),
  1023. project_id=repo.id,
  1024. title='Issue #1',
  1025. content='Description',
  1026. user_id=1, # pingou
  1027. uid='issue#1',
  1028. private=False,
  1029. )
  1030. self.session.add(issue)
  1031. self.session.commit()
  1032. issue = pagure.lib.model.Issue(
  1033. id=pagure.lib.get_next_id(self.session, repo.id),
  1034. project_id=repo.id,
  1035. title='Issue #2',
  1036. content='Description',
  1037. user_id=1, # pingou
  1038. uid='issue#2',
  1039. private=False,
  1040. milestone='v1.0',
  1041. )
  1042. self.session.add(issue)
  1043. self.session.commit()
  1044. # List all opened issues
  1045. output = self.app.get('/api/0/test/issues')
  1046. self.assertEqual(output.status_code, 200)
  1047. data = json.loads(output.data)
  1048. for idx in range(len(data['issues'])):
  1049. data['issues'][idx]['date_created'] = '1431414800'
  1050. data['issues'][idx]['last_updated'] = '1431414800'
  1051. lcl_issues = copy.deepcopy(LCL_ISSUES)
  1052. lcl_issues[0]['milestone'] = 'v1.0'
  1053. self.assertDictEqual(
  1054. data,
  1055. {
  1056. "args": {
  1057. "assignee": None,
  1058. "author": None,
  1059. 'milestones': [],
  1060. 'no_stones': None,
  1061. 'priority': None,
  1062. "since": None,
  1063. "status": None,
  1064. "tags": [],
  1065. },
  1066. "issues": lcl_issues,
  1067. "total_issues": 2
  1068. }
  1069. )
  1070. # List all issues of the milestone v1.0
  1071. output = self.app.get('/api/0/test/issues?milestones=v1.0')
  1072. self.assertEqual(output.status_code, 200)
  1073. data = json.loads(output.data)
  1074. for idx in range(len(data['issues'])):
  1075. data['issues'][idx]['date_created'] = '1431414800'
  1076. data['issues'][idx]['last_updated'] = '1431414800'
  1077. self.assertDictEqual(
  1078. data,
  1079. {
  1080. "args": {
  1081. "assignee": None,
  1082. "author": None,
  1083. 'milestones': ['v1.0'],
  1084. 'no_stones': None,
  1085. 'priority': None,
  1086. "since": None,
  1087. "status": None,
  1088. "tags": [],
  1089. },
  1090. "issues": [lcl_issues[0]],
  1091. "total_issues": 1
  1092. }
  1093. )
  1094. def test_api_view_issues_priority(self):
  1095. """ Test the api_view_issues method of the flask api when filtering
  1096. for a priority.
  1097. """
  1098. tests.create_projects(self.session)
  1099. tests.create_projects_git(
  1100. os.path.join(self.path, 'tickets'), bare=True)
  1101. tests.create_tokens(self.session)
  1102. tests.create_tokens_acl(self.session)
  1103. repo = pagure.get_authorized_project(self.session, 'test')
  1104. # Create 2 tickets but only 1 has a priority
  1105. start = datetime.datetime.utcnow().strftime('%s')
  1106. issue = pagure.lib.model.Issue(
  1107. id=pagure.lib.get_next_id(self.session, repo.id),
  1108. project_id=repo.id,
  1109. title='Issue #1',
  1110. content='Description',
  1111. user_id=1, # pingou
  1112. uid='issue#1',
  1113. private=False,
  1114. )
  1115. self.session.add(issue)
  1116. self.session.commit()
  1117. issue = pagure.lib.model.Issue(
  1118. id=pagure.lib.get_next_id(self.session, repo.id),
  1119. project_id=repo.id,
  1120. title='Issue #2',
  1121. content='Description',
  1122. user_id=1, # pingou
  1123. uid='issue#2',
  1124. private=False,
  1125. priority=1,
  1126. )
  1127. self.session.add(issue)
  1128. self.session.commit()
  1129. # Set some priorities to the project
  1130. repo.priorities = {'1': 'High', '2': 'Normal'}
  1131. self.session.add(repo)
  1132. self.session.commit()
  1133. # List all opened issues
  1134. output = self.app.get('/api/0/test/issues')
  1135. self.assertEqual(output.status_code, 200)
  1136. data = json.loads(output.data)
  1137. for idx in range(len(data['issues'])):
  1138. data['issues'][idx]['date_created'] = '1431414800'
  1139. data['issues'][idx]['last_updated'] = '1431414800'
  1140. lcl_issues = copy.deepcopy(LCL_ISSUES)
  1141. lcl_issues[0]['priority'] = 1
  1142. self.assertDictEqual(
  1143. data,
  1144. {
  1145. "args": {
  1146. "assignee": None,
  1147. "author": None,
  1148. 'milestones': [],
  1149. 'no_stones': None,
  1150. 'priority': None,
  1151. "since": None,
  1152. "status": None,
  1153. "tags": [],
  1154. },
  1155. "issues": lcl_issues,
  1156. "total_issues": 2
  1157. }
  1158. )
  1159. # List all issues of the priority high (ie: 1)
  1160. output = self.app.get('/api/0/test/issues?priority=high')
  1161. self.assertEqual(output.status_code, 200)
  1162. data = json.loads(output.data)
  1163. for idx in range(len(data['issues'])):
  1164. data['issues'][idx]['date_created'] = '1431414800'
  1165. data['issues'][idx]['last_updated'] = '1431414800'
  1166. self.assertDictEqual(
  1167. data,
  1168. {
  1169. "args": {
  1170. "assignee": None,
  1171. "author": None,
  1172. 'milestones': [],
  1173. 'no_stones': None,
  1174. 'priority': 'high',
  1175. "since": None,
  1176. "status": None,
  1177. "tags": [],
  1178. },
  1179. "issues": [lcl_issues[0]],
  1180. "total_issues": 1
  1181. }
  1182. )
  1183. output = self.app.get('/api/0/test/issues?priority=1')
  1184. self.assertEqual(output.status_code, 200)
  1185. data = json.loads(output.data)
  1186. for idx in range(len(data['issues'])):
  1187. data['issues'][idx]['date_created'] = '1431414800'
  1188. data['issues'][idx]['last_updated'] = '1431414800'
  1189. self.assertDictEqual(
  1190. data,
  1191. {
  1192. "args": {
  1193. "assignee": None,
  1194. "author": None,
  1195. 'milestones': [],
  1196. 'no_stones': None,
  1197. 'priority': '1',
  1198. "since": None,
  1199. "status": None,
  1200. "tags": [],
  1201. },
  1202. "issues": [lcl_issues[0]],
  1203. "total_issues": 1
  1204. }
  1205. )
  1206. def test_api_view_issues_priority_invalid(self):
  1207. """ Test the api_view_issues method of the flask api when filtering
  1208. for an invalid priority.
  1209. """
  1210. tests.create_projects(self.session)
  1211. tests.create_projects_git(
  1212. os.path.join(self.path, 'tickets'), bare=True)
  1213. tests.create_tokens(self.session)
  1214. tests.create_tokens_acl(self.session)
  1215. # Try getting issues with an invalid priority
  1216. output = self.app.get('/api/0/test/issues?priority=foobar')
  1217. self.assertEqual(output.status_code, 400)
  1218. data = json.loads(output.data)
  1219. self.assertDictEqual(
  1220. data,
  1221. {
  1222. "error": "Invalid priority submitted",
  1223. "error_code": "EINVALIDPRIORITY"
  1224. }
  1225. )
  1226. def test_api_view_issues_no_stones(self):
  1227. """ Test the api_view_issues method of the flask api when filtering
  1228. with no_stones.
  1229. """
  1230. tests.create_projects(self.session)
  1231. tests.create_projects_git(
  1232. os.path.join(self.path, 'tickets'), bare=True)
  1233. tests.create_tokens(self.session)
  1234. tests.create_tokens_acl(self.session)
  1235. repo = pagure.get_authorized_project(self.session, 'test')
  1236. # Create 2 tickets but only 1 has a milestone
  1237. start = datetime.datetime.utcnow().strftime('%s')
  1238. issue = pagure.lib.model.Issue(
  1239. id=pagure.lib.get_next_id(self.session, repo.id),
  1240. project_id=repo.id,
  1241. title='Issue #1',
  1242. content='Description',
  1243. user_id=1, # pingou
  1244. uid='issue#1',
  1245. private=False,
  1246. )
  1247. self.session.add(issue)
  1248. self.session.commit()
  1249. issue = pagure.lib.model.Issue(
  1250. id=pagure.lib.get_next_id(self.session, repo.id),
  1251. project_id=repo.id,
  1252. title='Issue #2',
  1253. content='Description',
  1254. user_id=1, # pingou
  1255. uid='issue#2',
  1256. private=False,
  1257. milestone='v1.0',
  1258. )
  1259. self.session.add(issue)
  1260. self.session.commit()
  1261. # List all opened issues
  1262. output = self.app.get('/api/0/test/issues')
  1263. self.assertEqual(output.status_code, 200)
  1264. data = json.loads(output.data)
  1265. for idx in range(len(data['issues'])):
  1266. data['issues'][idx]['date_created'] = '1431414800'
  1267. data['issues'][idx]['last_updated'] = '1431414800'
  1268. lcl_issues = copy.deepcopy(LCL_ISSUES)
  1269. lcl_issues[0]['milestone'] = 'v1.0'
  1270. self.assertDictEqual(
  1271. data,
  1272. {
  1273. "args": {
  1274. "assignee": None,
  1275. "author": None,
  1276. 'milestones': [],
  1277. 'no_stones': None,
  1278. 'priority': None,
  1279. "since": None,
  1280. "status": None,
  1281. "tags": [],
  1282. },
  1283. "issues": lcl_issues,
  1284. "total_issues": 2
  1285. }
  1286. )
  1287. # List all issues with no milestone
  1288. output = self.app.get('/api/0/test/issues?no_stones=1')
  1289. self.assertEqual(output.status_code, 200)
  1290. data = json.loads(output.data)
  1291. for idx in range(len(data['issues'])):
  1292. data['issues'][idx]['date_created'] = '1431414800'
  1293. data['issues'][idx]['last_updated'] = '1431414800'
  1294. self.assertDictEqual(
  1295. data,
  1296. {
  1297. "args": {
  1298. "assignee": None,
  1299. "author": None,
  1300. 'milestones': [],
  1301. 'no_stones': True,
  1302. 'priority': None,
  1303. "since": None,
  1304. "status": None,
  1305. "tags": [],
  1306. },
  1307. "issues": [lcl_issues[1]],
  1308. "total_issues": 1
  1309. }
  1310. )
  1311. # List all issues with a milestone
  1312. output = self.app.get('/api/0/test/issues?no_stones=0')
  1313. self.assertEqual(output.status_code, 200)
  1314. data = json.loads(output.data)
  1315. for idx in range(len(data['issues'])):
  1316. data['issues'][idx]['date_created'] = '1431414800'
  1317. data['issues'][idx]['last_updated'] = '1431414800'
  1318. self.assertDictEqual(
  1319. data,
  1320. {
  1321. "args": {
  1322. "assignee": None,
  1323. "author": None,
  1324. 'milestones': [],
  1325. 'no_stones': False,
  1326. 'priority': None,
  1327. "since": None,
  1328. "status": None,
  1329. "tags": [],
  1330. },
  1331. "issues": [lcl_issues[0]],
  1332. "total_issues": 1
  1333. }
  1334. )
  1335. def test_api_view_issues_since(self):
  1336. """ Test the api_view_issues method of the flask api for since option """
  1337. tests.create_projects(self.session)
  1338. tests.create_projects_git(
  1339. os.path.join(self.path, 'tickets'), bare=True)
  1340. tests.create_tokens(self.session)
  1341. tests.create_tokens_acl(self.session)
  1342. repo = pagure.get_authorized_project(self.session, 'test')
  1343. # Create 1st tickets
  1344. start = datetime.datetime.utcnow().strftime('%s')
  1345. issue = pagure.lib.model.Issue(
  1346. id=pagure.lib.get_next_id(self.session, repo.id),
  1347. project_id=repo.id,
  1348. title='Issue #1',
  1349. content='Description',
  1350. user_id=1, # pingou
  1351. uid='issue#1',
  1352. private=False,
  1353. )
  1354. self.session.add(issue)
  1355. self.session.commit()
  1356. time.sleep(1)
  1357. middle = datetime.datetime.utcnow().strftime('%s')
  1358. # Create 2nd tickets
  1359. issue = pagure.lib.model.Issue(
  1360. id=pagure.lib.get_next_id(self.session, repo.id),
  1361. project_id=repo.id,
  1362. title='Issue #2',
  1363. content='Description',
  1364. user_id=1, # pingou
  1365. uid='issue#2',
  1366. private=False,
  1367. )
  1368. self.session.add(issue)
  1369. self.session.commit()
  1370. time.sleep(1)
  1371. final = datetime.datetime.utcnow().strftime('%s')
  1372. # Create private issue
  1373. issue = pagure.lib.model.Issue(
  1374. id=pagure.lib.get_next_id(self.session, repo.id),
  1375. project_id=repo.id,
  1376. title='Issue #3',
  1377. content='Description',
  1378. user_id=1, # pingou
  1379. uid='issue#3',
  1380. private=True,
  1381. )
  1382. self.session.add(issue)
  1383. self.session.commit()
  1384. # Invalid repo
  1385. output = self.app.get('/api/0/foo/issues')
  1386. self.assertEqual(output.status_code, 404)
  1387. data = json.loads(output.data)
  1388. self.assertDictEqual(
  1389. data,
  1390. {
  1391. "error": "Project not found",
  1392. "error_code": "ENOPROJECT",
  1393. }
  1394. )
  1395. # List all opened issues
  1396. output = self.app.get('/api/0/test/issues')
  1397. self.assertEqual(output.status_code, 200)
  1398. data = json.loads(output.data)
  1399. for idx in range(len(data['issues'])):
  1400. data['issues'][idx]['date_created'] = '1431414800'
  1401. data['issues'][idx]['last_updated'] = '1431414800'
  1402. self.assertDictEqual(
  1403. data,
  1404. {
  1405. "args": {
  1406. "assignee": None,
  1407. "author": None,
  1408. 'milestones': [],
  1409. 'no_stones': None,
  1410. 'priority': None,
  1411. "since": None,
  1412. "status": None,
  1413. "tags": []
  1414. },
  1415. "issues": LCL_ISSUES,
  1416. "total_issues": 2
  1417. }
  1418. )
  1419. time.sleep(1)
  1420. late = datetime.datetime.utcnow().strftime('%s')
  1421. # List all opened issues from the start
  1422. output = self.app.get('/api/0/test/issues?since=%s' % start)
  1423. self.assertEqual(output.status_code, 200)
  1424. data = json.loads(output.data)
  1425. for idx in range(len(data['issues'])):
  1426. data['issues'][idx]['date_created'] = '1431414800'
  1427. data['issues'][idx]['last_updated'] = '1431414800'
  1428. self.assertDictEqual(
  1429. data,
  1430. {
  1431. "args": {
  1432. "assignee": None,
  1433. "author": None,
  1434. 'milestones': [],
  1435. 'no_stones': None,
  1436. 'priority': None,
  1437. "since": start,
  1438. "status": None,
  1439. "tags": []
  1440. },
  1441. "issues": LCL_ISSUES,
  1442. "total_issues": 2
  1443. }
  1444. )
  1445. # List all opened issues from the middle
  1446. output = self.app.get('/api/0/test/issues?since=%s' % middle)
  1447. self.assertEqual(output.status_code, 200)
  1448. data = json.loads(output.data)
  1449. for idx in range(len(data['issues'])):
  1450. data['issues'][idx]['date_created'] = '1431414800'
  1451. data['issues'][idx]['last_updated'] = '1431414800'
  1452. self.assertDictEqual(
  1453. data,
  1454. {
  1455. "args": {
  1456. "assignee": None,
  1457. "author": None,
  1458. 'milestones': [],
  1459. 'no_stones': None,
  1460. 'priority': None,
  1461. "since": middle,
  1462. "status": None,
  1463. "tags": []
  1464. },
  1465. "issues": LCL_ISSUES[:1],
  1466. "total_issues": 1
  1467. }
  1468. )
  1469. # List all opened issues at the end
  1470. output = self.app.get('/api/0/test/issues?since=%s' % final)
  1471. self.assertEqual(output.status_code, 200)
  1472. data = json.loads(output.data)
  1473. for idx in range(len(data['issues'])):
  1474. data['issues'][idx]['date_created'] = '1431414800'
  1475. data['issues'][idx]['last_updated'] = '1431414800'
  1476. self.assertDictEqual(
  1477. data,
  1478. {
  1479. "args": {
  1480. "assignee": None,
  1481. "author": None,
  1482. 'milestones': [],
  1483. 'no_stones': None,
  1484. 'priority': None,
  1485. "since": final,
  1486. "status": None,
  1487. "tags": []
  1488. },
  1489. "issues": [],
  1490. "total_issues": 0
  1491. }
  1492. )
  1493. headers = {'Authorization': 'token aaabbbcccddd'}
  1494. # Test since for a value before creation of issues
  1495. output = self.app.get(
  1496. '/api/0/test/issues?since=%s' % final, headers=headers)
  1497. self.assertEqual(output.status_code, 200)
  1498. data = json.loads(output.data)
  1499. for idx in range(len(data['issues'])):
  1500. data['issues'][idx]['last_updated'] = '1431414800'
  1501. data['issues'][idx]['date_created'] = '1431414800'
  1502. self.assertDictEqual(
  1503. data,
  1504. {
  1505. "args": {
  1506. "assignee": None,
  1507. "author": None,
  1508. 'milestones': [],
  1509. 'no_stones': None,
  1510. 'priority': None,
  1511. "since": final,
  1512. "status": None,
  1513. "tags": []
  1514. },
  1515. "issues": [{
  1516. 'assignee': None,
  1517. 'blocks': [],
  1518. 'close_status': None,
  1519. 'closed_at': None,
  1520. 'comments': [],
  1521. 'content': 'Description',
  1522. 'custom_fields': [],
  1523. 'date_created': '1431414800',
  1524. 'depends': [],
  1525. 'id': 3,
  1526. 'last_updated': '1431414800',
  1527. 'milestone': None,
  1528. 'priority': None,
  1529. 'private': True,
  1530. 'status': 'Open',
  1531. 'tags': [],
  1532. 'title': 'Issue #3',
  1533. 'user': {'fullname': 'PY C', 'name': 'pingou'}}
  1534. ],
  1535. "total_issues": 1
  1536. }
  1537. )
  1538. def test_api_view_issue(self):
  1539. """ Test the api_view_issue method of the flask api. """
  1540. self.test_api_new_issue()
  1541. # Invalid repo
  1542. output = self.app.get('/api/0/foo/issue/1')
  1543. self.assertEqual(output.status_code, 404)
  1544. data = json.loads(output.data)
  1545. self.assertDictEqual(
  1546. data,
  1547. {
  1548. "error": "Project not found",
  1549. "error_code": "ENOPROJECT",
  1550. }
  1551. )
  1552. # Invalid issue for this repo
  1553. output = self.app.get('/api/0/test2/issue/1')
  1554. self.assertEqual(output.status_code, 404)
  1555. data = json.loads(output.data)
  1556. self.assertDictEqual(
  1557. data,
  1558. {
  1559. "error": "Issue not found",
  1560. "error_code": "ENOISSUE",
  1561. }
  1562. )
  1563. # Valid issue
  1564. output = self.app.get('/api/0/test/issue/1')
  1565. self.assertEqual(output.status_code, 200)
  1566. data = json.loads(output.data)
  1567. data['date_created'] = '1431414800'
  1568. data['last_updated'] = '1431414800'
  1569. self.assertDictEqual(
  1570. data,
  1571. {
  1572. "assignee": None,
  1573. "blocks": [],
  1574. "comments": [],
  1575. "content": "This issue needs attention",
  1576. "custom_fields": [],
  1577. "date_created": "1431414800",
  1578. "close_status": None,
  1579. "closed_at": None,
  1580. "depends": [],
  1581. "id": 1,
  1582. "last_updated": "1431414800",
  1583. "milestone": "",
  1584. "priority": None,
  1585. "private": False,
  1586. "status": "Open",
  1587. "tags": [],
  1588. "title": "test issue",
  1589. "user": {
  1590. "fullname": "PY C",
  1591. "name": "pingou"
  1592. }
  1593. }
  1594. )
  1595. # Create private issue
  1596. repo = pagure.get_authorized_project(self.session, 'test')
  1597. msg = pagure.lib.new_issue(
  1598. session=self.session,
  1599. repo=repo,
  1600. title='Test issue',
  1601. content='We should work on this',
  1602. user='pingou',
  1603. ticketfolder=None,
  1604. private=True,
  1605. issue_uid='aaabbbccc',
  1606. )
  1607. self.session.commit()
  1608. self.assertEqual(msg.title, 'Test issue')
  1609. # Access private issue un-authenticated
  1610. output = self.app.get('/api/0/test/issue/7')
  1611. self.assertEqual(output.status_code, 403)
  1612. data = json.loads(output.data)
  1613. self.assertDictEqual(
  1614. data,
  1615. {
  1616. "error": "You are not allowed to view this issue",
  1617. "error_code": "EISSUENOTALLOWED",
  1618. }
  1619. )
  1620. headers = {'Authorization': 'token aaabbbccc'}
  1621. # Access private issue authenticated but non-existing token
  1622. output = self.app.get('/api/0/test/issue/6', headers=headers)
  1623. self.assertEqual(output.status_code, 401)
  1624. data = json.loads(output.data)
  1625. self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.name,
  1626. data['error_code'])
  1627. self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.value, data['error'])
  1628. # Create a new token for another user
  1629. item = pagure.lib.model.Token(
  1630. id='bar_token',
  1631. user_id=2,
  1632. project_id=1,
  1633. expiration=datetime.datetime.utcnow() + datetime.timedelta(
  1634. days=30)
  1635. )
  1636. self.session.add(item)
  1637. headers = {'Authorization': 'token bar_token'}
  1638. # Access private issue authenticated but wrong token
  1639. output = self.app.get('/api/0/test/issue/7', headers=headers)
  1640. self.assertEqual(output.status_code, 403)
  1641. data = json.loads(output.data)
  1642. self.assertDictEqual(
  1643. data,
  1644. {
  1645. "error": "You are not allowed to view this issue",
  1646. "error_code": "EISSUENOTALLOWED",
  1647. }
  1648. )
  1649. headers = {'Authorization': 'token aaabbbcccddd'}
  1650. # Access private issue authenticated correctly
  1651. output = self.app.get('/api/0/test/issue/6', headers=headers)
  1652. self.assertEqual(output.status_code, 200)
  1653. data = json.loads(output.data)
  1654. data['date_created'] = '1431414800'
  1655. data['last_updated'] = '1431414800'
  1656. self.assertDictEqual(
  1657. data,
  1658. {
  1659. "assignee": None,
  1660. "blocks": [],
  1661. "comments": [],
  1662. "content": "This issue needs attention",
  1663. "custom_fields": [],
  1664. "date_created": "1431414800",
  1665. "close_status": None,
  1666. "closed_at": None,
  1667. "depends": [],
  1668. "id": 6,
  1669. "last_updated": "1431414800",
  1670. "milestone": "",
  1671. "priority": None,
  1672. "private": False,
  1673. "status": "Open",
  1674. "tags": [],
  1675. "title": "test issue",
  1676. "user": {
  1677. "fullname": "PY C",
  1678. "name": "pingou"
  1679. }
  1680. }
  1681. )
  1682. # Access private issue authenticated correctly using the issue's uid
  1683. output = self.app.get('/api/0/test/issue/aaabbbccc', headers=headers)
  1684. self.assertEqual(output.status_code, 200)
  1685. data = json.loads(output.data)
  1686. data['date_created'] = '1431414800'
  1687. data['last_updated'] = '1431414800'
  1688. self.assertDictEqual(
  1689. data,
  1690. {
  1691. "assignee": None,
  1692. "blocks": [],
  1693. "comments": [],
  1694. "content": "We should work on this",
  1695. "custom_fields": [],
  1696. "date_created": "1431414800",
  1697. "close_status": None,
  1698. "closed_at": None,
  1699. "depends": [],
  1700. "id": 9,
  1701. "last_updated": "1431414800",
  1702. "milestone": None,
  1703. "priority": None,
  1704. "private": True,
  1705. "status": "Open",
  1706. "tags": [],
  1707. "title": "Test issue",
  1708. "user": {
  1709. "fullname": "PY C",
  1710. "name": "pingou"
  1711. }
  1712. }
  1713. )
  1714. def test_api_change_milestone_issue(self):
  1715. """ Test the api_change_milestone_issue method of the flask api. """
  1716. tests.create_projects(self.session)
  1717. tests.create_projects_git(os.path.join(self.path, 'tickets'))
  1718. tests.create_tokens(self.session)
  1719. tests.create_tokens_acl(self.session)
  1720. # Set some milestones to the project
  1721. repo = pagure.get_authorized_project(self.session, 'test')
  1722. repo.milestones = {'v1.0': None, 'v2.0': 'Soon'}
  1723. self.session.add(repo)
  1724. self.session.commit()
  1725. headers = {'Authorization': 'token aaabbbcccddd'}
  1726. # Invalid project
  1727. output = self.app.post('/api/0/foo/issue/1/milestone', headers=headers)
  1728. self.assertEqual(output.status_code, 404)
  1729. data = json.loads(output.data)
  1730. self.assertDictEqual(
  1731. data,
  1732. {
  1733. "error": "Project not found",
  1734. "error_code": "ENOPROJECT",
  1735. }
  1736. )
  1737. # Valid token, wrong project
  1738. output = self.app.post('/api/0/test2/issue/1/milestone', headers=headers)
  1739. self.assertEqual(output.status_code, 401)
  1740. data = json.loads(output.data)
  1741. self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.name,
  1742. data['error_code'])
  1743. self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.value, data['error'])
  1744. # No issue
  1745. output = self.app.post('/api/0/test/issue/1/milestone', headers=headers)
  1746. self.assertEqual(output.status_code, 404)
  1747. data = json.loads(output.data)
  1748. self.assertDictEqual(
  1749. data,
  1750. {
  1751. "error": "Issue not found",
  1752. "error_code": "ENOISSUE",
  1753. }
  1754. )
  1755. # Create normal issue
  1756. repo = pagure.get_authorized_project(self.session, 'test')
  1757. msg = pagure.lib.new_issue(
  1758. session=self.session,
  1759. repo=repo,
  1760. title='Test issue #1',
  1761. content='We should work on this',
  1762. user='pingou',
  1763. ticketfolder=None,
  1764. private=False,
  1765. )
  1766. self.session.commit()
  1767. self.assertEqual(msg.title, 'Test issue #1')
  1768. # Check milestone before
  1769. repo = pagure.get_authorized_project(self.session, 'test')
  1770. issue = pagure.lib.search_issues(self.session, repo, issueid=1)
  1771. self.assertEqual(issue.milestone, None)
  1772. data = {
  1773. 'milestone': '',
  1774. }
  1775. # Valid request but no milestone specified
  1776. output = self.app.post(
  1777. '/api/0/test/issue/1/milestone', data=data, headers=headers)
  1778. self.assertEqual(output.status_code, 200)
  1779. data = json.loads(output.data)
  1780. self.assertDictEqual(
  1781. data,
  1782. {'message': 'No changes'}
  1783. )
  1784. # No change
  1785. repo = pagure.get_authorized_project(self.session, 'test')
  1786. issue = pagure.lib.search_issues(self.session, repo, issueid=1)
  1787. self.assertEqual(issue.milestone, None)
  1788. data = {
  1789. 'milestone': 'milestone-1-0',
  1790. }
  1791. # Invalid milestone specified
  1792. output = self.app.post(
  1793. '/api/0/test/issue/1/milestone', data=data, headers=headers)
  1794. self.assertEqual(output.status_code, 400)
  1795. data = json.loads(output.data)
  1796. self.assertDictEqual(
  1797. data,
  1798. {
  1799. "error": "Invalid or incomplete input submited",
  1800. "error_code": "EINVALIDREQ",
  1801. "errors": {
  1802. "milestone": [
  1803. "Not a valid choice"
  1804. ]
  1805. }
  1806. }
  1807. )
  1808. data = {
  1809. 'milestone': 'v1.0',
  1810. }
  1811. # Valid requests
  1812. output = self.app.post(
  1813. '/api/0/test/issue/1/milestone', data=data, headers=headers)
  1814. self.assertEqual(output.status_code, 200)
  1815. data = json.loads(output.data)
  1816. self.assertDictEqual(
  1817. data,
  1818. {
  1819. "message": [
  1820. "Issue set to the milestone: v1.0"
  1821. ]
  1822. }
  1823. )
  1824. # remove milestone
  1825. data = {
  1826. 'milestone': '',
  1827. }
  1828. # Valid requests
  1829. output = self.app.post(
  1830. '/api/0/test/issue/1/milestone', data=data, headers=headers)
  1831. self.assertEqual(output.status_code, 200)
  1832. data = json.loads(output.data)
  1833. self.assertDictEqual(
  1834. data,
  1835. {
  1836. "message": [
  1837. "Issue set to the milestone: None (was: v1.0)"
  1838. ]
  1839. }
  1840. )
  1841. # Change recorded
  1842. repo = pagure.get_authorized_project(self.session, 'test')
  1843. issue = pagure.lib.search_issues(self.session, repo, issueid=1)
  1844. self.assertEqual(issue.milestone, None)
  1845. data = {
  1846. 'milestone': 'v1.0',
  1847. }
  1848. # Valid requests
  1849. output = self.app.post(
  1850. '/api/0/test/issue/1/milestone', data=data, headers=headers)
  1851. self.assertEqual(output.status_code, 200)
  1852. data = json.loads(output.data)
  1853. self.assertDictEqual(
  1854. data,
  1855. {
  1856. "message": [
  1857. "Issue set to the milestone: v1.0"
  1858. ]
  1859. }
  1860. )
  1861. # remove milestone by using no milestone in JSON
  1862. data = {}
  1863. # Valid requests
  1864. output = self.app.post(
  1865. '/api/0/test/issue/1/milestone', data=data, headers=headers)
  1866. self.assertEqual(output.status_code, 200)
  1867. data = json.loads(output.data)
  1868. self.assertDictEqual(
  1869. data,
  1870. {
  1871. "message": [
  1872. "Issue set to the milestone: None (was: v1.0)"
  1873. ]
  1874. }
  1875. )
  1876. # Change recorded
  1877. repo = pagure.get_authorized_project(self.session, 'test')
  1878. issue = pagure.lib.search_issues(self.session, repo, issueid=1)
  1879. self.assertEqual(issue.milestone, None)
  1880. headers = {'Authorization': 'token pingou_foo'}
  1881. # Un-authorized issue
  1882. output = self.app.post(
  1883. '/api/0/foo/issue/1/milestone', data=data, headers=headers)
  1884. self.assertEqual(output.status_code, 401)
  1885. data = json.loads(output.data)
  1886. self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.name,
  1887. data['error_code'])
  1888. self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.value, data['error'])
  1889. @patch('pagure.lib.git.update_git')
  1890. @patch('pagure.lib.notify.send_email')
  1891. def test_api_view_issue_comment(self, p_send_email, p_ugt):
  1892. """ Test the api_view_issue_comment endpoint. """
  1893. p_send_email.return_value = True
  1894. p_ugt.return_value = True
  1895. tests.create_projects(self.session)
  1896. tests.create_projects_git(os.path.join(self.path, 'tickets'))
  1897. tests.create_tokens(self.session)
  1898. tests.create_tokens_acl(self.session)
  1899. # Create normal issue in test
  1900. repo = pagure.get_authorized_project(self.session, 'test')
  1901. msg = pagure.lib.new_issue(
  1902. session=self.session,
  1903. repo=repo,
  1904. title='Test issue #1',
  1905. content='We should work on this',
  1906. user='pingou',
  1907. ticketfolder=None,
  1908. private=False,
  1909. issue_uid='aaabbbccc#1',
  1910. )
  1911. self.session.commit()
  1912. self.assertEqual(msg.title, 'Test issue #1')
  1913. headers = {'Authorization': 'token aaabbbcccddd'}
  1914. data = {
  1915. 'comment': 'This is a very interesting question',
  1916. }
  1917. # Valid request
  1918. output = self.app.post(
  1919. '/api/0/test/issue/1/comment', data=data, headers=headers)
  1920. self.assertEqual(output.status_code, 200)
  1921. data = json.loads(output.data)
  1922. self.assertDictEqual(
  1923. data,
  1924. {'message': 'Comment added'}
  1925. )
  1926. # One comment added
  1927. repo = pagure.get_authorized_project(self.session, 'test')
  1928. issue = pagure.lib.search_issues(self.session, repo, issueid=1)
  1929. self.assertEqual(len(issue.comments), 1)
  1930. # View a comment that does not exist
  1931. output = self.app.get('/api/0/foo/issue/100/comment/2')
  1932. self.assertEqual(output.status_code, 404)
  1933. # Issue exists but not the comment
  1934. output = self.app.get('/api/0/test/issue/1/comment/2')
  1935. self.assertEqual(output.status_code, 404)
  1936. # Issue and comment exists
  1937. output = self.app.get('/api/0/test/issue/1/comment/1')
  1938. self.assertEqual(output.status_code, 200)
  1939. data = json.loads(output.data)
  1940. data['date_created'] = '1435821770'
  1941. data["comment_date"] = "2015-07-02 09:22"
  1942. data["avatar_url"] = "https://seccdn.libravatar.org/avatar/..."
  1943. self.assertDictEqual(
  1944. data,
  1945. {
  1946. "avatar_url": "https://seccdn.libravatar.org/avatar/...",
  1947. "comment": "This is a very interesting question",
  1948. "comment_date": "2015-07-02 09:22",
  1949. "date_created": "1435821770",
  1950. "edited_on": None,
  1951. "editor": None,
  1952. "notification": False,
  1953. "id": 1,
  1954. "parent": None,
  1955. "user": {
  1956. "fullname": "PY C",
  1957. "name": "pingou"
  1958. }
  1959. }
  1960. )
  1961. # Issue and comment exists, using UID
  1962. output = self.app.get('/api/0/test/issue/aaabbbccc#1/comment/1')
  1963. self.assertEqual(output.status_code, 200)
  1964. data = json.loads(output.data)
  1965. data['date_created'] = '1435821770'
  1966. data["comment_date"] = "2015-07-02 09:22"
  1967. data["avatar_url"] = "https://seccdn.libravatar.org/avatar/..."
  1968. self.assertDictEqual(
  1969. data,
  1970. {
  1971. "avatar_url": "https://seccdn.libravatar.org/avatar/...",
  1972. "comment": "This is a very interesting question",
  1973. "comment_date": "2015-07-02 09:22",
  1974. "date_created": "1435821770",
  1975. "edited_on": None,
  1976. "editor": None,
  1977. "notification": False,
  1978. "id": 1,
  1979. "parent": None,
  1980. "user": {
  1981. "fullname": "PY C",
  1982. "name": "pingou"
  1983. }
  1984. }
  1985. )
  1986. @patch('pagure.lib.git.update_git')
  1987. @patch('pagure.lib.notify.send_email')
  1988. def test_api_view_issue_comment_private(self, p_send_email, p_ugt):
  1989. """ Test the api_view_issue_comment endpoint. """
  1990. p_send_email.return_value = True
  1991. p_ugt.return_value = True
  1992. tests.create_projects(self.session)
  1993. tests.create_projects_git(os.path.join(self.path, 'tickets'))
  1994. tests.create_tokens(self.session)
  1995. tests.create_tokens_acl(self.session)
  1996. # Create normal issue in test
  1997. repo = pagure.get_authorized_project(self.session, 'test')
  1998. msg = pagure.lib.new_issue(
  1999. session=self.session,
  2000. repo=repo,
  2001. title='Test issue #1',
  2002. content='We should work on this',
  2003. user='foo',
  2004. ticketfolder=None,
  2005. private=True,
  2006. issue_uid='aaabbbccc#1',
  2007. )
  2008. self.session.commit()
  2009. self.assertEqual(msg.title, 'Test issue #1')
  2010. # Create a token for another user
  2011. item = pagure.lib.model.Token(
  2012. id='foo_token_2',
  2013. user_id=2,
  2014. project_id=1,
  2015. expiration=datetime.datetime.utcnow()
  2016. + datetime.timedelta(days=30)
  2017. )
  2018. self.session.add(item)
  2019. self.session.commit()
  2020. tests.create_tokens_acl(self.session, token_id='foo_token_2')
  2021. # Add a comment to that issue
  2022. data = {
  2023. 'comment': 'This is a very interesting question',
  2024. }
  2025. headers = {'Authorization': 'token foo_token_2'}
  2026. output = self.app.post(
  2027. '/api/0/test/issue/1/comment', data=data, headers=headers)
  2028. self.assertEqual(output.status_code, 200)
  2029. data = json.loads(output.data)
  2030. self.assertDictEqual(
  2031. data,
  2032. {'message': 'Comment added'}
  2033. )
  2034. # Private issue - no auth
  2035. output = self.app.get('/api/0/test/issue/1/comment/2')
  2036. self.assertEqual(output.status_code, 403)
  2037. # Private issue - Auth - Invalid token
  2038. headers = {'Authorization': 'token aaabbbcccdddee'}
  2039. output = self.app.get('/api/0/test/issue/1/comment/2', headers=headers)
  2040. self.assertEqual(output.status_code, 401)
  2041. # Private issue - Auth - valid token - unknown comment
  2042. headers = {'Authorization': 'token foo_token_2'}
  2043. output = self.app.get('/api/0/test/issue/1/comment/3', headers=headers)
  2044. self.assertEqual(output.status_code, 404)
  2045. # Private issue - Auth - valid token - known comment
  2046. headers = {'Authorization': 'token foo_token_2'}
  2047. output = self.app.get('/api/0/test/issue/1/comment/1', headers=headers)
  2048. self.assertEqual(output.status_code, 200)
  2049. data = json.loads(output.data)
  2050. data['date_created'] = '1435821770'
  2051. data["comment_date"] = "2015-07-02 09:22"
  2052. data["avatar_url"] = "https://seccdn.libravatar.org/avatar/..."
  2053. self.assertDictEqual(
  2054. data,
  2055. {
  2056. "avatar_url": "https://seccdn.libravatar.org/avatar/...",
  2057. "comment": "This is a very interesting question",
  2058. "comment_date": "2015-07-02 09:22",
  2059. "date_created": "1435821770",
  2060. "edited_on": None,
  2061. "editor": None,
  2062. "notification": False,
  2063. "id": 1,
  2064. "parent": None,
  2065. "user": {
  2066. "fullname": "foo bar",
  2067. "name": "foo"
  2068. }
  2069. }
  2070. )
  2071. @patch('pagure.lib.git.update_git')
  2072. @patch('pagure.lib.notify.send_email')
  2073. def test_api_assign_issue(self, p_send_email, p_ugt):
  2074. """ Test the api_assign_issue method of the flask api. """
  2075. p_send_email.return_value = True
  2076. p_ugt.return_value = True
  2077. tests.create_projects(self.session)
  2078. tests.create_tokens(self.session)
  2079. tests.create_tokens_acl(self.session)
  2080. headers = {'Authorization': 'token aaabbbcccddd'}
  2081. # Invalid project
  2082. output = self.app.post('/api/0/foo/issue/1/assign', headers=headers)
  2083. self.assertEqual(output.status_code, 404)
  2084. data = json.loads(output.data)
  2085. self.assertDictEqual(
  2086. data,
  2087. {
  2088. "error": "Project not found",
  2089. "error_code": "ENOPROJECT",
  2090. }
  2091. )
  2092. # Valid token, wrong project
  2093. output = self.app.post('/api/0/test2/issue/1/assign', headers=headers)
  2094. self.assertEqual(output.status_code, 401)
  2095. data = json.loads(output.data)
  2096. self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.name,
  2097. data['error_code'])
  2098. self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.value, data['error'])
  2099. # No input
  2100. output = self.app.post('/api/0/test/issue/1/assign', headers=headers)
  2101. self.assertEqual(output.status_code, 404)
  2102. data = json.loads(output.data)
  2103. self.assertDictEqual(
  2104. data,
  2105. {
  2106. "error": "Issue not found",
  2107. "error_code": "ENOISSUE",
  2108. }
  2109. )
  2110. # Create normal issue
  2111. repo = pagure.get_authorized_project(self.session, 'test')
  2112. msg = pagure.lib.new_issue(
  2113. session=self.session,
  2114. repo=repo,
  2115. title='Test issue #1',
  2116. content='We should work on this',
  2117. user='pingou',
  2118. ticketfolder=None,
  2119. private=False,
  2120. issue_uid='aaabbbccc#1',
  2121. )
  2122. self.session.commit()
  2123. self.assertEqual(msg.title, 'Test issue #1')
  2124. # Check comments before
  2125. repo = pagure.get_authorized_project(self.session, 'test')
  2126. issue = pagure.lib.search_issues(self.session, repo, issueid=1)
  2127. self.assertEqual(len(issue.comments), 0)
  2128. # No change
  2129. repo = pagure.get_authorized_project(self.session, 'test')
  2130. issue = pagure.lib.search_issues(self.session, repo, issueid=1)
  2131. self.assertEqual(issue.status, 'Open')
  2132. data = {
  2133. 'assignee': 'pingou',
  2134. }
  2135. # Valid request
  2136. output = self.app.post(
  2137. '/api/0/test/issue/1/assign', data=data, headers=headers)
  2138. self.assertEqual(output.status_code, 200)
  2139. data = json.loads(output.data)
  2140. self.assertDictEqual(
  2141. data,
  2142. {'message': 'Issue assigned to pingou'}
  2143. )
  2144. # Un-assign
  2145. output = self.app.post(
  2146. '/api/0/test/issue/1/assign', data=data, headers=headers)
  2147. self.assertEqual(output.status_code, 200)
  2148. data = json.loads(output.data)
  2149. self.assertDictEqual(
  2150. data,
  2151. {'message': 'Assignee reset'}
  2152. )
  2153. # No change
  2154. repo = pagure.get_authorized_project(self.session, 'test')
  2155. issue = pagure.lib.search_issues(self.session, repo, issueid=1)
  2156. self.assertEqual(issue.assignee, None)
  2157. # Un-assign
  2158. data = {'assignee': None}
  2159. output = self.app.post(
  2160. '/api/0/test/issue/1/assign', data=data, headers=headers)
  2161. self.assertEqual(output.status_code, 200)
  2162. data = json.loads(output.data)
  2163. self.assertDictEqual(
  2164. data,
  2165. {'message': 'Nothing to change'}
  2166. )
  2167. repo = pagure.get_authorized_project(self.session, 'test')
  2168. issue = pagure.lib.search_issues(self.session, repo, issueid=1)
  2169. self.assertEqual(issue.assignee, None)
  2170. # Re-assign for the rest of the tests
  2171. data = {'assignee': 'pingou'}
  2172. output = self.app.post(
  2173. '/api/0/test/issue/1/assign', data=data, headers=headers)
  2174. self.assertEqual(output.status_code, 200)
  2175. data = json.loads(output.data)
  2176. self.assertDictEqual(
  2177. data,
  2178. {'message': 'Issue assigned to pingou'}
  2179. )
  2180. # Un-assign
  2181. data = {'assignee': ''}
  2182. output = self.app.post(
  2183. '/api/0/test/issue/1/assign', data=data, headers=headers)
  2184. self.assertEqual(output.status_code, 200)
  2185. data = json.loads(output.data)
  2186. self.assertDictEqual(
  2187. data,
  2188. {'message': 'Assignee reset'}
  2189. )
  2190. # Re-assign for the rest of the tests
  2191. data = {'assignee': 'pingou'}
  2192. output = self.app.post(
  2193. '/api/0/test/issue/1/assign', data=data, headers=headers)
  2194. self.assertEqual(output.status_code, 200)
  2195. data = json.loads(output.data)
  2196. self.assertDictEqual(
  2197. data,
  2198. {'message': 'Issue assigned to pingou'}
  2199. )
  2200. # One comment added
  2201. repo = pagure.get_authorized_project(self.session, 'test')
  2202. issue = pagure.lib.search_issues(self.session, repo, issueid=1)
  2203. self.assertEqual(issue.assignee.user, 'pingou')
  2204. # Create another project
  2205. item = pagure.lib.model.Project(
  2206. user_id=2, # foo
  2207. name='foo',
  2208. description='test project #3',
  2209. hook_token='aaabbbdddeee',
  2210. )
  2211. self.session.add(item)
  2212. self.session.commit()
  2213. # Create a token for pingou for this project
  2214. item = pagure.lib.model.Token(
  2215. id='pingou_foo',
  2216. user_id=1,
  2217. project_id=4,
  2218. expiration=datetime.datetime.utcnow() + datetime.timedelta(
  2219. days=30)
  2220. )
  2221. self.session.add(item)
  2222. self.session.commit()
  2223. # Give `issue_change_status` to this token when `issue_comment`
  2224. # is required
  2225. item = pagure.lib.model.TokenAcl(
  2226. token_id='pingou_foo',
  2227. acl_id=5,
  2228. )
  2229. self.session.add(item)
  2230. self.session.commit()
  2231. repo = pagure.get_authorized_project(self.session, 'foo')
  2232. # Create private issue
  2233. msg = pagure.lib.new_issue(
  2234. session=self.session,
  2235. repo=repo,
  2236. title='Test issue',
  2237. content='We should work on this',
  2238. user='foo',
  2239. ticketfolder=None,
  2240. private=True,
  2241. issue_uid='aaabbbccc#2',
  2242. )
  2243. self.session.commit()
  2244. self.assertEqual(msg.title, 'Test issue')
  2245. # Check before
  2246. repo = pagure.get_authorized_project(self.session, 'foo')
  2247. issue = pagure.lib.search_issues(self.session, repo, issueid=1)
  2248. self.assertEqual(len(issue.comments), 0)
  2249. data = {
  2250. 'assignee': 'pingou',
  2251. }
  2252. headers = {'Authorization': 'token pingou_foo'}
  2253. # Valid request but un-authorized
  2254. output = self.app.post(
  2255. '/api/0/foo/issue/1/assign', data=data, headers=headers)
  2256. self.assertEqual(output.status_code, 401)
  2257. data = json.loads(output.data)
  2258. self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.name,
  2259. data['error_code'])
  2260. self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.value, data['error'])
  2261. # No comment added
  2262. repo = pagure.get_authorized_project(self.session, 'foo')
  2263. issue = pagure.lib.search_issues(self.session, repo, issueid=1)
  2264. self.assertEqual(len(issue.comments), 0)
  2265. # Create token for user foo
  2266. item = pagure.lib.model.Token(
  2267. id='foo_token2',
  2268. user_id=2,
  2269. project_id=4,
  2270. expiration=datetime.datetime.utcnow() + datetime.timedelta(days=30)
  2271. )
  2272. self.session.add(item)
  2273. self.session.commit()
  2274. tests.create_tokens_acl(self.session, token_id='foo_token2')
  2275. data = {
  2276. 'assignee': 'pingou',
  2277. }
  2278. headers = {'Authorization': 'token foo_token2'}
  2279. # Valid request and authorized
  2280. output = self.app.post(
  2281. '/api/0/foo/issue/1/assign', data=data, headers=headers)
  2282. self.assertEqual(output.status_code, 200)
  2283. data = json.loads(output.data)
  2284. self.assertDictEqual(
  2285. data,
  2286. {'message': 'Issue assigned to pingou'}
  2287. )
  2288. @patch('pagure.lib.git.update_git')
  2289. @patch('pagure.lib.notify.send_email')
  2290. def test_api_subscribe_issue(self, p_send_email, p_ugt):
  2291. """ Test the api_subscribe_issue method of the flask api. """
  2292. p_send_email.return_value = True
  2293. p_ugt.return_value = True
  2294. item = pagure.lib.model.User(
  2295. user='bar',
  2296. fullname='bar foo',
  2297. password='foo',
  2298. default_email='bar@bar.com',
  2299. )
  2300. self.session.add(item)
  2301. item = pagure.lib.model.UserEmail(
  2302. user_id=3,
  2303. email='bar@bar.com')
  2304. self.session.add(item)
  2305. self.session.commit()
  2306. tests.create_projects(self.session)
  2307. tests.create_tokens(self.session, user_id=3)
  2308. tests.create_tokens_acl(self.session)
  2309. headers = {'Authorization': 'token aaabbbcccddd'}
  2310. # Invalid project
  2311. output = self.app.post(
  2312. '/api/0/foo/issue/1/subscribe', headers=headers)
  2313. self.assertEqual(output.status_code, 404)
  2314. data = json.loads(output.data)
  2315. self.assertDictEqual(
  2316. data,
  2317. {
  2318. "error": "Project not found",
  2319. "error_code": "ENOPROJECT",
  2320. }
  2321. )
  2322. # Valid token, wrong project
  2323. output = self.app.post(
  2324. '/api/0/test2/issue/1/subscribe', headers=headers)
  2325. self.assertEqual(output.status_code, 401)
  2326. data = json.loads(output.data)
  2327. self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.name,
  2328. data['error_code'])
  2329. self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.value, data['error'])
  2330. # No input
  2331. output = self.app.post(
  2332. '/api/0/test/issue/1/subscribe', headers=headers)
  2333. self.assertEqual(output.status_code, 404)
  2334. data = json.loads(output.data)
  2335. self.assertDictEqual(
  2336. data,
  2337. {
  2338. "error": "Issue not found",
  2339. "error_code": "ENOISSUE",
  2340. }
  2341. )
  2342. # Create normal issue
  2343. repo = pagure.get_authorized_project(self.session, 'test')
  2344. msg = pagure.lib.new_issue(
  2345. session=self.session,
  2346. repo=repo,
  2347. title='Test issue #1',
  2348. content='We should work on this',
  2349. user='foo',
  2350. ticketfolder=None,
  2351. private=False,
  2352. issue_uid='aaabbbccc#1',
  2353. )
  2354. self.session.commit()
  2355. self.assertEqual(msg.title, 'Test issue #1')
  2356. # Check subscribtion before
  2357. repo = pagure.get_authorized_project(self.session, 'test')
  2358. issue = pagure.lib.search_issues(self.session, repo, issueid=1)
  2359. self.assertEqual(
  2360. pagure.lib.get_watch_list(self.session, issue),
  2361. set(['pingou', 'foo']))
  2362. # Unsubscribe - no changes
  2363. data = {}
  2364. output = self.app.post(
  2365. '/api/0/test/issue/1/subscribe', data=data, headers=headers)
  2366. self.assertEqual(output.status_code, 200)
  2367. data = json.loads(output.data)
  2368. self.assertDictEqual(
  2369. data,
  2370. {'message': 'You are no longer watching this issue'}
  2371. )
  2372. data = {}
  2373. output = self.app.post(
  2374. '/api/0/test/issue/1/subscribe', data=data, headers=headers)
  2375. self.assertEqual(output.status_code, 200)
  2376. data = json.loads(output.data)
  2377. self.assertDictEqual(
  2378. data,
  2379. {'message': 'You are no longer watching this issue'}
  2380. )
  2381. # No change
  2382. repo = pagure.get_authorized_project(self.session, 'test')
  2383. issue = pagure.lib.search_issues(self.session, repo, issueid=1)
  2384. self.assertEqual(
  2385. pagure.lib.get_watch_list(self.session, issue),
  2386. set(['pingou', 'foo']))
  2387. # Subscribe
  2388. data = {'status': True}
  2389. output = self.app.post(
  2390. '/api/0/test/issue/1/subscribe', data=data, headers=headers)
  2391. self.assertEqual(output.status_code, 200)
  2392. data = json.loads(output.data)
  2393. self.assertDictEqual(
  2394. data,
  2395. {'message': 'You are now watching this issue'}
  2396. )
  2397. # Subscribe - no changes
  2398. data = {'status': True}
  2399. output = self.app.post(
  2400. '/api/0/test/issue/1/subscribe', data=data, headers=headers)
  2401. self.assertEqual(output.status_code, 200)
  2402. data = json.loads(output.data)
  2403. self.assertDictEqual(
  2404. data,
  2405. {'message': 'You are now watching this issue'}
  2406. )
  2407. repo = pagure.get_authorized_project(self.session, 'test')
  2408. issue = pagure.lib.search_issues(self.session, repo, issueid=1)
  2409. self.assertEqual(
  2410. pagure.lib.get_watch_list(self.session, issue),
  2411. set(['pingou', 'foo', 'bar']))
  2412. # Unsubscribe
  2413. data = {}
  2414. output = self.app.post(
  2415. '/api/0/test/issue/1/subscribe', data=data, headers=headers)
  2416. self.assertEqual(output.status_code, 200)
  2417. data = json.loads(output.data)
  2418. self.assertDictEqual(
  2419. data,
  2420. {'message': 'You are no longer watching this issue'}
  2421. )
  2422. repo = pagure.get_authorized_project(self.session, 'test')
  2423. issue = pagure.lib.search_issues(self.session, repo, issueid=1)
  2424. self.assertEqual(
  2425. pagure.lib.get_watch_list(self.session, issue),
  2426. set(['pingou', 'foo']))
  2427. def test_api_update_custom_field(self):
  2428. """ Test the api_update_custom_field method of the flask api. """
  2429. tests.create_projects(self.session)
  2430. tests.create_projects_git(os.path.join(self.path, 'tickets'))
  2431. tests.create_tokens(self.session)
  2432. tests.create_tokens_acl(self.session)
  2433. headers = {'Authorization': 'token aaabbbcccddd'}
  2434. # Invalid project
  2435. output = self.app.post(
  2436. '/api/0/foo/issue/1/custom/bugzilla', headers=headers)
  2437. self.assertEqual(output.status_code, 404)
  2438. data = json.loads(output.data)
  2439. self.assertDictEqual(
  2440. data,
  2441. {
  2442. "error": "Project not found",
  2443. "error_code": "ENOPROJECT",
  2444. }
  2445. )
  2446. # Valid token, wrong project
  2447. output = self.app.post(
  2448. '/api/0/test2/issue/1/custom/bugzilla', headers=headers)
  2449. self.assertEqual(output.status_code, 401)
  2450. data = json.loads(output.data)
  2451. self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.name,
  2452. data['error_code'])
  2453. self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.value, data['error'])
  2454. # No issue
  2455. output = self.app.post(
  2456. '/api/0/test/issue/1/custom/bugzilla', headers=headers)
  2457. self.assertEqual(output.status_code, 404)
  2458. data = json.loads(output.data)
  2459. self.assertDictEqual(
  2460. data,
  2461. {
  2462. "error": "Issue not found",
  2463. "error_code": "ENOISSUE",
  2464. }
  2465. )
  2466. # Create normal issue
  2467. repo = pagure.get_authorized_project(self.session, 'test')
  2468. msg = pagure.lib.new_issue(
  2469. session=self.session,
  2470. repo=repo,
  2471. title='Test issue #1',
  2472. content='We should work on this',
  2473. user='pingou',
  2474. ticketfolder=None,
  2475. private=False,
  2476. )
  2477. self.session.commit()
  2478. self.assertEqual(msg.title, 'Test issue #1')
  2479. # Project does not have this custom field
  2480. output = self.app.post(
  2481. '/api/0/test/issue/1/custom/bugzilla', headers=headers)
  2482. self.assertEqual(output.status_code, 400)
  2483. data = json.loads(output.data)
  2484. self.assertDictEqual(
  2485. data,
  2486. {
  2487. "error": "Invalid custom field submitted",
  2488. "error_code": "EINVALIDISSUEFIELD",
  2489. }
  2490. )
  2491. # Check the behavior if the project disabled the issue tracker
  2492. repo = pagure.get_authorized_project(self.session, 'test')
  2493. settings = repo.settings
  2494. settings['issue_tracker'] = False
  2495. repo.settings = settings
  2496. self.session.add(repo)
  2497. self.session.commit()
  2498. output = self.app.post(
  2499. '/api/0/test/issue/1/custom/bugzilla', headers=headers)
  2500. self.assertEqual(output.status_code, 404)
  2501. data = json.loads(output.data)
  2502. self.assertDictEqual(
  2503. data,
  2504. {
  2505. "error": "Issue tracker disabled for this project",
  2506. "error_code": "ETRACKERDISABLED",
  2507. }
  2508. )
  2509. repo = pagure.get_authorized_project(self.session, 'test')
  2510. settings = repo.settings
  2511. settings['issue_tracker'] = True
  2512. repo.settings = settings
  2513. self.session.add(repo)
  2514. self.session.commit()
  2515. # Invalid API token
  2516. headers = {'Authorization': 'token foobar'}
  2517. output = self.app.post(
  2518. '/api/0/test/issue/1/custom/bugzilla', headers=headers)
  2519. self.assertEqual(output.status_code, 401)
  2520. data = json.loads(output.data)
  2521. self.assertDictEqual(
  2522. data,
  2523. {
  2524. "error": "Invalid or expired token. Please visit "
  2525. "https://pagure.org/ to get or renew your API token.",
  2526. "error_code": "EINVALIDTOK",
  2527. }
  2528. )
  2529. headers = {'Authorization': 'token aaabbbcccddd'}
  2530. # Set some custom fields
  2531. repo = pagure.get_authorized_project(self.session, 'test')
  2532. msg = pagure.lib.set_custom_key_fields(
  2533. self.session, repo,
  2534. ['bugzilla', 'upstream', 'reviewstatus'],
  2535. ['link', 'boolean', 'list'],
  2536. ['unused data for non-list type', '', 'ack, nack , needs review'],
  2537. [None, None, None])
  2538. self.session.commit()
  2539. self.assertEqual(msg, 'List of custom fields updated')
  2540. # Check the project custom fields were correctly set
  2541. for key in repo.issue_keys:
  2542. # Check that the bugzilla field correctly had its data removed
  2543. if key.name == "bugzilla":
  2544. self.assertIsNone(key.data)
  2545. # Check that the reviewstatus list field still has its list
  2546. if key.name == "reviewstatus":
  2547. self.assertEqual(
  2548. sorted(key.data), ['ack', 'nack', 'needs review'])
  2549. # Check that not setting the value on a non-existing custom field
  2550. # changes nothing
  2551. output = self.app.post(
  2552. '/api/0/test/issue/1/custom/bugzilla', headers=headers)
  2553. self.assertEqual(output.status_code, 200)
  2554. data = json.loads(output.data)
  2555. self.assertDictEqual(
  2556. data,
  2557. {
  2558. 'message': 'No changes'
  2559. }
  2560. )
  2561. repo = pagure.get_authorized_project(self.session, 'test')
  2562. issue = pagure.lib.search_issues(self.session, repo, issueid=1)
  2563. self.assertEqual(issue.other_fields, [])
  2564. self.assertEqual(len(issue.other_fields), 0)
  2565. # Invalid value
  2566. output = self.app.post(
  2567. '/api/0/test/issue/1/custom/bugzilla', headers=headers,
  2568. data={'value': 'foobar'})
  2569. self.assertEqual(output.status_code, 400)
  2570. data = json.loads(output.data)
  2571. self.assertDictEqual(
  2572. data,
  2573. {
  2574. "error": "Invalid custom field submitted, the value is not "
  2575. "a link",
  2576. "error_code": "EINVALIDISSUEFIELD_LINK",
  2577. }
  2578. )
  2579. repo = pagure.get_authorized_project(self.session, 'test')
  2580. issue = pagure.lib.search_issues(self.session, repo, issueid=1)
  2581. self.assertEqual(issue.other_fields, [])
  2582. self.assertEqual(len(issue.other_fields), 0)
  2583. # All good
  2584. output = self.app.post(
  2585. '/api/0/test/issue/1/custom/bugzilla', headers=headers,
  2586. data={'value': 'https://bugzilla.redhat.com/1234'})
  2587. self.assertEqual(output.status_code, 200)
  2588. data = json.loads(output.data)
  2589. self.assertDictEqual(
  2590. data,
  2591. {
  2592. "message": "Custom field bugzilla adjusted to "
  2593. "https://bugzilla.redhat.com/1234"
  2594. }
  2595. )
  2596. repo = pagure.get_authorized_project(self.session, 'test')
  2597. issue = pagure.lib.search_issues(self.session, repo, issueid=1)
  2598. self.assertEqual(len(issue.other_fields), 1)
  2599. self.assertEqual(issue.other_fields[0].key.name, 'bugzilla')
  2600. self.assertEqual(
  2601. issue.other_fields[0].value,
  2602. 'https://bugzilla.redhat.com/1234')
  2603. # Reset the value
  2604. output = self.app.post(
  2605. '/api/0/test/issue/1/custom/bugzilla', headers=headers,
  2606. data={'value': ''})
  2607. self.assertEqual(output.status_code, 200)
  2608. data = json.loads(output.data)
  2609. self.assertDictEqual(
  2610. data,
  2611. {
  2612. "message": "Custom field bugzilla reset "
  2613. "(from https://bugzilla.redhat.com/1234)"
  2614. }
  2615. )
  2616. repo = pagure.get_authorized_project(self.session, 'test')
  2617. issue = pagure.lib.search_issues(self.session, repo, issueid=1)
  2618. self.assertEqual(len(issue.other_fields), 0)
  2619. if __name__ == '__main__':
  2620. unittest.main(verbosity=2)