test_pagure_flask_api_fork.py 138 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791
  1. # -*- coding: utf-8 -*-
  2. """
  3. (c) 2015 - Copyright Red Hat Inc
  4. Authors:
  5. Pierre-Yves Chibon <pingou@pingoured.fr>
  6. """
  7. from __future__ import unicode_literals, absolute_import
  8. import datetime
  9. import unittest
  10. import shutil
  11. import sys
  12. import os
  13. import json
  14. from mock import patch, MagicMock
  15. sys.path.insert(
  16. 0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..")
  17. )
  18. import pagure.lib.query
  19. import pagure.default_config
  20. import tests
  21. class PagureFlaskApiForktests(tests.Modeltests):
  22. """ Tests for the flask API of pagure for issue """
  23. maxDiff = None
  24. def setUp(self):
  25. """ Set up the environnment, ran before every tests. """
  26. super(PagureFlaskApiForktests, self).setUp()
  27. pagure.config.config["REQUESTS_FOLDER"] = None
  28. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  29. def test_api_pull_request_views_pr_disabled(self):
  30. """ Test the api_pull_request_views method of the flask api when PR
  31. are disabled. """
  32. tests.create_projects(self.session)
  33. tests.create_tokens(self.session)
  34. tests.create_tokens_acl(self.session)
  35. # Create a pull-request
  36. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  37. forked_repo = pagure.lib.query.get_authorized_project(
  38. self.session, "test"
  39. )
  40. req = pagure.lib.query.new_pull_request(
  41. session=self.session,
  42. repo_from=forked_repo,
  43. branch_from="master",
  44. repo_to=repo,
  45. branch_to="master",
  46. title="test pull-request",
  47. user="pingou",
  48. )
  49. self.session.commit()
  50. self.assertEqual(req.id, 1)
  51. self.assertEqual(req.title, "test pull-request")
  52. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  53. settings = repo.settings
  54. settings["pull_requests"] = False
  55. repo.settings = settings
  56. self.session.add(repo)
  57. self.session.commit()
  58. output = self.app.get("/api/0/test/pull-requests")
  59. self.assertEqual(output.status_code, 404)
  60. data = json.loads(output.get_data(as_text=True))
  61. self.assertDictEqual(
  62. data,
  63. {
  64. "error": "Pull-Request have been deactivated for this project",
  65. "error_code": "EPULLREQUESTSDISABLED",
  66. },
  67. )
  68. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  69. def test_api_pull_request_views_pr_closed(self):
  70. """ Test the api_pull_request_views method of the flask api to list
  71. the closed PRs. """
  72. tests.create_projects(self.session)
  73. tests.create_tokens(self.session)
  74. tests.create_tokens_acl(self.session)
  75. # Create a pull-request
  76. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  77. forked_repo = pagure.lib.query.get_authorized_project(
  78. self.session, "test"
  79. )
  80. req = pagure.lib.query.new_pull_request(
  81. session=self.session,
  82. repo_from=forked_repo,
  83. branch_from="master",
  84. repo_to=repo,
  85. branch_to="master",
  86. title="test pull-request",
  87. user="pingou",
  88. )
  89. self.session.commit()
  90. self.assertEqual(req.id, 1)
  91. self.assertEqual(req.title, "test pull-request")
  92. output = self.app.get("/api/0/test/pull-requests?status=closed")
  93. self.assertEqual(output.status_code, 200)
  94. data = json.loads(output.get_data(as_text=True))
  95. for k in ["first", "last"]:
  96. self.assertIsNotNone(data["pagination"][k])
  97. data["pagination"][k] = "http://localhost..."
  98. self.assertDictEqual(
  99. data,
  100. {
  101. "args": {
  102. "assignee": None,
  103. "author": None,
  104. "tags": [],
  105. "page": 1,
  106. "per_page": 20,
  107. "status": "closed",
  108. },
  109. "pagination": {
  110. "first": "http://localhost...",
  111. "last": "http://localhost...",
  112. "next": None,
  113. "page": 1,
  114. "pages": 0,
  115. "per_page": 20,
  116. "prev": None,
  117. },
  118. "requests": [],
  119. "total_requests": 0,
  120. },
  121. )
  122. # Close the PR and try again
  123. pagure.lib.query.close_pull_request(
  124. self.session, request=req, user="pingou", merged=False
  125. )
  126. output = self.app.get("/api/0/test/pull-requests?status=closed")
  127. self.assertEqual(output.status_code, 200)
  128. data = json.loads(output.get_data(as_text=True))
  129. self.assertEqual(
  130. sorted(data.keys()),
  131. ["args", "pagination", "requests", "total_requests"],
  132. )
  133. self.assertDictEqual(
  134. data["args"],
  135. {
  136. "assignee": None,
  137. "author": None,
  138. "tags": [],
  139. "page": 1,
  140. "per_page": 20,
  141. "status": "closed",
  142. },
  143. )
  144. self.assertEqual(data["total_requests"], 1)
  145. # Create two closed pull-requests
  146. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  147. forked_repo = pagure.lib.query.get_authorized_project(
  148. self.session, "test"
  149. )
  150. pagure.lib.query.new_pull_request(
  151. session=self.session,
  152. repo_from=forked_repo,
  153. branch_from="master",
  154. repo_to=repo,
  155. branch_to="master",
  156. title="closed pullrequest by user foo on repo test",
  157. user="foo",
  158. status="Closed",
  159. )
  160. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  161. forked_repo = pagure.lib.query.get_authorized_project(
  162. self.session, "test"
  163. )
  164. pagure.lib.query.new_pull_request(
  165. session=self.session,
  166. repo_from=forked_repo,
  167. branch_from="master",
  168. repo_to=repo,
  169. branch_to="master",
  170. title="closed pullrequest by user pingou on repo test",
  171. user="pingou",
  172. status="Closed",
  173. )
  174. self.session.commit()
  175. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  176. forked_repo = pagure.lib.query.get_authorized_project(
  177. self.session, "test"
  178. )
  179. pagure.lib.query.new_pull_request(
  180. session=self.session,
  181. repo_from=forked_repo,
  182. branch_from="master",
  183. repo_to=repo,
  184. branch_to="master",
  185. title="merged pullrequest by user pingou on repo test",
  186. user="pingou",
  187. status="Merged",
  188. )
  189. self.session.commit()
  190. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  191. forked_repo = pagure.lib.query.get_authorized_project(
  192. self.session, "test"
  193. )
  194. pagure.lib.query.new_pull_request(
  195. session=self.session,
  196. repo_from=forked_repo,
  197. branch_from="master",
  198. repo_to=repo,
  199. branch_to="master",
  200. title="merged pullrequest by user foo on repo test",
  201. user="foo",
  202. status="Merged",
  203. )
  204. self.session.commit()
  205. # Test the API view of closed pull-requests
  206. output = self.app.get("/api/0/test/pull-requests?status=closed")
  207. self.assertEqual(output.status_code, 200)
  208. data = json.loads(output.get_data(as_text=True))
  209. self.assertEqual(len(data["requests"]), 3)
  210. self.assertEqual(
  211. sorted(data.keys()),
  212. ["args", "pagination", "requests", "total_requests"],
  213. )
  214. for req in data["requests"]:
  215. self.assertEqual(req["status"], "Closed")
  216. self.assertEqual(data["args"]["status"], "closed")
  217. self.assertEqual(data["args"]["page"], 1)
  218. self.assertEqual(data["total_requests"], 3)
  219. # Test the API view of merged pull-requests
  220. output = self.app.get("/api/0/test/pull-requests?status=merged")
  221. self.assertEqual(output.status_code, 200)
  222. data = json.loads(output.get_data(as_text=True))
  223. self.assertEqual(len(data["requests"]), 2)
  224. self.assertEqual(
  225. sorted(data.keys()),
  226. ["args", "pagination", "requests", "total_requests"],
  227. )
  228. for req in data["requests"]:
  229. self.assertEqual(req["status"], "Merged")
  230. self.assertEqual(data["args"]["status"], "merged")
  231. self.assertEqual(data["args"]["page"], 1)
  232. self.assertEqual(data["total_requests"], 2)
  233. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  234. def test_api_pull_request_views_all_pr(self):
  235. """ Test the api_pull_request_views method of the flask api to list
  236. all PRs. """
  237. tests.create_projects(self.session)
  238. tests.create_tokens(self.session)
  239. tests.create_tokens_acl(self.session)
  240. # Create a pull-request
  241. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  242. forked_repo = pagure.lib.query.get_authorized_project(
  243. self.session, "test"
  244. )
  245. req = pagure.lib.query.new_pull_request(
  246. session=self.session,
  247. repo_from=forked_repo,
  248. branch_from="master",
  249. repo_to=repo,
  250. branch_to="master",
  251. title="test pull-request",
  252. user="pingou",
  253. )
  254. self.session.commit()
  255. self.assertEqual(req.id, 1)
  256. self.assertEqual(req.title, "test pull-request")
  257. output = self.app.get("/api/0/test/pull-requests?status=all")
  258. self.assertEqual(output.status_code, 200)
  259. data = json.loads(output.get_data(as_text=True))
  260. self.assertEqual(
  261. sorted(data.keys()),
  262. ["args", "pagination", "requests", "total_requests"],
  263. )
  264. self.assertDictEqual(
  265. data["args"],
  266. {
  267. "assignee": None,
  268. "author": None,
  269. "tags": [],
  270. "page": 1,
  271. "per_page": 20,
  272. "status": "all",
  273. },
  274. )
  275. self.assertEqual(data["total_requests"], 1)
  276. # Close the PR and try again
  277. pagure.lib.query.close_pull_request(
  278. self.session, request=req, user="pingou", merged=False
  279. )
  280. output = self.app.get("/api/0/test/pull-requests?status=all")
  281. self.assertEqual(output.status_code, 200)
  282. data = json.loads(output.get_data(as_text=True))
  283. self.assertEqual(
  284. sorted(data.keys()),
  285. ["args", "pagination", "requests", "total_requests"],
  286. )
  287. self.assertDictEqual(
  288. data["args"],
  289. {
  290. "assignee": None,
  291. "author": None,
  292. "tags": [],
  293. "page": 1,
  294. "per_page": 20,
  295. "status": "all",
  296. },
  297. )
  298. self.assertEqual(data["total_requests"], 1)
  299. @patch("pagure.lib.notify.send_email")
  300. def test_api_pull_request_views(self, send_email):
  301. """ Test the api_pull_request_views method of the flask api. """
  302. send_email.return_value = True
  303. tests.create_projects(self.session)
  304. tests.create_tokens(self.session)
  305. tests.create_tokens_acl(self.session)
  306. # Create a pull-request
  307. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  308. forked_repo = pagure.lib.query.get_authorized_project(
  309. self.session, "test"
  310. )
  311. req = pagure.lib.query.new_pull_request(
  312. session=self.session,
  313. repo_from=forked_repo,
  314. branch_from="master",
  315. repo_to=repo,
  316. branch_to="master",
  317. title="test pull-request",
  318. user="pingou",
  319. )
  320. self.session.commit()
  321. self.assertEqual(req.id, 1)
  322. self.assertEqual(req.title, "test pull-request")
  323. # Invalid repo
  324. output = self.app.get("/api/0/foo/pull-requests")
  325. self.assertEqual(output.status_code, 404)
  326. data = json.loads(output.get_data(as_text=True))
  327. self.assertDictEqual(
  328. data, {"error": "Project not found", "error_code": "ENOPROJECT"}
  329. )
  330. # List pull-requests
  331. output = self.app.get("/api/0/test/pull-requests")
  332. self.assertEqual(output.status_code, 200)
  333. data = json.loads(output.get_data(as_text=True))
  334. data["requests"][0]["date_created"] = "1431414800"
  335. data["requests"][0]["updated_on"] = "1431414800"
  336. data["requests"][0]["project"]["date_created"] = "1431414800"
  337. data["requests"][0]["project"]["date_modified"] = "1431414800"
  338. data["requests"][0]["repo_from"]["date_created"] = "1431414800"
  339. data["requests"][0]["repo_from"]["date_modified"] = "1431414800"
  340. data["requests"][0]["uid"] = "1431414800"
  341. data["requests"][0]["last_updated"] = "1431414800"
  342. for k in ["first", "last"]:
  343. self.assertIsNotNone(data["pagination"][k])
  344. data["pagination"][k] = "http://localhost..."
  345. expected_data = {
  346. "args": {
  347. "assignee": None,
  348. "author": None,
  349. "tags": [],
  350. "page": 1,
  351. "per_page": 20,
  352. "status": True,
  353. },
  354. "pagination": {
  355. "first": "http://localhost...",
  356. "last": "http://localhost...",
  357. "next": None,
  358. "page": 1,
  359. "pages": 1,
  360. "per_page": 20,
  361. "prev": None,
  362. },
  363. "requests": [
  364. {
  365. "assignee": None,
  366. "branch": "master",
  367. "branch_from": "master",
  368. "cached_merge_status": "unknown",
  369. "closed_at": None,
  370. "closed_by": None,
  371. "comments": [],
  372. "commit_start": None,
  373. "commit_stop": None,
  374. "date_created": "1431414800",
  375. "id": 1,
  376. "initial_comment": None,
  377. "last_updated": "1431414800",
  378. "project": {
  379. "access_groups": {
  380. "admin": [],
  381. "commit": [],
  382. "ticket": [],
  383. },
  384. "access_users": {
  385. "admin": [],
  386. "commit": [],
  387. "owner": ["pingou"],
  388. "ticket": [],
  389. },
  390. "close_status": [
  391. "Invalid",
  392. "Insufficient data",
  393. "Fixed",
  394. "Duplicate",
  395. ],
  396. "custom_keys": [],
  397. "date_created": "1431414800",
  398. "date_modified": "1431414800",
  399. "description": "test project #1",
  400. "fullname": "test",
  401. "url_path": "test",
  402. "id": 1,
  403. "milestones": {},
  404. "name": "test",
  405. "namespace": None,
  406. "parent": None,
  407. "priorities": {},
  408. "tags": [],
  409. "user": {
  410. "fullname": "PY C",
  411. "name": "pingou",
  412. "url_path": "user/pingou",
  413. },
  414. },
  415. "remote_git": None,
  416. "repo_from": {
  417. "access_groups": {
  418. "admin": [],
  419. "commit": [],
  420. "ticket": [],
  421. },
  422. "access_users": {
  423. "admin": [],
  424. "commit": [],
  425. "owner": ["pingou"],
  426. "ticket": [],
  427. },
  428. "close_status": [
  429. "Invalid",
  430. "Insufficient data",
  431. "Fixed",
  432. "Duplicate",
  433. ],
  434. "custom_keys": [],
  435. "date_created": "1431414800",
  436. "date_modified": "1431414800",
  437. "description": "test project #1",
  438. "fullname": "test",
  439. "url_path": "test",
  440. "id": 1,
  441. "milestones": {},
  442. "name": "test",
  443. "namespace": None,
  444. "parent": None,
  445. "priorities": {},
  446. "tags": [],
  447. "user": {
  448. "fullname": "PY C",
  449. "name": "pingou",
  450. "url_path": "user/pingou",
  451. },
  452. },
  453. "status": "Open",
  454. "tags": [],
  455. "threshold_reached": None,
  456. "title": "test pull-request",
  457. "uid": "1431414800",
  458. "updated_on": "1431414800",
  459. "user": {
  460. "fullname": "PY C",
  461. "name": "pingou",
  462. "url_path": "user/pingou",
  463. },
  464. }
  465. ],
  466. "total_requests": 1,
  467. }
  468. self.assertDictEqual(data, expected_data)
  469. headers = {"Authorization": "token aaabbbcccddd"}
  470. # Access Pull-Request authenticated
  471. output = self.app.get("/api/0/test/pull-requests", headers=headers)
  472. self.assertEqual(output.status_code, 200)
  473. data2 = json.loads(output.get_data(as_text=True))
  474. data2["requests"][0]["date_created"] = "1431414800"
  475. data2["requests"][0]["updated_on"] = "1431414800"
  476. data2["requests"][0]["project"]["date_created"] = "1431414800"
  477. data2["requests"][0]["project"]["date_modified"] = "1431414800"
  478. data2["requests"][0]["repo_from"]["date_created"] = "1431414800"
  479. data2["requests"][0]["repo_from"]["date_modified"] = "1431414800"
  480. data2["requests"][0]["uid"] = "1431414800"
  481. data2["requests"][0]["last_updated"] = "1431414800"
  482. for k in ["first", "last"]:
  483. self.assertIsNotNone(data["pagination"][k])
  484. data2["pagination"][k] = "http://localhost..."
  485. self.assertDictEqual(data, data2)
  486. @patch("pagure.lib.notify.send_email")
  487. def test_api_pull_request_view_tag_filtered(self, send_email):
  488. """ Test the api_pull_request_view method of the flask api to list
  489. tag filtered open PRs. """
  490. send_email.return_value = True
  491. tests.create_projects(self.session)
  492. tests.create_tokens(self.session)
  493. tests.create_tokens_acl(self.session)
  494. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  495. # Add a tag
  496. pagure.lib.query.new_tag(
  497. self.session, "tag-1", "tag-1 description", "#ff0000", repo.id
  498. )
  499. # Create a pull-request
  500. forked_repo = pagure.lib.query.get_authorized_project(
  501. self.session, "test"
  502. )
  503. req = pagure.lib.query.new_pull_request(
  504. session=self.session,
  505. repo_from=forked_repo,
  506. branch_from="master",
  507. repo_to=repo,
  508. branch_to="master",
  509. title="test pull-request",
  510. user="pingou",
  511. )
  512. self.session.commit()
  513. self.assertEqual(req.id, 1)
  514. self.assertEqual(req.title, "test pull-request")
  515. output = self.app.get("/api/0/test/pull-requests?tags=tag-1")
  516. self.assertEqual(output.status_code, 200)
  517. data = json.loads(output.get_data(as_text=True))
  518. for k in ["first", "last"]:
  519. self.assertIsNotNone(data["pagination"][k])
  520. data["pagination"][k] = "http://localhost..."
  521. self.assertDictEqual(
  522. data,
  523. {
  524. "args": {
  525. "assignee": None,
  526. "author": None,
  527. "tags": ["tag-1"],
  528. "page": 1,
  529. "per_page": 20,
  530. "status": True,
  531. },
  532. "pagination": {
  533. "first": "http://localhost...",
  534. "last": "http://localhost...",
  535. "next": None,
  536. "page": 1,
  537. "pages": 0,
  538. "per_page": 20,
  539. "prev": None,
  540. },
  541. "requests": [],
  542. "total_requests": 0,
  543. },
  544. )
  545. # Tag the PR and try again
  546. pagure.lib.query.update_tags(
  547. self.session, obj=req, tags=["tag-1"], username="pingou"
  548. )
  549. self.session.commit()
  550. output = self.app.get("/api/0/test/pull-requests?tags=tag-1")
  551. self.assertEqual(output.status_code, 200)
  552. data = json.loads(output.get_data(as_text=True))
  553. self.assertEqual(
  554. sorted(data.keys()),
  555. ["args", "pagination", "requests", "total_requests"],
  556. )
  557. self.assertDictEqual(
  558. data["args"],
  559. {
  560. "assignee": None,
  561. "author": None,
  562. "tags": ["tag-1"],
  563. "page": 1,
  564. "per_page": 20,
  565. "status": True,
  566. },
  567. )
  568. self.assertEqual(data["total_requests"], 1)
  569. # Try negative filtering
  570. output = self.app.get("/api/0/test/pull-requests?tags=!tag-1")
  571. self.assertEqual(output.status_code, 200)
  572. data = json.loads(output.get_data(as_text=True))
  573. for k in ["first", "last"]:
  574. self.assertIsNotNone(data["pagination"][k])
  575. data["pagination"][k] = "http://localhost..."
  576. self.assertDictEqual(
  577. data,
  578. {
  579. "args": {
  580. "assignee": None,
  581. "author": None,
  582. "tags": ["!tag-1"],
  583. "page": 1,
  584. "per_page": 20,
  585. "status": True,
  586. },
  587. "pagination": {
  588. "first": "http://localhost...",
  589. "last": "http://localhost...",
  590. "next": None,
  591. "page": 1,
  592. "pages": 0,
  593. "per_page": 20,
  594. "prev": None,
  595. },
  596. "requests": [],
  597. "total_requests": 0,
  598. },
  599. )
  600. @patch("pagure.lib.notify.send_email")
  601. def test_api_pull_request_view_pr_disabled(self, send_email):
  602. """ Test the api_pull_request_view method of the flask api. """
  603. send_email.return_value = True
  604. tests.create_projects(self.session)
  605. tests.create_tokens(self.session)
  606. tests.create_tokens_acl(self.session)
  607. # Create a pull-request
  608. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  609. forked_repo = pagure.lib.query.get_authorized_project(
  610. self.session, "test"
  611. )
  612. req = pagure.lib.query.new_pull_request(
  613. session=self.session,
  614. repo_from=forked_repo,
  615. branch_from="master",
  616. repo_to=repo,
  617. branch_to="master",
  618. title="test pull-request",
  619. user="pingou",
  620. )
  621. self.session.commit()
  622. self.assertEqual(req.id, 1)
  623. self.assertEqual(req.title, "test pull-request")
  624. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  625. settings = repo.settings
  626. settings["pull_requests"] = False
  627. repo.settings = settings
  628. self.session.add(repo)
  629. self.session.commit()
  630. output = self.app.get("/api/0/test/pull-request/1")
  631. self.assertEqual(output.status_code, 404)
  632. data = json.loads(output.get_data(as_text=True))
  633. self.assertDictEqual(
  634. data,
  635. {
  636. "error": "Pull-Request have been deactivated for this project",
  637. "error_code": "EPULLREQUESTSDISABLED",
  638. },
  639. )
  640. @patch("pagure.lib.notify.send_email")
  641. def test_api_pull_request_view(self, send_email):
  642. """ Test the api_pull_request_view method of the flask api. """
  643. send_email.return_value = True
  644. tests.create_projects(self.session)
  645. tests.create_tokens(self.session)
  646. tests.create_tokens_acl(self.session)
  647. # Create a pull-request
  648. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  649. forked_repo = pagure.lib.query.get_authorized_project(
  650. self.session, "test"
  651. )
  652. req = pagure.lib.query.new_pull_request(
  653. session=self.session,
  654. repo_from=forked_repo,
  655. branch_from="master",
  656. repo_to=repo,
  657. branch_to="master",
  658. title="test pull-request",
  659. user="pingou",
  660. )
  661. self.session.commit()
  662. self.assertEqual(req.id, 1)
  663. self.assertEqual(req.title, "test pull-request")
  664. # Invalid repo
  665. output = self.app.get("/api/0/foo/pull-request/1")
  666. self.assertEqual(output.status_code, 404)
  667. data = json.loads(output.get_data(as_text=True))
  668. self.assertDictEqual(
  669. data, {"error": "Project not found", "error_code": "ENOPROJECT"}
  670. )
  671. # Invalid issue for this repo
  672. output = self.app.get("/api/0/test2/pull-request/1")
  673. self.assertEqual(output.status_code, 404)
  674. data = json.loads(output.get_data(as_text=True))
  675. self.assertDictEqual(
  676. data, {"error": "Pull-Request not found", "error_code": "ENOREQ"}
  677. )
  678. # Valid issue
  679. output = self.app.get("/api/0/test/pull-request/1")
  680. self.assertEqual(output.status_code, 200)
  681. data = json.loads(output.get_data(as_text=True))
  682. data["date_created"] = "1431414800"
  683. data["updated_on"] = "1431414800"
  684. data["project"]["date_created"] = "1431414800"
  685. data["project"]["date_modified"] = "1431414800"
  686. data["repo_from"]["date_created"] = "1431414800"
  687. data["repo_from"]["date_modified"] = "1431414800"
  688. data["uid"] = "1431414800"
  689. data["last_updated"] = "1431414800"
  690. expected_data = {
  691. "assignee": None,
  692. "branch": "master",
  693. "branch_from": "master",
  694. "cached_merge_status": "unknown",
  695. "closed_at": None,
  696. "closed_by": None,
  697. "comments": [],
  698. "commit_start": None,
  699. "commit_stop": None,
  700. "date_created": "1431414800",
  701. "id": 1,
  702. "initial_comment": None,
  703. "last_updated": "1431414800",
  704. "project": {
  705. "access_groups": {"admin": [], "commit": [], "ticket": []},
  706. "access_users": {
  707. "admin": [],
  708. "commit": [],
  709. "owner": ["pingou"],
  710. "ticket": [],
  711. },
  712. "close_status": [
  713. "Invalid",
  714. "Insufficient data",
  715. "Fixed",
  716. "Duplicate",
  717. ],
  718. "custom_keys": [],
  719. "date_created": "1431414800",
  720. "date_modified": "1431414800",
  721. "description": "test project #1",
  722. "fullname": "test",
  723. "url_path": "test",
  724. "id": 1,
  725. "milestones": {},
  726. "name": "test",
  727. "namespace": None,
  728. "parent": None,
  729. "priorities": {},
  730. "tags": [],
  731. "user": {
  732. "fullname": "PY C",
  733. "name": "pingou",
  734. "url_path": "user/pingou",
  735. },
  736. },
  737. "remote_git": None,
  738. "repo_from": {
  739. "access_groups": {"admin": [], "commit": [], "ticket": []},
  740. "access_users": {
  741. "admin": [],
  742. "commit": [],
  743. "owner": ["pingou"],
  744. "ticket": [],
  745. },
  746. "close_status": [
  747. "Invalid",
  748. "Insufficient data",
  749. "Fixed",
  750. "Duplicate",
  751. ],
  752. "custom_keys": [],
  753. "date_created": "1431414800",
  754. "date_modified": "1431414800",
  755. "description": "test project #1",
  756. "fullname": "test",
  757. "url_path": "test",
  758. "id": 1,
  759. "milestones": {},
  760. "name": "test",
  761. "namespace": None,
  762. "parent": None,
  763. "priorities": {},
  764. "tags": [],
  765. "user": {
  766. "fullname": "PY C",
  767. "name": "pingou",
  768. "url_path": "user/pingou",
  769. },
  770. },
  771. "status": "Open",
  772. "tags": [],
  773. "threshold_reached": None,
  774. "title": "test pull-request",
  775. "uid": "1431414800",
  776. "updated_on": "1431414800",
  777. "user": {
  778. "fullname": "PY C",
  779. "name": "pingou",
  780. "url_path": "user/pingou",
  781. },
  782. }
  783. self.assertDictEqual(data, expected_data)
  784. headers = {"Authorization": "token aaabbbcccddd"}
  785. # Access Pull-Request authenticated
  786. output = self.app.get("/api/0/test/pull-request/1", headers=headers)
  787. self.assertEqual(output.status_code, 200)
  788. data2 = json.loads(output.get_data(as_text=True))
  789. data2["date_created"] = "1431414800"
  790. data2["project"]["date_created"] = "1431414800"
  791. data2["project"]["date_modified"] = "1431414800"
  792. data2["repo_from"]["date_created"] = "1431414800"
  793. data2["repo_from"]["date_modified"] = "1431414800"
  794. data2["uid"] = "1431414800"
  795. data2["date_created"] = "1431414800"
  796. data2["updated_on"] = "1431414800"
  797. data2["last_updated"] = "1431414800"
  798. self.assertDictEqual(data, data2)
  799. @patch("pagure.lib.notify.send_email")
  800. def test_api_pull_request_by_uid_view(self, send_email):
  801. """ Test the api_pull_request_by_uid_view method of the flask api. """
  802. send_email.return_value = True
  803. tests.create_projects(self.session)
  804. tests.create_tokens(self.session)
  805. tests.create_tokens_acl(self.session)
  806. # Create a pull-request
  807. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  808. forked_repo = pagure.lib.query.get_authorized_project(
  809. self.session, "test"
  810. )
  811. req = pagure.lib.query.new_pull_request(
  812. session=self.session,
  813. repo_from=forked_repo,
  814. branch_from="master",
  815. repo_to=repo,
  816. branch_to="master",
  817. title="test pull-request",
  818. user="pingou",
  819. )
  820. self.session.commit()
  821. self.assertEqual(req.id, 1)
  822. self.assertEqual(req.title, "test pull-request")
  823. uid = req.uid
  824. # Invalid request
  825. output = self.app.get("/api/0/pull-requests/{}".format(uid + "aaa"))
  826. self.assertEqual(output.status_code, 404)
  827. data = json.loads(output.get_data(as_text=True))
  828. self.assertDictEqual(
  829. data, {"error": "Pull-Request not found", "error_code": "ENOREQ"}
  830. )
  831. # Valid issue
  832. output = self.app.get("/api/0/pull-requests/{}".format(uid))
  833. self.assertEqual(output.status_code, 200)
  834. data = json.loads(output.get_data(as_text=True))
  835. data["date_created"] = "1431414800"
  836. data["updated_on"] = "1431414800"
  837. data["project"]["date_created"] = "1431414800"
  838. data["project"]["date_modified"] = "1431414800"
  839. data["repo_from"]["date_created"] = "1431414800"
  840. data["repo_from"]["date_modified"] = "1431414800"
  841. data["last_updated"] = "1431414800"
  842. expected_data = {
  843. "assignee": None,
  844. "branch": "master",
  845. "branch_from": "master",
  846. "cached_merge_status": "unknown",
  847. "closed_at": None,
  848. "closed_by": None,
  849. "comments": [],
  850. "commit_start": None,
  851. "commit_stop": None,
  852. "date_created": "1431414800",
  853. "id": 1,
  854. "initial_comment": None,
  855. "last_updated": "1431414800",
  856. "project": {
  857. "access_groups": {"admin": [], "commit": [], "ticket": []},
  858. "access_users": {
  859. "admin": [],
  860. "commit": [],
  861. "owner": ["pingou"],
  862. "ticket": [],
  863. },
  864. "close_status": [
  865. "Invalid",
  866. "Insufficient data",
  867. "Fixed",
  868. "Duplicate",
  869. ],
  870. "custom_keys": [],
  871. "date_created": "1431414800",
  872. "date_modified": "1431414800",
  873. "description": "test project #1",
  874. "fullname": "test",
  875. "url_path": "test",
  876. "id": 1,
  877. "milestones": {},
  878. "name": "test",
  879. "namespace": None,
  880. "parent": None,
  881. "priorities": {},
  882. "tags": [],
  883. "user": {
  884. "fullname": "PY C",
  885. "name": "pingou",
  886. "url_path": "user/pingou",
  887. },
  888. },
  889. "remote_git": None,
  890. "repo_from": {
  891. "access_groups": {"admin": [], "commit": [], "ticket": []},
  892. "access_users": {
  893. "admin": [],
  894. "commit": [],
  895. "owner": ["pingou"],
  896. "ticket": [],
  897. },
  898. "close_status": [
  899. "Invalid",
  900. "Insufficient data",
  901. "Fixed",
  902. "Duplicate",
  903. ],
  904. "custom_keys": [],
  905. "date_created": "1431414800",
  906. "date_modified": "1431414800",
  907. "description": "test project #1",
  908. "fullname": "test",
  909. "url_path": "test",
  910. "id": 1,
  911. "milestones": {},
  912. "name": "test",
  913. "namespace": None,
  914. "parent": None,
  915. "priorities": {},
  916. "tags": [],
  917. "user": {
  918. "fullname": "PY C",
  919. "name": "pingou",
  920. "url_path": "user/pingou",
  921. },
  922. },
  923. "status": "Open",
  924. "tags": [],
  925. "threshold_reached": None,
  926. "title": "test pull-request",
  927. "uid": uid,
  928. "updated_on": "1431414800",
  929. "user": {
  930. "fullname": "PY C",
  931. "name": "pingou",
  932. "url_path": "user/pingou",
  933. },
  934. }
  935. self.assertDictEqual(data, expected_data)
  936. headers = {"Authorization": "token aaabbbcccddd"}
  937. # Access Pull-Request authenticated
  938. output = self.app.get(
  939. "/api/0/pull-requests/{}".format(uid), headers=headers
  940. )
  941. self.assertEqual(output.status_code, 200)
  942. data2 = json.loads(output.get_data(as_text=True))
  943. data2["date_created"] = "1431414800"
  944. data2["project"]["date_created"] = "1431414800"
  945. data2["project"]["date_modified"] = "1431414800"
  946. data2["repo_from"]["date_created"] = "1431414800"
  947. data2["repo_from"]["date_modified"] = "1431414800"
  948. data2["date_created"] = "1431414800"
  949. data2["updated_on"] = "1431414800"
  950. data2["last_updated"] = "1431414800"
  951. self.assertDictEqual(data, data2)
  952. @patch("pagure.lib.notify.send_email")
  953. def test_api_pull_request_close_pr_disabled(self, send_email):
  954. """ Test the api_pull_request_close method of the flask api. """
  955. send_email.return_value = True
  956. tests.create_projects(self.session)
  957. tests.create_tokens(self.session)
  958. tests.create_tokens_acl(self.session)
  959. # Create the pull-request to close
  960. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  961. forked_repo = pagure.lib.query.get_authorized_project(
  962. self.session, "test"
  963. )
  964. req = pagure.lib.query.new_pull_request(
  965. session=self.session,
  966. repo_from=forked_repo,
  967. branch_from="master",
  968. repo_to=repo,
  969. branch_to="master",
  970. title="test pull-request",
  971. user="pingou",
  972. )
  973. self.session.commit()
  974. self.assertEqual(req.id, 1)
  975. self.assertEqual(req.title, "test pull-request")
  976. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  977. settings = repo.settings
  978. settings["pull_requests"] = False
  979. repo.settings = settings
  980. self.session.add(repo)
  981. self.session.commit()
  982. headers = {"Authorization": "token aaabbbcccddd"}
  983. output = self.app.post(
  984. "/api/0/test/pull-request/1/close", headers=headers
  985. )
  986. self.assertEqual(output.status_code, 404)
  987. data = json.loads(output.get_data(as_text=True))
  988. self.assertDictEqual(
  989. data,
  990. {
  991. "error": "Pull-Request have been deactivated for this project",
  992. "error_code": "EPULLREQUESTSDISABLED",
  993. },
  994. )
  995. @patch("pagure.lib.notify.send_email")
  996. def test_api_pull_request_close(self, send_email):
  997. """ Test the api_pull_request_close method of the flask api. """
  998. send_email.return_value = True
  999. tests.create_projects(self.session)
  1000. tests.create_tokens(self.session)
  1001. tests.create_tokens_acl(self.session)
  1002. # Create the pull-request to close
  1003. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  1004. forked_repo = pagure.lib.query.get_authorized_project(
  1005. self.session, "test"
  1006. )
  1007. req = pagure.lib.query.new_pull_request(
  1008. session=self.session,
  1009. repo_from=forked_repo,
  1010. branch_from="master",
  1011. repo_to=repo,
  1012. branch_to="master",
  1013. title="test pull-request",
  1014. user="pingou",
  1015. )
  1016. self.session.commit()
  1017. self.assertEqual(req.id, 1)
  1018. self.assertEqual(req.title, "test pull-request")
  1019. headers = {"Authorization": "token aaabbbcccddd"}
  1020. # Invalid project
  1021. output = self.app.post(
  1022. "/api/0/foo/pull-request/1/close", headers=headers
  1023. )
  1024. self.assertEqual(output.status_code, 404)
  1025. data = json.loads(output.get_data(as_text=True))
  1026. self.assertDictEqual(
  1027. data, {"error": "Project not found", "error_code": "ENOPROJECT"}
  1028. )
  1029. # Valid token, wrong project
  1030. output = self.app.post(
  1031. "/api/0/test2/pull-request/1/close", headers=headers
  1032. )
  1033. self.assertEqual(output.status_code, 401)
  1034. data = json.loads(output.get_data(as_text=True))
  1035. self.assertEqual(
  1036. pagure.api.APIERROR.EINVALIDTOK.name, data["error_code"]
  1037. )
  1038. self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.value, data["error"])
  1039. # Invalid PR
  1040. output = self.app.post(
  1041. "/api/0/test/pull-request/2/close", headers=headers
  1042. )
  1043. self.assertEqual(output.status_code, 404)
  1044. data = json.loads(output.get_data(as_text=True))
  1045. self.assertDictEqual(
  1046. data, {"error": "Pull-Request not found", "error_code": "ENOREQ"}
  1047. )
  1048. # Create a token for foo for this project
  1049. item = pagure.lib.model.Token(
  1050. id="foobar_token",
  1051. user_id=2,
  1052. project_id=1,
  1053. expiration=datetime.datetime.utcnow()
  1054. + datetime.timedelta(days=30),
  1055. )
  1056. self.session.add(item)
  1057. self.session.commit()
  1058. # Allow the token to close PR
  1059. acls = pagure.lib.query.get_acls(self.session)
  1060. for acl in acls:
  1061. if acl.name == "pull_request_close":
  1062. break
  1063. item = pagure.lib.model.TokenAcl(
  1064. token_id="foobar_token", acl_id=acl.id
  1065. )
  1066. self.session.add(item)
  1067. self.session.commit()
  1068. headers = {"Authorization": "token foobar_token"}
  1069. # User not admin
  1070. output = self.app.post(
  1071. "/api/0/test/pull-request/1/close", headers=headers
  1072. )
  1073. self.assertEqual(output.status_code, 403)
  1074. data = json.loads(output.get_data(as_text=True))
  1075. self.assertDictEqual(
  1076. data,
  1077. {
  1078. "error": "You are not allowed to merge/close pull-request "
  1079. "for this project",
  1080. "error_code": "ENOPRCLOSE",
  1081. },
  1082. )
  1083. headers = {"Authorization": "token aaabbbcccddd"}
  1084. # Close PR
  1085. output = self.app.post(
  1086. "/api/0/test/pull-request/1/close", headers=headers
  1087. )
  1088. self.assertEqual(output.status_code, 200)
  1089. data = json.loads(output.get_data(as_text=True))
  1090. self.assertDictEqual(data, {"message": "Pull-request closed!"})
  1091. @patch("pagure.lib.notify.send_email")
  1092. def test_api_pull_request_merge_pr_disabled(self, send_email):
  1093. """ Test the api_pull_request_merge method of the flask api when PR
  1094. are disabled. """
  1095. send_email.return_value = True
  1096. tests.create_projects(self.session)
  1097. tests.create_projects_git(os.path.join(self.path, "repos"), bare=True)
  1098. tests.create_projects_git(
  1099. os.path.join(self.path, "requests"), bare=True
  1100. )
  1101. tests.add_readme_git_repo(os.path.join(self.path, "repos", "test.git"))
  1102. tests.add_commit_git_repo(
  1103. os.path.join(self.path, "repos", "test.git"), branch="test"
  1104. )
  1105. tests.create_tokens(self.session)
  1106. tests.create_tokens_acl(self.session)
  1107. # Create the pull-request to close
  1108. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  1109. forked_repo = pagure.lib.query.get_authorized_project(
  1110. self.session, "test"
  1111. )
  1112. req = pagure.lib.query.new_pull_request(
  1113. session=self.session,
  1114. repo_from=forked_repo,
  1115. branch_from="test",
  1116. repo_to=repo,
  1117. branch_to="master",
  1118. title="test pull-request",
  1119. user="pingou",
  1120. )
  1121. self.session.commit()
  1122. self.assertEqual(req.id, 1)
  1123. self.assertEqual(req.title, "test pull-request")
  1124. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  1125. settings = repo.settings
  1126. settings["pull_requests"] = False
  1127. repo.settings = settings
  1128. self.session.add(repo)
  1129. self.session.commit()
  1130. headers = {"Authorization": "token aaabbbcccddd"}
  1131. output = self.app.post(
  1132. "/api/0/test/pull-request/1/merge", headers=headers
  1133. )
  1134. self.assertEqual(output.status_code, 404)
  1135. data = json.loads(output.get_data(as_text=True))
  1136. self.assertDictEqual(
  1137. data,
  1138. {
  1139. "error": "Pull-Request have been deactivated for this project",
  1140. "error_code": "EPULLREQUESTSDISABLED",
  1141. },
  1142. )
  1143. @patch("pagure.lib.notify.send_email")
  1144. def test_api_pull_request_merge_only_assigned(self, send_email):
  1145. """ Test the api_pull_request_merge method of the flask api when
  1146. only assignee can merge the PR and the PR isn't assigned. """
  1147. send_email.return_value = True
  1148. tests.create_projects(self.session)
  1149. tests.create_projects_git(os.path.join(self.path, "repos"), bare=True)
  1150. tests.create_projects_git(
  1151. os.path.join(self.path, "requests"), bare=True
  1152. )
  1153. tests.add_readme_git_repo(os.path.join(self.path, "repos", "test.git"))
  1154. tests.add_commit_git_repo(
  1155. os.path.join(self.path, "repos", "test.git"), branch="test"
  1156. )
  1157. tests.create_tokens(self.session)
  1158. tests.create_tokens_acl(self.session)
  1159. # Create the pull-request to close
  1160. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  1161. forked_repo = pagure.lib.query.get_authorized_project(
  1162. self.session, "test"
  1163. )
  1164. req = pagure.lib.query.new_pull_request(
  1165. session=self.session,
  1166. repo_from=forked_repo,
  1167. branch_from="test",
  1168. repo_to=repo,
  1169. branch_to="master",
  1170. title="test pull-request",
  1171. user="pingou",
  1172. )
  1173. self.session.commit()
  1174. self.assertEqual(req.id, 1)
  1175. self.assertEqual(req.title, "test pull-request")
  1176. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  1177. settings = repo.settings
  1178. settings["Only_assignee_can_merge_pull-request"] = True
  1179. repo.settings = settings
  1180. self.session.add(repo)
  1181. self.session.commit()
  1182. headers = {"Authorization": "token aaabbbcccddd"}
  1183. output = self.app.post(
  1184. "/api/0/test/pull-request/1/merge", headers=headers
  1185. )
  1186. self.assertEqual(output.status_code, 403)
  1187. data = json.loads(output.get_data(as_text=True))
  1188. self.assertDictEqual(
  1189. data,
  1190. {
  1191. "error": "This request must be assigned to be merged",
  1192. "error_code": "ENOTASSIGNED",
  1193. },
  1194. )
  1195. @patch("pagure.lib.notify.send_email")
  1196. def test_api_pull_request_merge_only_assigned_not_assignee(
  1197. self, send_email
  1198. ):
  1199. """ Test the api_pull_request_merge method of the flask api when
  1200. only assignee can merge the PR and the PR isn't assigned to the
  1201. user asking to merge. """
  1202. send_email.return_value = True
  1203. tests.create_projects(self.session)
  1204. tests.create_projects_git(os.path.join(self.path, "repos"), bare=True)
  1205. tests.create_projects_git(
  1206. os.path.join(self.path, "requests"), bare=True
  1207. )
  1208. tests.add_readme_git_repo(os.path.join(self.path, "repos", "test.git"))
  1209. tests.add_commit_git_repo(
  1210. os.path.join(self.path, "repos", "test.git"), branch="test"
  1211. )
  1212. tests.create_tokens(self.session)
  1213. tests.create_tokens_acl(self.session)
  1214. # Create the pull-request to close
  1215. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  1216. forked_repo = pagure.lib.query.get_authorized_project(
  1217. self.session, "test"
  1218. )
  1219. req = pagure.lib.query.new_pull_request(
  1220. session=self.session,
  1221. repo_from=forked_repo,
  1222. branch_from="test",
  1223. repo_to=repo,
  1224. branch_to="master",
  1225. title="test pull-request",
  1226. user="pingou",
  1227. )
  1228. self.session.commit()
  1229. self.assertEqual(req.id, 1)
  1230. self.assertEqual(req.title, "test pull-request")
  1231. req.assignee = pagure.lib.query.search_user(self.session, "foo")
  1232. self.session.add(req)
  1233. self.session.commit()
  1234. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  1235. settings = repo.settings
  1236. settings["Only_assignee_can_merge_pull-request"] = True
  1237. repo.settings = settings
  1238. self.session.add(repo)
  1239. self.session.commit()
  1240. headers = {"Authorization": "token aaabbbcccddd"}
  1241. output = self.app.post(
  1242. "/api/0/test/pull-request/1/merge", headers=headers
  1243. )
  1244. self.assertEqual(output.status_code, 403)
  1245. data = json.loads(output.get_data(as_text=True))
  1246. self.assertDictEqual(
  1247. data,
  1248. {
  1249. "error": "Only the assignee can merge this request",
  1250. "error_code": "ENOTASSIGNEE",
  1251. },
  1252. )
  1253. @patch("pagure.lib.notify.send_email")
  1254. def test_api_pull_request_merge_minimal_score(self, send_email):
  1255. """ Test the api_pull_request_merge method of the flask api when
  1256. a PR requires a certain minimal score to be merged. """
  1257. send_email.return_value = True
  1258. tests.create_projects(self.session)
  1259. tests.create_projects_git(os.path.join(self.path, "repos"), bare=True)
  1260. tests.create_projects_git(
  1261. os.path.join(self.path, "requests"), bare=True
  1262. )
  1263. tests.add_readme_git_repo(os.path.join(self.path, "repos", "test.git"))
  1264. tests.add_commit_git_repo(
  1265. os.path.join(self.path, "repos", "test.git"), branch="test"
  1266. )
  1267. tests.create_tokens(self.session)
  1268. tests.create_tokens_acl(self.session)
  1269. # Create the pull-request to close
  1270. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  1271. forked_repo = pagure.lib.query.get_authorized_project(
  1272. self.session, "test"
  1273. )
  1274. req = pagure.lib.query.new_pull_request(
  1275. session=self.session,
  1276. repo_from=forked_repo,
  1277. branch_from="test",
  1278. repo_to=repo,
  1279. branch_to="master",
  1280. title="test pull-request",
  1281. user="pingou",
  1282. )
  1283. self.session.commit()
  1284. self.assertEqual(req.id, 1)
  1285. self.assertEqual(req.title, "test pull-request")
  1286. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  1287. settings = repo.settings
  1288. settings["Minimum_score_to_merge_pull-request"] = 2
  1289. repo.settings = settings
  1290. self.session.add(repo)
  1291. self.session.commit()
  1292. headers = {"Authorization": "token aaabbbcccddd"}
  1293. output = self.app.post(
  1294. "/api/0/test/pull-request/1/merge", headers=headers
  1295. )
  1296. self.assertEqual(output.status_code, 403)
  1297. data = json.loads(output.get_data(as_text=True))
  1298. self.assertDictEqual(
  1299. data,
  1300. {
  1301. "error": "This request does not have the minimum review "
  1302. "score necessary to be merged",
  1303. "error_code": "EPRSCORE",
  1304. },
  1305. )
  1306. @patch("pagure.lib.notify.send_email")
  1307. def test_api_pull_request_merge(self, send_email):
  1308. """ Test the api_pull_request_merge method of the flask api. """
  1309. send_email.return_value = True
  1310. tests.create_projects(self.session)
  1311. tests.create_projects_git(os.path.join(self.path, "repos"), bare=True)
  1312. tests.create_projects_git(
  1313. os.path.join(self.path, "requests"), bare=True
  1314. )
  1315. tests.add_readme_git_repo(os.path.join(self.path, "repos", "test.git"))
  1316. tests.add_commit_git_repo(
  1317. os.path.join(self.path, "repos", "test.git"), branch="test"
  1318. )
  1319. tests.create_tokens(self.session)
  1320. tests.create_tokens_acl(self.session)
  1321. # Create the pull-request to close
  1322. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  1323. forked_repo = pagure.lib.query.get_authorized_project(
  1324. self.session, "test"
  1325. )
  1326. req = pagure.lib.query.new_pull_request(
  1327. session=self.session,
  1328. repo_from=forked_repo,
  1329. branch_from="test",
  1330. repo_to=repo,
  1331. branch_to="master",
  1332. title="test pull-request",
  1333. user="pingou",
  1334. )
  1335. self.session.commit()
  1336. self.assertEqual(req.id, 1)
  1337. self.assertEqual(req.title, "test pull-request")
  1338. headers = {"Authorization": "token aaabbbcccddd"}
  1339. # Invalid project
  1340. output = self.app.post(
  1341. "/api/0/foo/pull-request/1/merge", headers=headers
  1342. )
  1343. self.assertEqual(output.status_code, 404)
  1344. data = json.loads(output.get_data(as_text=True))
  1345. self.assertDictEqual(
  1346. data, {"error": "Project not found", "error_code": "ENOPROJECT"}
  1347. )
  1348. # Valid token, wrong project
  1349. output = self.app.post(
  1350. "/api/0/test2/pull-request/1/merge", headers=headers
  1351. )
  1352. self.assertEqual(output.status_code, 401)
  1353. data = json.loads(output.get_data(as_text=True))
  1354. self.assertEqual(
  1355. pagure.api.APIERROR.EINVALIDTOK.name, data["error_code"]
  1356. )
  1357. self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.value, data["error"])
  1358. # Invalid PR
  1359. output = self.app.post(
  1360. "/api/0/test/pull-request/2/merge", headers=headers
  1361. )
  1362. self.assertEqual(output.status_code, 404)
  1363. data = json.loads(output.get_data(as_text=True))
  1364. self.assertDictEqual(
  1365. data, {"error": "Pull-Request not found", "error_code": "ENOREQ"}
  1366. )
  1367. # Create a token for foo for this project
  1368. item = pagure.lib.model.Token(
  1369. id="foobar_token",
  1370. user_id=2,
  1371. project_id=1,
  1372. expiration=datetime.datetime.utcnow()
  1373. + datetime.timedelta(days=30),
  1374. )
  1375. self.session.add(item)
  1376. self.session.commit()
  1377. # Allow the token to merge PR
  1378. acls = pagure.lib.query.get_acls(self.session)
  1379. for acl in acls:
  1380. if acl.name == "pull_request_merge":
  1381. break
  1382. item = pagure.lib.model.TokenAcl(
  1383. token_id="foobar_token", acl_id=acl.id
  1384. )
  1385. self.session.add(item)
  1386. self.session.commit()
  1387. headers = {"Authorization": "token foobar_token"}
  1388. # User not admin
  1389. output = self.app.post(
  1390. "/api/0/test/pull-request/1/merge", headers=headers
  1391. )
  1392. self.assertEqual(output.status_code, 403)
  1393. data = json.loads(output.get_data(as_text=True))
  1394. self.assertDictEqual(
  1395. data,
  1396. {
  1397. "error": "You are not allowed to merge/close pull-request "
  1398. "for this project",
  1399. "error_code": "ENOPRCLOSE",
  1400. },
  1401. )
  1402. headers = {"Authorization": "token aaabbbcccddd"}
  1403. # Merge PR
  1404. output = self.app.post(
  1405. "/api/0/test/pull-request/1/merge", headers=headers
  1406. )
  1407. self.assertEqual(output.status_code, 200)
  1408. data = json.loads(output.get_data(as_text=True))
  1409. self.assertDictEqual(data, {"message": "Changes merged!"})
  1410. @patch("pagure.lib.notify.send_email")
  1411. def test_api_pull_request_merge_conflicting(self, send_email):
  1412. """ Test the api_pull_request_merge method of the flask api. """
  1413. send_email.return_value = True
  1414. tests.create_projects(self.session)
  1415. tests.add_content_git_repo(
  1416. os.path.join(self.path, "repos", "test.git")
  1417. )
  1418. # Fork
  1419. project = pagure.lib.query.get_authorized_project(self.session, "test")
  1420. task = pagure.lib.query.fork_project(
  1421. session=self.session, user="pingou", repo=project
  1422. )
  1423. self.session.commit()
  1424. self.assertEqual(
  1425. task.get(),
  1426. {
  1427. "endpoint": "ui_ns.view_repo",
  1428. "repo": "test",
  1429. "namespace": None,
  1430. "username": "pingou",
  1431. },
  1432. )
  1433. # Add content to the fork
  1434. tests.add_content_to_git(
  1435. os.path.join(self.path, "repos", "forks", "pingou", "test.git"),
  1436. filename="foobar",
  1437. content="content from the fork",
  1438. )
  1439. # Add content to the main repo, so they conflict
  1440. tests.add_content_to_git(
  1441. os.path.join(self.path, "repos", "test.git"),
  1442. filename="foobar",
  1443. content="content from the main repo",
  1444. )
  1445. project = pagure.lib.query.get_authorized_project(self.session, "test")
  1446. fork = pagure.lib.query.get_authorized_project(
  1447. self.session, "test", user="pingou"
  1448. )
  1449. tests.create_tokens(self.session)
  1450. tests.create_tokens_acl(self.session)
  1451. # Create the pull-request to close
  1452. req = pagure.lib.query.new_pull_request(
  1453. session=self.session,
  1454. repo_from=fork,
  1455. branch_from="master",
  1456. repo_to=project,
  1457. branch_to="master",
  1458. title="test pull-request",
  1459. user="pingou",
  1460. )
  1461. self.session.commit()
  1462. self.assertEqual(req.id, 1)
  1463. self.assertEqual(req.title, "test pull-request")
  1464. headers = {"Authorization": "token aaabbbcccddd"}
  1465. # Merge PR
  1466. output = self.app.post(
  1467. "/api/0/test/pull-request/1/merge", headers=headers
  1468. )
  1469. self.assertEqual(output.status_code, 409)
  1470. data = json.loads(output.get_data(as_text=True))
  1471. self.assertDictEqual(
  1472. data,
  1473. {
  1474. "error": "This pull-request conflicts and thus cannot be merged",
  1475. "error_code": "EPRCONFLICTS",
  1476. },
  1477. )
  1478. @patch("pagure.lib.notify.send_email")
  1479. def test_api_pull_request_merge_user_token(self, send_email):
  1480. """ Test the api_pull_request_merge method of the flask api. """
  1481. send_email.return_value = True
  1482. tests.create_projects(self.session)
  1483. tests.create_projects_git(os.path.join(self.path, "repos"), bare=True)
  1484. tests.create_projects_git(
  1485. os.path.join(self.path, "requests"), bare=True
  1486. )
  1487. tests.add_readme_git_repo(os.path.join(self.path, "repos", "test.git"))
  1488. tests.add_commit_git_repo(
  1489. os.path.join(self.path, "repos", "test.git"), branch="test"
  1490. )
  1491. tests.create_tokens(self.session, project_id=None)
  1492. tests.create_tokens_acl(self.session)
  1493. # Create the pull-request to close
  1494. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  1495. forked_repo = pagure.lib.query.get_authorized_project(
  1496. self.session, "test"
  1497. )
  1498. req = pagure.lib.query.new_pull_request(
  1499. session=self.session,
  1500. repo_from=forked_repo,
  1501. branch_from="test",
  1502. repo_to=repo,
  1503. branch_to="master",
  1504. title="test pull-request",
  1505. user="pingou",
  1506. )
  1507. self.session.commit()
  1508. self.assertEqual(req.id, 1)
  1509. self.assertEqual(req.title, "test pull-request")
  1510. headers = {"Authorization": "token aaabbbcccddd"}
  1511. # Invalid project
  1512. output = self.app.post(
  1513. "/api/0/foo/pull-request/1/merge", headers=headers
  1514. )
  1515. self.assertEqual(output.status_code, 404)
  1516. data = json.loads(output.get_data(as_text=True))
  1517. self.assertDictEqual(
  1518. data, {"error": "Project not found", "error_code": "ENOPROJECT"}
  1519. )
  1520. # Valid token, invalid PR
  1521. output = self.app.post(
  1522. "/api/0/test2/pull-request/1/merge", headers=headers
  1523. )
  1524. self.assertEqual(output.status_code, 404)
  1525. data = json.loads(output.get_data(as_text=True))
  1526. self.assertDictEqual(
  1527. data, {"error": "Pull-Request not found", "error_code": "ENOREQ"}
  1528. )
  1529. # Valid token, invalid PR - other project
  1530. output = self.app.post(
  1531. "/api/0/test/pull-request/2/merge", headers=headers
  1532. )
  1533. self.assertEqual(output.status_code, 404)
  1534. data = json.loads(output.get_data(as_text=True))
  1535. self.assertDictEqual(
  1536. data, {"error": "Pull-Request not found", "error_code": "ENOREQ"}
  1537. )
  1538. # Create a token for foo for this project
  1539. item = pagure.lib.model.Token(
  1540. id="foobar_token",
  1541. user_id=2,
  1542. project_id=1,
  1543. expiration=datetime.datetime.utcnow()
  1544. + datetime.timedelta(days=30),
  1545. )
  1546. self.session.add(item)
  1547. self.session.commit()
  1548. # Allow the token to merge PR
  1549. acls = pagure.lib.query.get_acls(self.session)
  1550. acl = None
  1551. for acl in acls:
  1552. if acl.name == "pull_request_merge":
  1553. break
  1554. item = pagure.lib.model.TokenAcl(
  1555. token_id="foobar_token", acl_id=acl.id
  1556. )
  1557. self.session.add(item)
  1558. self.session.commit()
  1559. headers = {"Authorization": "token foobar_token"}
  1560. # User not admin
  1561. output = self.app.post(
  1562. "/api/0/test/pull-request/1/merge", headers=headers
  1563. )
  1564. self.assertEqual(output.status_code, 403)
  1565. data = json.loads(output.get_data(as_text=True))
  1566. self.assertDictEqual(
  1567. data,
  1568. {
  1569. "error": "You are not allowed to merge/close pull-request "
  1570. "for this project",
  1571. "error_code": "ENOPRCLOSE",
  1572. },
  1573. )
  1574. headers = {"Authorization": "token aaabbbcccddd"}
  1575. # Merge PR
  1576. output = self.app.post(
  1577. "/api/0/test/pull-request/1/merge", headers=headers
  1578. )
  1579. self.assertEqual(output.status_code, 200)
  1580. data = json.loads(output.get_data(as_text=True))
  1581. self.assertDictEqual(data, {"message": "Changes merged!"})
  1582. @patch("pagure.lib.notify.send_email")
  1583. def test_api_pull_request_add_comment(self, mockemail):
  1584. """ Test the api_pull_request_add_comment method of the flask api. """
  1585. mockemail.return_value = True
  1586. tests.create_projects(self.session)
  1587. tests.create_tokens(self.session)
  1588. tests.create_tokens_acl(self.session)
  1589. headers = {"Authorization": "token aaabbbcccddd"}
  1590. # Invalid project
  1591. output = self.app.post(
  1592. "/api/0/foo/pull-request/1/comment", headers=headers
  1593. )
  1594. self.assertEqual(output.status_code, 404)
  1595. data = json.loads(output.get_data(as_text=True))
  1596. self.assertDictEqual(
  1597. data, {"error": "Project not found", "error_code": "ENOPROJECT"}
  1598. )
  1599. # Valid token, wrong project
  1600. output = self.app.post(
  1601. "/api/0/test2/pull-request/1/comment", headers=headers
  1602. )
  1603. self.assertEqual(output.status_code, 401)
  1604. data = json.loads(output.get_data(as_text=True))
  1605. self.assertEqual(
  1606. pagure.api.APIERROR.EINVALIDTOK.name, data["error_code"]
  1607. )
  1608. self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.value, data["error"])
  1609. # No input
  1610. output = self.app.post(
  1611. "/api/0/test/pull-request/1/comment", headers=headers
  1612. )
  1613. self.assertEqual(output.status_code, 404)
  1614. data = json.loads(output.get_data(as_text=True))
  1615. self.assertDictEqual(
  1616. data, {"error": "Pull-Request not found", "error_code": "ENOREQ"}
  1617. )
  1618. # Create a pull-request
  1619. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  1620. forked_repo = pagure.lib.query.get_authorized_project(
  1621. self.session, "test"
  1622. )
  1623. req = pagure.lib.query.new_pull_request(
  1624. session=self.session,
  1625. repo_from=forked_repo,
  1626. branch_from="master",
  1627. repo_to=repo,
  1628. branch_to="master",
  1629. title="test pull-request",
  1630. user="pingou",
  1631. )
  1632. self.session.commit()
  1633. self.assertEqual(req.id, 1)
  1634. self.assertEqual(req.title, "test pull-request")
  1635. # Check comments before
  1636. self.session.commit()
  1637. request = pagure.lib.query.search_pull_requests(
  1638. self.session, project_id=1, requestid=1
  1639. )
  1640. self.assertEqual(len(request.comments), 0)
  1641. data = {"title": "test issue"}
  1642. # Incomplete request
  1643. output = self.app.post(
  1644. "/api/0/test/pull-request/1/comment", data=data, headers=headers
  1645. )
  1646. self.assertEqual(output.status_code, 400)
  1647. data = json.loads(output.get_data(as_text=True))
  1648. self.assertDictEqual(
  1649. data,
  1650. {
  1651. "error": "Invalid or incomplete input submitted",
  1652. "error_code": "EINVALIDREQ",
  1653. "errors": {"comment": ["This field is required."]},
  1654. },
  1655. )
  1656. # No change
  1657. self.session.commit()
  1658. request = pagure.lib.query.search_pull_requests(
  1659. self.session, project_id=1, requestid=1
  1660. )
  1661. self.assertEqual(len(request.comments), 0)
  1662. data = {"comment": "This is a very interesting question"}
  1663. # Valid request
  1664. output = self.app.post(
  1665. "/api/0/test/pull-request/1/comment", data=data, headers=headers
  1666. )
  1667. self.assertEqual(output.status_code, 200)
  1668. data = json.loads(output.get_data(as_text=True))
  1669. self.assertDictEqual(data, {"message": "Comment added"})
  1670. # One comment added
  1671. self.session.commit()
  1672. request = pagure.lib.query.search_pull_requests(
  1673. self.session, project_id=1, requestid=1
  1674. )
  1675. self.assertEqual(len(request.comments), 1)
  1676. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  1677. def test_api_pull_request_add_comment_wrong_user(self):
  1678. """ Test the api_pull_request_add_comment method of the flask api
  1679. when the user is not found in the DB. """
  1680. tests.create_projects(self.session)
  1681. tests.create_tokens(self.session, project_id=None)
  1682. tests.create_tokens_acl(self.session)
  1683. headers = {"Authorization": "token aaabbbcccddd"}
  1684. # Create a pull-request
  1685. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  1686. forked_repo = pagure.lib.query.get_authorized_project(
  1687. self.session, "test"
  1688. )
  1689. req = pagure.lib.query.new_pull_request(
  1690. session=self.session,
  1691. repo_from=forked_repo,
  1692. branch_from="master",
  1693. repo_to=repo,
  1694. branch_to="master",
  1695. title="test pull-request",
  1696. user="pingou",
  1697. )
  1698. self.session.commit()
  1699. self.assertEqual(req.id, 1)
  1700. self.assertEqual(req.title, "test pull-request")
  1701. data = {"comment": "This is a very interesting question"}
  1702. # Valid request
  1703. with patch(
  1704. "pagure.lib.query.add_pull_request_comment",
  1705. side_effect=pagure.exceptions.PagureException("error"),
  1706. ):
  1707. output = self.app.post(
  1708. "/api/0/test/pull-request/1/comment",
  1709. data=data,
  1710. headers=headers,
  1711. )
  1712. self.assertEqual(output.status_code, 400)
  1713. data = json.loads(output.get_data(as_text=True))
  1714. self.assertDictEqual(
  1715. data, {"error": "error", "error_code": "ENOCODE"}
  1716. )
  1717. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  1718. def test_api_pull_request_add_comment_pr_disabled(self):
  1719. """ Test the api_pull_request_add_comment method of the flask api
  1720. when PRs are disabled. """
  1721. tests.create_projects(self.session)
  1722. tests.create_tokens(self.session, project_id=None)
  1723. tests.create_tokens_acl(self.session)
  1724. headers = {"Authorization": "token aaabbbcccddd"}
  1725. # Create a pull-request
  1726. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  1727. forked_repo = pagure.lib.query.get_authorized_project(
  1728. self.session, "test"
  1729. )
  1730. req = pagure.lib.query.new_pull_request(
  1731. session=self.session,
  1732. repo_from=forked_repo,
  1733. branch_from="master",
  1734. repo_to=repo,
  1735. branch_to="master",
  1736. title="test pull-request",
  1737. user="pingou",
  1738. )
  1739. self.session.commit()
  1740. self.assertEqual(req.id, 1)
  1741. self.assertEqual(req.title, "test pull-request")
  1742. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  1743. settings = repo.settings
  1744. settings["pull_requests"] = False
  1745. repo.settings = settings
  1746. self.session.add(repo)
  1747. self.session.commit()
  1748. data = {"comment": "This is a very interesting question"}
  1749. # Valid request
  1750. output = self.app.post(
  1751. "/api/0/test/pull-request/1/comment", data=data, headers=headers
  1752. )
  1753. self.assertEqual(output.status_code, 404)
  1754. data = json.loads(output.get_data(as_text=True))
  1755. self.assertDictEqual(
  1756. data,
  1757. {
  1758. "error": "Pull-Request have been deactivated for this project",
  1759. "error_code": "EPULLREQUESTSDISABLED",
  1760. },
  1761. )
  1762. # no comment added
  1763. self.session.commit()
  1764. request = pagure.lib.query.search_pull_requests(
  1765. self.session, project_id=1, requestid=1
  1766. )
  1767. self.assertEqual(len(request.comments), 0)
  1768. @patch("pagure.lib.notify.send_email")
  1769. def test_api_pull_request_add_comment_user_token(self, mockemail):
  1770. """ Test the api_pull_request_add_comment method of the flask api. """
  1771. mockemail.return_value = True
  1772. tests.create_projects(self.session)
  1773. tests.create_tokens(self.session, project_id=None)
  1774. tests.create_tokens_acl(self.session)
  1775. headers = {"Authorization": "token aaabbbcccddd"}
  1776. # Invalid project
  1777. output = self.app.post(
  1778. "/api/0/foo/pull-request/1/comment", headers=headers
  1779. )
  1780. self.assertEqual(output.status_code, 404)
  1781. data = json.loads(output.get_data(as_text=True))
  1782. self.assertDictEqual(
  1783. data, {"error": "Project not found", "error_code": "ENOPROJECT"}
  1784. )
  1785. # Valid token, invalid request
  1786. output = self.app.post(
  1787. "/api/0/test2/pull-request/1/comment", headers=headers
  1788. )
  1789. self.assertEqual(output.status_code, 404)
  1790. data = json.loads(output.get_data(as_text=True))
  1791. self.assertDictEqual(
  1792. data, {"error": "Pull-Request not found", "error_code": "ENOREQ"}
  1793. )
  1794. # Valid token, invalid request in another project
  1795. output = self.app.post(
  1796. "/api/0/test/pull-request/1/comment", headers=headers
  1797. )
  1798. self.assertEqual(output.status_code, 404)
  1799. data = json.loads(output.get_data(as_text=True))
  1800. self.assertDictEqual(
  1801. data, {"error": "Pull-Request not found", "error_code": "ENOREQ"}
  1802. )
  1803. # Create a pull-request
  1804. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  1805. forked_repo = pagure.lib.query.get_authorized_project(
  1806. self.session, "test"
  1807. )
  1808. req = pagure.lib.query.new_pull_request(
  1809. session=self.session,
  1810. repo_from=forked_repo,
  1811. branch_from="master",
  1812. repo_to=repo,
  1813. branch_to="master",
  1814. title="test pull-request",
  1815. user="pingou",
  1816. )
  1817. self.session.commit()
  1818. self.assertEqual(req.id, 1)
  1819. self.assertEqual(req.title, "test pull-request")
  1820. # Check comments before
  1821. self.session.commit()
  1822. request = pagure.lib.query.search_pull_requests(
  1823. self.session, project_id=1, requestid=1
  1824. )
  1825. self.assertEqual(len(request.comments), 0)
  1826. data = {"title": "test issue"}
  1827. # Incomplete request
  1828. output = self.app.post(
  1829. "/api/0/test/pull-request/1/comment", data=data, headers=headers
  1830. )
  1831. self.assertEqual(output.status_code, 400)
  1832. data = json.loads(output.get_data(as_text=True))
  1833. self.assertDictEqual(
  1834. data,
  1835. {
  1836. "error": "Invalid or incomplete input submitted",
  1837. "error_code": "EINVALIDREQ",
  1838. "errors": {"comment": ["This field is required."]},
  1839. },
  1840. )
  1841. # No change
  1842. self.session.commit()
  1843. request = pagure.lib.query.search_pull_requests(
  1844. self.session, project_id=1, requestid=1
  1845. )
  1846. self.assertEqual(len(request.comments), 0)
  1847. data = {"comment": "This is a very interesting question"}
  1848. # Valid request
  1849. output = self.app.post(
  1850. "/api/0/test/pull-request/1/comment", data=data, headers=headers
  1851. )
  1852. self.assertEqual(output.status_code, 200)
  1853. data = json.loads(output.get_data(as_text=True))
  1854. self.assertDictEqual(data, {"message": "Comment added"})
  1855. # One comment added
  1856. self.session.commit()
  1857. request = pagure.lib.query.search_pull_requests(
  1858. self.session, project_id=1, requestid=1
  1859. )
  1860. self.assertEqual(len(request.comments), 1)
  1861. @patch("pagure.lib.notify.send_email")
  1862. def test_api_subscribe_pull_request_pr_disabled(self, p_send_email):
  1863. """ Test the api_subscribe_pull_request method of the flask api. """
  1864. p_send_email.return_value = True
  1865. tests.create_projects(self.session)
  1866. tests.create_tokens(self.session)
  1867. tests.create_tokens_acl(self.session)
  1868. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  1869. settings = repo.settings
  1870. settings["pull_requests"] = False
  1871. repo.settings = settings
  1872. self.session.add(repo)
  1873. self.session.commit()
  1874. headers = {"Authorization": "token aaabbbcccddd"}
  1875. # Invalid project
  1876. output = self.app.post(
  1877. "/api/0/test/pull-request/1/subscribe", headers=headers
  1878. )
  1879. self.assertEqual(output.status_code, 404)
  1880. data = json.loads(output.get_data(as_text=True))
  1881. self.assertDictEqual(
  1882. data,
  1883. {
  1884. "error": "Pull-Request have been deactivated for this project",
  1885. "error_code": "EPULLREQUESTSDISABLED",
  1886. },
  1887. )
  1888. @patch("pagure.lib.git.update_git")
  1889. @patch("pagure.lib.notify.send_email")
  1890. def test_api_subscribe_pull_request_invalid_token(
  1891. self, p_send_email, p_ugt
  1892. ):
  1893. """ Test the api_subscribe_pull_request method of the flask api. """
  1894. p_send_email.return_value = True
  1895. p_ugt.return_value = True
  1896. item = pagure.lib.model.User(
  1897. user="bar",
  1898. fullname="bar foo",
  1899. password="foo",
  1900. default_email="bar@bar.com",
  1901. )
  1902. self.session.add(item)
  1903. item = pagure.lib.model.UserEmail(user_id=3, email="bar@bar.com")
  1904. self.session.add(item)
  1905. self.session.commit()
  1906. tests.create_projects(self.session)
  1907. tests.create_tokens(self.session, user_id=3, project_id=2)
  1908. tests.create_tokens_acl(self.session)
  1909. headers = {"Authorization": "token aaabbbcccddd"}
  1910. # Create pull-request
  1911. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  1912. req = pagure.lib.query.new_pull_request(
  1913. session=self.session,
  1914. repo_from=repo,
  1915. branch_from="feature",
  1916. repo_to=repo,
  1917. branch_to="master",
  1918. title="test pull-request",
  1919. user="pingou",
  1920. )
  1921. self.session.commit()
  1922. self.assertEqual(req.id, 1)
  1923. self.assertEqual(req.title, "test pull-request")
  1924. # Check subscribtion before
  1925. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  1926. request = pagure.lib.query.search_pull_requests(
  1927. self.session, project_id=1, requestid=1
  1928. )
  1929. self.assertEqual(
  1930. pagure.lib.query.get_watch_list(self.session, request),
  1931. set(["pingou"]),
  1932. )
  1933. data = {}
  1934. output = self.app.post(
  1935. "/api/0/test/pull-request/1/subscribe", data=data, headers=headers
  1936. )
  1937. self.assertEqual(output.status_code, 401)
  1938. data = json.loads(output.get_data(as_text=True))
  1939. self.assertDictEqual(
  1940. data,
  1941. {
  1942. "error": "Invalid or expired token. Please visit "
  1943. "http://localhost.localdomain/settings#nav-api-tab to get or "
  1944. "renew your API token.",
  1945. "error_code": "EINVALIDTOK",
  1946. },
  1947. )
  1948. @patch("pagure.lib.git.update_git")
  1949. @patch("pagure.lib.notify.send_email")
  1950. def test_api_subscribe_pull_request(self, p_send_email, p_ugt):
  1951. """ Test the api_subscribe_pull_request method of the flask api. """
  1952. p_send_email.return_value = True
  1953. p_ugt.return_value = True
  1954. item = pagure.lib.model.User(
  1955. user="bar",
  1956. fullname="bar foo",
  1957. password="foo",
  1958. default_email="bar@bar.com",
  1959. )
  1960. self.session.add(item)
  1961. item = pagure.lib.model.UserEmail(user_id=3, email="bar@bar.com")
  1962. self.session.add(item)
  1963. self.session.commit()
  1964. tests.create_projects(self.session)
  1965. tests.create_tokens(self.session, user_id=3)
  1966. tests.create_tokens_acl(self.session)
  1967. headers = {"Authorization": "token aaabbbcccddd"}
  1968. # Invalid project
  1969. output = self.app.post(
  1970. "/api/0/foo/pull-request/1/subscribe", headers=headers
  1971. )
  1972. self.assertEqual(output.status_code, 404)
  1973. data = json.loads(output.get_data(as_text=True))
  1974. self.assertDictEqual(
  1975. data, {"error": "Project not found", "error_code": "ENOPROJECT"}
  1976. )
  1977. # Valid token, wrong project
  1978. output = self.app.post(
  1979. "/api/0/test2/pull-request/1/subscribe", headers=headers
  1980. )
  1981. self.assertEqual(output.status_code, 401)
  1982. data = json.loads(output.get_data(as_text=True))
  1983. self.assertEqual(
  1984. pagure.api.APIERROR.EINVALIDTOK.name, data["error_code"]
  1985. )
  1986. self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.value, data["error"])
  1987. # No input
  1988. output = self.app.post(
  1989. "/api/0/test/pull-request/1/subscribe", headers=headers
  1990. )
  1991. self.assertEqual(output.status_code, 404)
  1992. data = json.loads(output.get_data(as_text=True))
  1993. self.assertDictEqual(
  1994. data, {"error": "Pull-Request not found", "error_code": "ENOREQ"}
  1995. )
  1996. # Create pull-request
  1997. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  1998. req = pagure.lib.query.new_pull_request(
  1999. session=self.session,
  2000. repo_from=repo,
  2001. branch_from="feature",
  2002. repo_to=repo,
  2003. branch_to="master",
  2004. title="test pull-request",
  2005. user="pingou",
  2006. )
  2007. self.session.commit()
  2008. self.assertEqual(req.id, 1)
  2009. self.assertEqual(req.title, "test pull-request")
  2010. # Check subscribtion before
  2011. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  2012. request = pagure.lib.query.search_pull_requests(
  2013. self.session, project_id=1, requestid=1
  2014. )
  2015. self.assertEqual(
  2016. pagure.lib.query.get_watch_list(self.session, request),
  2017. set(["pingou"]),
  2018. )
  2019. # Unsubscribe - no changes
  2020. data = {}
  2021. output = self.app.post(
  2022. "/api/0/test/pull-request/1/subscribe", data=data, headers=headers
  2023. )
  2024. self.assertEqual(output.status_code, 200)
  2025. data = json.loads(output.get_data(as_text=True))
  2026. data["avatar_url"] = "https://seccdn.libravatar.org/avatar/..."
  2027. self.assertDictEqual(
  2028. data,
  2029. {
  2030. "message": "You are no longer watching this pull-request",
  2031. "avatar_url": "https://seccdn.libravatar.org/avatar/...",
  2032. "user": "bar",
  2033. },
  2034. )
  2035. data = {}
  2036. output = self.app.post(
  2037. "/api/0/test/pull-request/1/subscribe", data=data, headers=headers
  2038. )
  2039. self.assertEqual(output.status_code, 200)
  2040. data = json.loads(output.get_data(as_text=True))
  2041. data["avatar_url"] = "https://seccdn.libravatar.org/avatar/..."
  2042. self.assertDictEqual(
  2043. data,
  2044. {
  2045. "message": "You are no longer watching this pull-request",
  2046. "avatar_url": "https://seccdn.libravatar.org/avatar/...",
  2047. "user": "bar",
  2048. },
  2049. )
  2050. # No change
  2051. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  2052. request = pagure.lib.query.search_pull_requests(
  2053. self.session, project_id=1, requestid=1
  2054. )
  2055. self.assertEqual(
  2056. pagure.lib.query.get_watch_list(self.session, request),
  2057. set(["pingou"]),
  2058. )
  2059. # Subscribe
  2060. data = {"status": True}
  2061. output = self.app.post(
  2062. "/api/0/test/pull-request/1/subscribe", data=data, headers=headers
  2063. )
  2064. self.assertEqual(output.status_code, 200)
  2065. data = json.loads(output.get_data(as_text=True))
  2066. data["avatar_url"] = "https://seccdn.libravatar.org/avatar/..."
  2067. self.assertDictEqual(
  2068. data,
  2069. {
  2070. "message": "You are now watching this pull-request",
  2071. "avatar_url": "https://seccdn.libravatar.org/avatar/...",
  2072. "user": "bar",
  2073. },
  2074. )
  2075. # Subscribe - no changes
  2076. data = {"status": True}
  2077. output = self.app.post(
  2078. "/api/0/test/pull-request/1/subscribe", data=data, headers=headers
  2079. )
  2080. self.assertEqual(output.status_code, 200)
  2081. data = json.loads(output.get_data(as_text=True))
  2082. data["avatar_url"] = "https://seccdn.libravatar.org/avatar/..."
  2083. self.assertDictEqual(
  2084. data,
  2085. {
  2086. "message": "You are now watching this pull-request",
  2087. "avatar_url": "https://seccdn.libravatar.org/avatar/...",
  2088. "user": "bar",
  2089. },
  2090. )
  2091. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  2092. request = pagure.lib.query.search_pull_requests(
  2093. self.session, project_id=1, requestid=1
  2094. )
  2095. self.assertEqual(
  2096. pagure.lib.query.get_watch_list(self.session, request),
  2097. set(["pingou", "bar"]),
  2098. )
  2099. # Unsubscribe
  2100. data = {}
  2101. output = self.app.post(
  2102. "/api/0/test/pull-request/1/subscribe", data=data, headers=headers
  2103. )
  2104. self.assertEqual(output.status_code, 200)
  2105. data = json.loads(output.get_data(as_text=True))
  2106. data["avatar_url"] = "https://seccdn.libravatar.org/avatar/..."
  2107. self.assertDictEqual(
  2108. data,
  2109. {
  2110. "message": "You are no longer watching this pull-request",
  2111. "avatar_url": "https://seccdn.libravatar.org/avatar/...",
  2112. "user": "bar",
  2113. },
  2114. )
  2115. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  2116. request = pagure.lib.query.search_pull_requests(
  2117. self.session, project_id=1, requestid=1
  2118. )
  2119. self.assertEqual(
  2120. pagure.lib.query.get_watch_list(self.session, request),
  2121. set(["pingou"]),
  2122. )
  2123. @patch("pagure.lib.git.update_git")
  2124. @patch("pagure.lib.notify.send_email")
  2125. def test_api_subscribe_pull_request_logged_in(self, p_send_email, p_ugt):
  2126. """ Test the api_subscribe_pull_request method of the flask api
  2127. when the user is logged in via the UI. """
  2128. p_send_email.return_value = True
  2129. p_ugt.return_value = True
  2130. item = pagure.lib.model.User(
  2131. user="bar",
  2132. fullname="bar foo",
  2133. password="foo",
  2134. default_email="bar@bar.com",
  2135. )
  2136. self.session.add(item)
  2137. item = pagure.lib.model.UserEmail(user_id=3, email="bar@bar.com")
  2138. self.session.add(item)
  2139. self.session.commit()
  2140. tests.create_projects(self.session)
  2141. tests.create_tokens(self.session, user_id=3)
  2142. tests.create_tokens_acl(self.session)
  2143. # Create pull-request
  2144. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  2145. req = pagure.lib.query.new_pull_request(
  2146. session=self.session,
  2147. repo_from=repo,
  2148. branch_from="feature",
  2149. repo_to=repo,
  2150. branch_to="master",
  2151. title="test pull-request",
  2152. user="pingou",
  2153. )
  2154. self.session.commit()
  2155. self.assertEqual(req.id, 1)
  2156. self.assertEqual(req.title, "test pull-request")
  2157. # Check subscribtion before
  2158. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  2159. request = pagure.lib.query.search_pull_requests(
  2160. self.session, project_id=1, requestid=1
  2161. )
  2162. self.assertEqual(
  2163. pagure.lib.query.get_watch_list(self.session, request),
  2164. set(["pingou"]),
  2165. )
  2166. # Subscribe
  2167. user = tests.FakeUser(username="foo")
  2168. with tests.user_set(self.app.application, user):
  2169. data = {"status": True}
  2170. output = self.app.post(
  2171. "/api/0/test/pull-request/1/subscribe", data=data
  2172. )
  2173. self.assertEqual(output.status_code, 200)
  2174. data = json.loads(output.get_data(as_text=True))
  2175. data["avatar_url"] = "https://seccdn.libravatar.org/avatar/..."
  2176. self.assertDictEqual(
  2177. data,
  2178. {
  2179. "message": "You are now watching this pull-request",
  2180. "avatar_url": "https://seccdn.libravatar.org/avatar/...",
  2181. "user": "foo",
  2182. },
  2183. )
  2184. # Check subscribtions after
  2185. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  2186. request = pagure.lib.query.search_pull_requests(
  2187. self.session, project_id=1, requestid=1
  2188. )
  2189. self.assertEqual(
  2190. pagure.lib.query.get_watch_list(self.session, request),
  2191. set(["pingou", "foo"]),
  2192. )
  2193. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  2194. def test_api_pull_request_open_invalid_project(self):
  2195. """ Test the api_pull_request_create method of the flask api when
  2196. not the project doesn't exist.
  2197. """
  2198. tests.create_projects(self.session)
  2199. tests.create_projects_git(os.path.join(self.path, "repos"), bare=True)
  2200. tests.create_projects_git(
  2201. os.path.join(self.path, "requests"), bare=True
  2202. )
  2203. tests.add_readme_git_repo(os.path.join(self.path, "repos", "test.git"))
  2204. tests.add_commit_git_repo(
  2205. os.path.join(self.path, "repos", "test.git"), branch="test"
  2206. )
  2207. tests.create_tokens(self.session)
  2208. tests.create_tokens_acl(self.session)
  2209. headers = {"Authorization": "token aaabbbcccddd"}
  2210. data = {
  2211. "initial_comment": "Nothing much, the changes speak for themselves",
  2212. "branch_to": "master",
  2213. "branch_from": "test",
  2214. }
  2215. output = self.app.post(
  2216. "/api/0/foobar/pull-request/new", headers=headers, data=data
  2217. )
  2218. self.assertEqual(output.status_code, 404)
  2219. data = json.loads(output.get_data(as_text=True))
  2220. self.assertDictEqual(
  2221. data, {"error": "Project not found", "error_code": "ENOPROJECT"}
  2222. )
  2223. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  2224. def test_api_pull_request_open_missing_title(self):
  2225. """ Test the api_pull_request_create method of the flask api when
  2226. not title is submitted.
  2227. """
  2228. tests.create_projects(self.session)
  2229. tests.create_projects_git(os.path.join(self.path, "repos"), bare=True)
  2230. tests.create_projects_git(
  2231. os.path.join(self.path, "requests"), bare=True
  2232. )
  2233. tests.add_readme_git_repo(os.path.join(self.path, "repos", "test.git"))
  2234. tests.add_commit_git_repo(
  2235. os.path.join(self.path, "repos", "test.git"), branch="test"
  2236. )
  2237. tests.create_tokens(self.session)
  2238. tests.create_tokens_acl(self.session)
  2239. headers = {"Authorization": "token aaabbbcccddd"}
  2240. data = {
  2241. "initial_comment": "Nothing much, the changes speak for themselves",
  2242. "branch_to": "master",
  2243. "branch_from": "test",
  2244. }
  2245. output = self.app.post(
  2246. "/api/0/test/pull-request/new", headers=headers, data=data
  2247. )
  2248. self.assertEqual(output.status_code, 400)
  2249. data = json.loads(output.get_data(as_text=True))
  2250. self.assertDictEqual(
  2251. data,
  2252. {
  2253. "error": "Invalid or incomplete input submitted",
  2254. "error_code": "EINVALIDREQ",
  2255. "errors": {"title": ["This field is required."]},
  2256. },
  2257. )
  2258. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  2259. def test_api_pull_request_open_missing_branch_to(self):
  2260. """ Test the api_pull_request_create method of the flask api when
  2261. not branch to is submitted.
  2262. """
  2263. tests.create_projects(self.session)
  2264. tests.create_projects_git(os.path.join(self.path, "repos"), bare=True)
  2265. tests.create_projects_git(
  2266. os.path.join(self.path, "requests"), bare=True
  2267. )
  2268. tests.add_readme_git_repo(os.path.join(self.path, "repos", "test.git"))
  2269. tests.add_commit_git_repo(
  2270. os.path.join(self.path, "repos", "test.git"), branch="test"
  2271. )
  2272. tests.create_tokens(self.session)
  2273. tests.create_tokens_acl(self.session)
  2274. headers = {"Authorization": "token aaabbbcccddd"}
  2275. data = {
  2276. "title": "Test PR",
  2277. "initial_comment": "Nothing much, the changes speak for themselves",
  2278. "branch_from": "test",
  2279. }
  2280. output = self.app.post(
  2281. "/api/0/test/pull-request/new", headers=headers, data=data
  2282. )
  2283. self.assertEqual(output.status_code, 400)
  2284. data = json.loads(output.get_data(as_text=True))
  2285. self.assertDictEqual(
  2286. data,
  2287. {
  2288. "error": "Invalid or incomplete input submitted",
  2289. "error_code": "EINVALIDREQ",
  2290. "errors": {"branch_to": ["This field is required."]},
  2291. },
  2292. )
  2293. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  2294. def test_api_pull_request_open_missing_branch_from(self):
  2295. """ Test the api_pull_request_create method of the flask api when
  2296. not branch from is submitted.
  2297. """
  2298. tests.create_projects(self.session)
  2299. tests.create_projects_git(os.path.join(self.path, "repos"), bare=True)
  2300. tests.create_projects_git(
  2301. os.path.join(self.path, "requests"), bare=True
  2302. )
  2303. tests.add_readme_git_repo(os.path.join(self.path, "repos", "test.git"))
  2304. tests.add_commit_git_repo(
  2305. os.path.join(self.path, "repos", "test.git"), branch="test"
  2306. )
  2307. tests.create_tokens(self.session)
  2308. tests.create_tokens_acl(self.session)
  2309. headers = {"Authorization": "token aaabbbcccddd"}
  2310. data = {
  2311. "title": "Test PR",
  2312. "initial_comment": "Nothing much, the changes speak for themselves",
  2313. "branch_to": "master",
  2314. }
  2315. output = self.app.post(
  2316. "/api/0/test/pull-request/new", headers=headers, data=data
  2317. )
  2318. self.assertEqual(output.status_code, 400)
  2319. data = json.loads(output.get_data(as_text=True))
  2320. self.assertDictEqual(
  2321. data,
  2322. {
  2323. "error": "Invalid or incomplete input submitted",
  2324. "error_code": "EINVALIDREQ",
  2325. "errors": {"branch_from": ["This field is required."]},
  2326. },
  2327. )
  2328. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  2329. def test_api_pull_request_open_pr_disabled(self):
  2330. """ Test the api_pull_request_create method of the flask api when
  2331. the parent repo disabled pull-requests.
  2332. """
  2333. tests.create_projects(self.session)
  2334. tests.create_projects_git(os.path.join(self.path, "repos"), bare=True)
  2335. tests.create_projects_git(
  2336. os.path.join(self.path, "requests"), bare=True
  2337. )
  2338. tests.add_readme_git_repo(os.path.join(self.path, "repos", "test.git"))
  2339. tests.add_commit_git_repo(
  2340. os.path.join(self.path, "repos", "test.git"), branch="test"
  2341. )
  2342. tests.create_tokens(self.session)
  2343. tests.create_tokens_acl(self.session)
  2344. # Check the behavior if the project disabled the issue tracker
  2345. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  2346. settings = repo.settings
  2347. settings["pull_requests"] = False
  2348. repo.settings = settings
  2349. self.session.add(repo)
  2350. self.session.commit()
  2351. headers = {"Authorization": "token aaabbbcccddd"}
  2352. data = {
  2353. "title": "Test PR",
  2354. "initial_comment": "Nothing much, the changes speak for themselves",
  2355. "branch_to": "master",
  2356. "branch_from": "test",
  2357. }
  2358. output = self.app.post(
  2359. "/api/0/test/pull-request/new", headers=headers, data=data
  2360. )
  2361. self.assertEqual(output.status_code, 404)
  2362. data = json.loads(output.get_data(as_text=True))
  2363. self.assertDictEqual(
  2364. data,
  2365. {
  2366. "error": "Pull-Request have been deactivated for this project",
  2367. "error_code": "EPULLREQUESTSDISABLED",
  2368. },
  2369. )
  2370. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  2371. def test_api_pull_request_open_signed_pr(self):
  2372. """ Test the api_pull_request_create method of the flask api when
  2373. the parent repo enforces signed-off pull-requests.
  2374. """
  2375. tests.create_projects(self.session)
  2376. tests.create_projects_git(os.path.join(self.path, "repos"), bare=True)
  2377. tests.create_projects_git(
  2378. os.path.join(self.path, "requests"), bare=True
  2379. )
  2380. tests.add_readme_git_repo(os.path.join(self.path, "repos", "test.git"))
  2381. tests.add_commit_git_repo(
  2382. os.path.join(self.path, "repos", "test.git"), branch="test"
  2383. )
  2384. tests.create_tokens(self.session)
  2385. tests.create_tokens_acl(self.session)
  2386. # Check the behavior if the project disabled the issue tracker
  2387. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  2388. settings = repo.settings
  2389. settings["Enforce_signed-off_commits_in_pull-request"] = True
  2390. repo.settings = settings
  2391. self.session.add(repo)
  2392. self.session.commit()
  2393. headers = {"Authorization": "token aaabbbcccddd"}
  2394. data = {
  2395. "title": "Test PR",
  2396. "initial_comment": "Nothing much, the changes speak for themselves",
  2397. "branch_to": "master",
  2398. "branch_from": "test",
  2399. }
  2400. output = self.app.post(
  2401. "/api/0/test/pull-request/new", headers=headers, data=data
  2402. )
  2403. self.assertEqual(output.status_code, 400)
  2404. data = json.loads(output.get_data(as_text=True))
  2405. self.assertDictEqual(
  2406. data,
  2407. {
  2408. "error": "This repo enforces that all commits are signed "
  2409. "off by their author.",
  2410. "error_code": "ENOSIGNEDOFF",
  2411. },
  2412. )
  2413. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  2414. def test_api_pull_request_open_invalid_branch_from(self):
  2415. """ Test the api_pull_request_create method of the flask api when
  2416. the branch from does not exist.
  2417. """
  2418. tests.create_projects(self.session)
  2419. tests.create_projects_git(os.path.join(self.path, "repos"), bare=True)
  2420. tests.create_projects_git(
  2421. os.path.join(self.path, "requests"), bare=True
  2422. )
  2423. tests.add_readme_git_repo(os.path.join(self.path, "repos", "test.git"))
  2424. tests.add_commit_git_repo(
  2425. os.path.join(self.path, "repos", "test.git"), branch="test"
  2426. )
  2427. tests.create_tokens(self.session)
  2428. tests.create_tokens_acl(self.session)
  2429. # Check the behavior if the project disabled the issue tracker
  2430. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  2431. settings = repo.settings
  2432. settings["Enforce_signed-off_commits_in_pull-request"] = True
  2433. repo.settings = settings
  2434. self.session.add(repo)
  2435. self.session.commit()
  2436. headers = {"Authorization": "token aaabbbcccddd"}
  2437. data = {
  2438. "title": "Test PR",
  2439. "initial_comment": "Nothing much, the changes speak for themselves",
  2440. "branch_to": "master",
  2441. "branch_from": "foobarbaz",
  2442. }
  2443. output = self.app.post(
  2444. "/api/0/test/pull-request/new", headers=headers, data=data
  2445. )
  2446. self.assertEqual(output.status_code, 400)
  2447. data = json.loads(output.get_data(as_text=True))
  2448. self.assertDictEqual(
  2449. data,
  2450. {
  2451. "error": "Invalid or incomplete input submitted",
  2452. "error_code": "EINVALIDREQ",
  2453. "errors": "Branch foobarbaz does not exist",
  2454. },
  2455. )
  2456. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  2457. def test_api_pull_request_open_invalid_token(self):
  2458. """ Test the api_pull_request_create method of the flask api when
  2459. queried with an invalid token.
  2460. """
  2461. tests.create_projects(self.session)
  2462. tests.create_projects_git(os.path.join(self.path, "repos"), bare=True)
  2463. tests.create_projects_git(
  2464. os.path.join(self.path, "requests"), bare=True
  2465. )
  2466. tests.add_readme_git_repo(os.path.join(self.path, "repos", "test.git"))
  2467. tests.add_commit_git_repo(
  2468. os.path.join(self.path, "repos", "test.git"), branch="test"
  2469. )
  2470. tests.create_tokens(self.session)
  2471. tests.create_tokens_acl(self.session)
  2472. headers = {"Authorization": "token aaabbbcccddd"}
  2473. data = {
  2474. "title": "Test PR",
  2475. "initial_comment": "Nothing much, the changes speak for themselves",
  2476. "branch_to": "master",
  2477. "branch_from": "foobarbaz",
  2478. }
  2479. output = self.app.post(
  2480. "/api/0/test2/pull-request/new", headers=headers, data=data
  2481. )
  2482. self.assertEqual(output.status_code, 401)
  2483. data = json.loads(output.get_data(as_text=True))
  2484. self.assertDictEqual(
  2485. data,
  2486. {
  2487. "error": "Invalid or expired token. Please visit "
  2488. "http://localhost.localdomain/settings#nav-api-tab to get or "
  2489. "renew your API token.",
  2490. "error_code": "EINVALIDTOK",
  2491. },
  2492. )
  2493. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  2494. def test_api_pull_request_open_invalid_access(self):
  2495. """ Test the api_pull_request_create method of the flask api when
  2496. the user opening the PR doesn't have commit access.
  2497. """
  2498. tests.create_projects(self.session)
  2499. tests.create_projects_git(os.path.join(self.path, "repos"), bare=True)
  2500. tests.create_projects_git(
  2501. os.path.join(self.path, "requests"), bare=True
  2502. )
  2503. tests.add_readme_git_repo(os.path.join(self.path, "repos", "test.git"))
  2504. tests.add_commit_git_repo(
  2505. os.path.join(self.path, "repos", "test.git"), branch="test"
  2506. )
  2507. tests.create_tokens(self.session, user_id=2)
  2508. tests.create_tokens_acl(self.session)
  2509. headers = {"Authorization": "token aaabbbcccddd"}
  2510. data = {
  2511. "title": "Test PR",
  2512. "initial_comment": "Nothing much, the changes speak for themselves",
  2513. "branch_to": "master",
  2514. "branch_from": "foobarbaz",
  2515. }
  2516. output = self.app.post(
  2517. "/api/0/test/pull-request/new", headers=headers, data=data
  2518. )
  2519. self.assertEqual(output.status_code, 401)
  2520. data = json.loads(output.get_data(as_text=True))
  2521. self.assertDictEqual(
  2522. data,
  2523. {
  2524. "error": "You do not have sufficient permissions to "
  2525. "perform this action",
  2526. "error_code": "ENOTHIGHENOUGH",
  2527. },
  2528. )
  2529. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  2530. def test_api_pull_request_open_invalid_branch_to(self):
  2531. """ Test the api_pull_request_create method of the flask api when
  2532. the branch to does not exist.
  2533. """
  2534. tests.create_projects(self.session)
  2535. tests.create_projects_git(os.path.join(self.path, "repos"), bare=True)
  2536. tests.create_projects_git(
  2537. os.path.join(self.path, "requests"), bare=True
  2538. )
  2539. tests.add_readme_git_repo(os.path.join(self.path, "repos", "test.git"))
  2540. tests.add_commit_git_repo(
  2541. os.path.join(self.path, "repos", "test.git"), branch="test"
  2542. )
  2543. tests.create_tokens(self.session)
  2544. tests.create_tokens_acl(self.session)
  2545. # Check the behavior if the project disabled the issue tracker
  2546. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  2547. settings = repo.settings
  2548. settings["Enforce_signed-off_commits_in_pull-request"] = True
  2549. repo.settings = settings
  2550. self.session.add(repo)
  2551. self.session.commit()
  2552. headers = {"Authorization": "token aaabbbcccddd"}
  2553. data = {
  2554. "title": "Test PR",
  2555. "initial_comment": "Nothing much, the changes speak for themselves",
  2556. "branch_to": "foobarbaz",
  2557. "branch_from": "test",
  2558. }
  2559. output = self.app.post(
  2560. "/api/0/test/pull-request/new", headers=headers, data=data
  2561. )
  2562. self.assertEqual(output.status_code, 400)
  2563. data = json.loads(output.get_data(as_text=True))
  2564. self.assertDictEqual(
  2565. data,
  2566. {
  2567. "error": "Invalid or incomplete input submitted",
  2568. "error_code": "EINVALIDREQ",
  2569. "errors": "Branch foobarbaz could not be found in the "
  2570. "target repo",
  2571. },
  2572. )
  2573. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  2574. def test_api_pull_request_open_project_token_different_project(self):
  2575. """Test the api_pull_request_create method with the project token
  2576. of a different project - fails"""
  2577. tests.create_projects(self.session)
  2578. tests.create_projects_git(os.path.join(self.path, "repos"), bare=True)
  2579. tests.create_projects_git(
  2580. os.path.join(self.path, "requests"), bare=True
  2581. )
  2582. tests.add_readme_git_repo(os.path.join(self.path, "repos", "test.git"))
  2583. tests.add_commit_git_repo(
  2584. os.path.join(self.path, "repos", "test.git"), branch="test"
  2585. )
  2586. tests.create_tokens(self.session, project_id=2)
  2587. tests.create_tokens_acl(self.session)
  2588. headers = {"Authorization": "token foo_token"}
  2589. data = {
  2590. "title": "Test of PR",
  2591. "inicial comment": "Some readme adjustment",
  2592. "branch_to": "master",
  2593. "branch_from": "test",
  2594. }
  2595. output = self.app.post(
  2596. "/api/0/test/pull-request/new", headers=headers, data=data
  2597. )
  2598. self.assertEqual(output.status_code, 401)
  2599. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  2600. def test_api_pull_request_open_user_token_invalid_acls(self):
  2601. """Test the api_pull_request_create method with the user token, but with
  2602. no acls for opening pull request - fails"""
  2603. tests.create_projects(self.session)
  2604. tests.create_projects_git(os.path.join(self.path, "repos"), bare=True)
  2605. tests.create_projects_git(
  2606. os.path.join(self.path, "requests"), bare=True
  2607. )
  2608. tests.add_readme_git_repo(os.path.join(self.path, "repos", "test.git"))
  2609. tests.add_commit_git_repo(
  2610. os.path.join(self.path, "repos", "test.git"), branch="test"
  2611. )
  2612. tests.create_tokens(self.session, project_id=None)
  2613. for acl in (
  2614. "create_project",
  2615. "fork_project",
  2616. "modify_project",
  2617. "update_watch_status",
  2618. ):
  2619. tests.create_tokens_acl(self.session, acl_name=acl)
  2620. headers = {"Authorization": "token aaabbbcccddd"}
  2621. data = {
  2622. "title": "Test of PR",
  2623. "initial_comment": "Some readme adjustment",
  2624. "branch_to": "master",
  2625. "branch_from": "test",
  2626. }
  2627. output = self.app.post(
  2628. "/api/0/test/pull-request/new", headers=headers, data=data
  2629. )
  2630. self.assertEqual(output.status_code, 401)
  2631. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  2632. def test_api_pull_request_open_from_branch_to_origin(self):
  2633. """Test the api_pull_request_create method from a fork to a master,
  2634. with project token of a origin with all the acls"""
  2635. tests.create_projects(self.session)
  2636. tests.create_projects(
  2637. self.session, is_fork=True, hook_token_suffix="foo"
  2638. )
  2639. project_query = self.session.query(pagure.lib.model.Project)
  2640. for project in project_query.filter_by(name="test").all():
  2641. if project.parent_id == None:
  2642. parent = project
  2643. else:
  2644. child = project
  2645. tests.create_projects_git(os.path.join(self.path, "repos"), bare=True)
  2646. tests.create_projects_git(
  2647. os.path.join(self.path, "requests"), bare=True
  2648. )
  2649. tests.add_readme_git_repo(
  2650. os.path.join(self.path, "repos", "forks", "pingou", "test.git"),
  2651. branch="branch",
  2652. )
  2653. tests.add_commit_git_repo(
  2654. os.path.join(self.path, "repos", "forks", "pingou", "test.git"),
  2655. branch="branch",
  2656. )
  2657. # Create tokens
  2658. parent_token = pagure.lib.model.Token(
  2659. id="iamparenttoken",
  2660. user_id=parent.user_id,
  2661. project_id=parent.id,
  2662. expiration=datetime.datetime.utcnow()
  2663. + datetime.timedelta(days=30),
  2664. )
  2665. self.session.add(parent_token)
  2666. fork_token = pagure.lib.model.Token(
  2667. id="iamforktoken",
  2668. user_id=child.user_id,
  2669. project_id=child.id,
  2670. expiration=datetime.datetime.utcnow()
  2671. + datetime.timedelta(days=30),
  2672. )
  2673. self.session.add(fork_token)
  2674. self.session.commit()
  2675. tests.create_tokens_acl(self.session, token_id="iamparenttoken")
  2676. for acl in pagure.default_config.CROSS_PROJECT_ACLS:
  2677. tests.create_tokens_acl(
  2678. self.session, token_id="iamforktoken", acl_name=acl
  2679. )
  2680. headers = {"Authorization": "token iamforktoken"}
  2681. data = {
  2682. "title": "war of tomatoes",
  2683. "initial_comment": "the manifest",
  2684. "branch_to": "master",
  2685. "branch_from": "branch",
  2686. "repo_from": "test",
  2687. "repo_from_username": "pingou",
  2688. }
  2689. output = self.app.post(
  2690. "/api/0/test/pull-request/new", headers=headers, data=data
  2691. )
  2692. self.assertEqual(output.status_code, 200)
  2693. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  2694. def test_api_pull_request_open(self):
  2695. """ Test the api_pull_request_create method of the flask api. """
  2696. tests.create_projects(self.session)
  2697. tests.create_projects_git(os.path.join(self.path, "repos"), bare=True)
  2698. tests.create_projects_git(
  2699. os.path.join(self.path, "requests"), bare=True
  2700. )
  2701. tests.add_readme_git_repo(os.path.join(self.path, "repos", "test.git"))
  2702. tests.add_commit_git_repo(
  2703. os.path.join(self.path, "repos", "test.git"), branch="test"
  2704. )
  2705. tests.create_tokens(self.session)
  2706. tests.create_tokens_acl(self.session)
  2707. headers = {"Authorization": "token aaabbbcccddd"}
  2708. data = {
  2709. "title": "Test PR",
  2710. "initial_comment": "Nothing much, the changes speak for themselves",
  2711. "branch_to": "master",
  2712. "branch_from": "test",
  2713. }
  2714. output = self.app.post(
  2715. "/api/0/test/pull-request/new", headers=headers, data=data
  2716. )
  2717. self.assertEqual(output.status_code, 200)
  2718. data = json.loads(output.get_data(as_text=True))
  2719. data["project"]["date_created"] = "1516348115"
  2720. data["project"]["date_modified"] = "1516348115"
  2721. data["repo_from"]["date_created"] = "1516348115"
  2722. data["repo_from"]["date_modified"] = "1516348115"
  2723. data["uid"] = "e8b68df8711648deac67c3afed15a798"
  2724. data["commit_start"] = "114f1b468a5f05e635fcb6394273f3f907386eab"
  2725. data["commit_stop"] = "114f1b468a5f05e635fcb6394273f3f907386eab"
  2726. data["date_created"] = "1516348115"
  2727. data["last_updated"] = "1516348115"
  2728. data["updated_on"] = "1516348115"
  2729. self.assertDictEqual(
  2730. data,
  2731. {
  2732. "assignee": None,
  2733. "branch": "master",
  2734. "branch_from": "test",
  2735. "cached_merge_status": "unknown",
  2736. "closed_at": None,
  2737. "closed_by": None,
  2738. "comments": [],
  2739. "commit_start": "114f1b468a5f05e635fcb6394273f3f907386eab",
  2740. "commit_stop": "114f1b468a5f05e635fcb6394273f3f907386eab",
  2741. "date_created": "1516348115",
  2742. "id": 1,
  2743. "initial_comment": "Nothing much, the changes speak for themselves",
  2744. "last_updated": "1516348115",
  2745. "project": {
  2746. "access_groups": {"admin": [], "commit": [], "ticket": []},
  2747. "access_users": {
  2748. "admin": [],
  2749. "commit": [],
  2750. "owner": ["pingou"],
  2751. "ticket": [],
  2752. },
  2753. "close_status": [
  2754. "Invalid",
  2755. "Insufficient data",
  2756. "Fixed",
  2757. "Duplicate",
  2758. ],
  2759. "custom_keys": [],
  2760. "date_created": "1516348115",
  2761. "date_modified": "1516348115",
  2762. "description": "test project #1",
  2763. "fullname": "test",
  2764. "id": 1,
  2765. "milestones": {},
  2766. "name": "test",
  2767. "namespace": None,
  2768. "parent": None,
  2769. "priorities": {},
  2770. "tags": [],
  2771. "url_path": "test",
  2772. "user": {
  2773. "fullname": "PY C",
  2774. "name": "pingou",
  2775. "url_path": "user/pingou",
  2776. },
  2777. },
  2778. "remote_git": None,
  2779. "repo_from": {
  2780. "access_groups": {"admin": [], "commit": [], "ticket": []},
  2781. "access_users": {
  2782. "admin": [],
  2783. "commit": [],
  2784. "owner": ["pingou"],
  2785. "ticket": [],
  2786. },
  2787. "close_status": [
  2788. "Invalid",
  2789. "Insufficient data",
  2790. "Fixed",
  2791. "Duplicate",
  2792. ],
  2793. "custom_keys": [],
  2794. "date_created": "1516348115",
  2795. "date_modified": "1516348115",
  2796. "description": "test project #1",
  2797. "fullname": "test",
  2798. "id": 1,
  2799. "milestones": {},
  2800. "name": "test",
  2801. "namespace": None,
  2802. "parent": None,
  2803. "priorities": {},
  2804. "tags": [],
  2805. "url_path": "test",
  2806. "user": {
  2807. "fullname": "PY C",
  2808. "name": "pingou",
  2809. "url_path": "user/pingou",
  2810. },
  2811. },
  2812. "status": "Open",
  2813. "tags": [],
  2814. "threshold_reached": None,
  2815. "title": "Test PR",
  2816. "uid": "e8b68df8711648deac67c3afed15a798",
  2817. "updated_on": "1516348115",
  2818. "user": {
  2819. "fullname": "PY C",
  2820. "name": "pingou",
  2821. "url_path": "user/pingou",
  2822. },
  2823. },
  2824. )
  2825. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  2826. def test_api_pull_request_open_missing_initial_comment(self):
  2827. """ Test the api_pull_request_create method of the flask api when
  2828. not initial comment is submitted.
  2829. """
  2830. tests.create_projects(self.session)
  2831. tests.create_projects_git(os.path.join(self.path, "repos"), bare=True)
  2832. tests.create_projects_git(
  2833. os.path.join(self.path, "requests"), bare=True
  2834. )
  2835. tests.add_readme_git_repo(os.path.join(self.path, "repos", "test.git"))
  2836. tests.add_commit_git_repo(
  2837. os.path.join(self.path, "repos", "test.git"), branch="test"
  2838. )
  2839. tests.create_tokens(self.session)
  2840. tests.create_tokens_acl(self.session)
  2841. headers = {"Authorization": "token aaabbbcccddd"}
  2842. data = {
  2843. "title": "Test PR",
  2844. "branch_to": "master",
  2845. "branch_from": "test",
  2846. }
  2847. output = self.app.post(
  2848. "/api/0/test/pull-request/new", headers=headers, data=data
  2849. )
  2850. self.assertEqual(output.status_code, 200)
  2851. data = json.loads(output.get_data(as_text=True))
  2852. data["project"]["date_created"] = "1516348115"
  2853. data["project"]["date_modified"] = "1516348115"
  2854. data["repo_from"]["date_created"] = "1516348115"
  2855. data["repo_from"]["date_modified"] = "1516348115"
  2856. data["uid"] = "e8b68df8711648deac67c3afed15a798"
  2857. data["commit_start"] = "114f1b468a5f05e635fcb6394273f3f907386eab"
  2858. data["commit_stop"] = "114f1b468a5f05e635fcb6394273f3f907386eab"
  2859. data["date_created"] = "1516348115"
  2860. data["last_updated"] = "1516348115"
  2861. data["updated_on"] = "1516348115"
  2862. self.assertDictEqual(
  2863. data,
  2864. {
  2865. "assignee": None,
  2866. "branch": "master",
  2867. "branch_from": "test",
  2868. "cached_merge_status": "unknown",
  2869. "closed_at": None,
  2870. "closed_by": None,
  2871. "comments": [],
  2872. "commit_start": "114f1b468a5f05e635fcb6394273f3f907386eab",
  2873. "commit_stop": "114f1b468a5f05e635fcb6394273f3f907386eab",
  2874. "date_created": "1516348115",
  2875. "id": 1,
  2876. "initial_comment": None,
  2877. "last_updated": "1516348115",
  2878. "project": {
  2879. "access_groups": {"admin": [], "commit": [], "ticket": []},
  2880. "access_users": {
  2881. "admin": [],
  2882. "commit": [],
  2883. "owner": ["pingou"],
  2884. "ticket": [],
  2885. },
  2886. "close_status": [
  2887. "Invalid",
  2888. "Insufficient data",
  2889. "Fixed",
  2890. "Duplicate",
  2891. ],
  2892. "custom_keys": [],
  2893. "date_created": "1516348115",
  2894. "date_modified": "1516348115",
  2895. "description": "test project #1",
  2896. "fullname": "test",
  2897. "id": 1,
  2898. "milestones": {},
  2899. "name": "test",
  2900. "namespace": None,
  2901. "parent": None,
  2902. "priorities": {},
  2903. "tags": [],
  2904. "url_path": "test",
  2905. "user": {
  2906. "fullname": "PY C",
  2907. "name": "pingou",
  2908. "url_path": "user/pingou",
  2909. },
  2910. },
  2911. "remote_git": None,
  2912. "repo_from": {
  2913. "access_groups": {"admin": [], "commit": [], "ticket": []},
  2914. "access_users": {
  2915. "admin": [],
  2916. "commit": [],
  2917. "owner": ["pingou"],
  2918. "ticket": [],
  2919. },
  2920. "close_status": [
  2921. "Invalid",
  2922. "Insufficient data",
  2923. "Fixed",
  2924. "Duplicate",
  2925. ],
  2926. "custom_keys": [],
  2927. "date_created": "1516348115",
  2928. "date_modified": "1516348115",
  2929. "description": "test project #1",
  2930. "fullname": "test",
  2931. "id": 1,
  2932. "milestones": {},
  2933. "name": "test",
  2934. "namespace": None,
  2935. "parent": None,
  2936. "priorities": {},
  2937. "tags": [],
  2938. "url_path": "test",
  2939. "user": {
  2940. "fullname": "PY C",
  2941. "name": "pingou",
  2942. "url_path": "user/pingou",
  2943. },
  2944. },
  2945. "status": "Open",
  2946. "tags": [],
  2947. "threshold_reached": None,
  2948. "title": "Test PR",
  2949. "uid": "e8b68df8711648deac67c3afed15a798",
  2950. "updated_on": "1516348115",
  2951. "user": {
  2952. "fullname": "PY C",
  2953. "name": "pingou",
  2954. "url_path": "user/pingou",
  2955. },
  2956. },
  2957. )
  2958. class PagureFlaskApiForkPRDiffStatstests(tests.Modeltests):
  2959. """ Tests for the flask API of pagure for the diff stats endpoint of PRs
  2960. """
  2961. maxDiff = None
  2962. def setUp(self):
  2963. """ Set up the environnment, ran before every tests. """
  2964. super(PagureFlaskApiForkPRDiffStatstests, self).setUp()
  2965. pagure.config.config["REQUESTS_FOLDER"] = None
  2966. tests.create_projects(self.session)
  2967. tests.create_projects_git(os.path.join(self.path, "repos"), bare=True)
  2968. tests.create_projects_git(
  2969. os.path.join(self.path, "requests"), bare=True
  2970. )
  2971. tests.add_readme_git_repo(os.path.join(self.path, "repos", "test.git"))
  2972. tests.add_commit_git_repo(
  2973. os.path.join(self.path, "repos", "test.git"), ncommits=5
  2974. )
  2975. tests.add_commit_git_repo(
  2976. os.path.join(self.path, "repos", "test.git"), branch="test"
  2977. )
  2978. # Create the pull-request to close
  2979. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  2980. req = pagure.lib.query.new_pull_request(
  2981. session=self.session,
  2982. repo_from=repo,
  2983. branch_from="test",
  2984. repo_to=repo,
  2985. branch_to="master",
  2986. title="test pull-request",
  2987. user="pingou",
  2988. )
  2989. self.session.commit()
  2990. self.assertEqual(req.id, 1)
  2991. self.assertEqual(req.title, "test pull-request")
  2992. @patch("pagure.lib.git.update_git", MagicMock(return_value=True))
  2993. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  2994. def test_api_pull_request_diffstats_no_repo(self):
  2995. """ Test the api_pull_request_merge method of the flask api. """
  2996. output = self.app.get("/api/0/invalid/pull-request/404/diffstats")
  2997. self.assertEqual(output.status_code, 404)
  2998. data = json.loads(output.get_data(as_text=True))
  2999. self.assertEqual(
  3000. data, {"error": "Project not found", "error_code": "ENOPROJECT"}
  3001. )
  3002. @patch("pagure.lib.git.update_git", MagicMock(return_value=True))
  3003. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  3004. def test_api_pull_request_diffstats_no_pr(self):
  3005. """ Test the api_pull_request_merge method of the flask api. """
  3006. output = self.app.get("/api/0/test/pull-request/404/diffstats")
  3007. self.assertEqual(output.status_code, 404)
  3008. data = json.loads(output.get_data(as_text=True))
  3009. self.assertEqual(
  3010. data, {"error": "Pull-Request not found", "error_code": "ENOREQ"}
  3011. )
  3012. @patch("pagure.lib.git.update_git", MagicMock(return_value=True))
  3013. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  3014. def test_api_pull_request_diffstats_file_modified(self):
  3015. """ Test the api_pull_request_merge method of the flask api. """
  3016. output = self.app.get("/api/0/test/pull-request/1/diffstats")
  3017. self.assertEqual(output.status_code, 200)
  3018. data = json.loads(output.get_data(as_text=True))
  3019. self.assertEqual(
  3020. data,
  3021. {
  3022. "sources": {
  3023. "lines_added": 10,
  3024. "lines_removed": 0,
  3025. "new_id": "540916fbd3d825d14cc0c0b2397606fda69379ce",
  3026. "old_id": "265f133a7c94ede4cb183dd808219c5bf9e08f87",
  3027. "old_path": "sources",
  3028. "status": "M",
  3029. }
  3030. },
  3031. )
  3032. @patch("pagure.lib.git.update_git", MagicMock(return_value=True))
  3033. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  3034. def test_api_pull_request_diffstats_file_added_mofidied(self):
  3035. """ Test the api_pull_request_merge method of the flask api. """
  3036. tests.add_commit_git_repo(
  3037. os.path.join(self.path, "repos", "test.git"), ncommits=5
  3038. )
  3039. tests.add_readme_git_repo(
  3040. os.path.join(self.path, "repos", "test.git"),
  3041. readme_name="README.md",
  3042. branch="test",
  3043. )
  3044. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  3045. self.assertEqual(len(repo.requests), 1)
  3046. output = self.app.get("/api/0/test/pull-request/1/diffstats")
  3047. self.assertEqual(output.status_code, 200)
  3048. data = json.loads(output.get_data(as_text=True))
  3049. self.assertTrue(
  3050. data
  3051. in [
  3052. {
  3053. "README.md": {
  3054. "lines_added": 5,
  3055. "lines_removed": 0,
  3056. "new_id": "bd913ea153650b94f33f53e5164c36a28b761bf4",
  3057. "old_id": "0000000000000000000000000000000000000000",
  3058. "old_path": "README.md",
  3059. "status": "A",
  3060. },
  3061. "sources": {
  3062. "lines_added": 5,
  3063. "lines_removed": 0,
  3064. "new_id": "540916fbd3d825d14cc0c0b2397606fda69379ce",
  3065. "old_id": "293500070b9dfc6ab66e31383f8f7fccf6a95fe2",
  3066. "old_path": "sources",
  3067. "status": "M",
  3068. },
  3069. },
  3070. {
  3071. "README.md": {
  3072. "lines_added": 5,
  3073. "lines_removed": 0,
  3074. "new_id": "bd913ea153650b94f33f53e5164c36a28b761bf4",
  3075. "old_id": "0000000000000000000000000000000000000000",
  3076. "old_path": "README.md",
  3077. "status": "A",
  3078. },
  3079. "sources": {
  3080. "lines_added": 10,
  3081. "lines_removed": 0,
  3082. "new_id": "540916fbd3d825d14cc0c0b2397606fda69379ce",
  3083. "old_id": "265f133a7c94ede4cb183dd808219c5bf9e08f87",
  3084. "old_path": "sources",
  3085. "status": "M",
  3086. },
  3087. },
  3088. ]
  3089. )
  3090. @patch("pagure.lib.git.update_git", MagicMock(return_value=True))
  3091. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  3092. def test_api_pull_request_diffstats_file_modified_deleted(self):
  3093. """ Test the api_pull_request_merge method of the flask api. """
  3094. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  3095. self.assertEqual(len(repo.requests), 1)
  3096. pagure.lib.tasks.update_pull_request(repo.requests[0].uid)
  3097. tests.add_readme_git_repo(
  3098. os.path.join(self.path, "repos", "test.git"),
  3099. readme_name="README.md",
  3100. branch="test",
  3101. )
  3102. tests.remove_file_git_repo(
  3103. os.path.join(self.path, "repos", "test.git"),
  3104. filename="sources",
  3105. branch="test",
  3106. )
  3107. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  3108. self.assertEqual(len(repo.requests), 1)
  3109. pagure.lib.tasks.update_pull_request(repo.requests[0].uid)
  3110. output = self.app.get("/api/0/test/pull-request/1/diffstats")
  3111. self.assertEqual(output.status_code, 200)
  3112. data = json.loads(output.get_data(as_text=True))
  3113. self.assertEqual(
  3114. data,
  3115. {
  3116. "README.md": {
  3117. "lines_added": 5,
  3118. "lines_removed": 0,
  3119. "new_id": "bd913ea153650b94f33f53e5164c36a28b761bf4",
  3120. "old_id": "0000000000000000000000000000000000000000",
  3121. "old_path": "README.md",
  3122. "status": "A",
  3123. },
  3124. "sources": {
  3125. "lines_added": 0,
  3126. "lines_removed": 5,
  3127. "new_id": "0000000000000000000000000000000000000000",
  3128. "old_id": "265f133a7c94ede4cb183dd808219c5bf9e08f87",
  3129. "old_path": "sources",
  3130. "status": "D",
  3131. },
  3132. },
  3133. )
  3134. class PagureApiThresholdReachedTests(tests.Modeltests):
  3135. """ Test the behavior of the threshold_reached value returned by the API.
  3136. """
  3137. maxDiff = None
  3138. def _clean_data(self, data):
  3139. data["project"]["date_created"] = "1516348115"
  3140. data["project"]["date_modified"] = "1516348115"
  3141. data["repo_from"]["date_created"] = "1516348115"
  3142. data["repo_from"]["date_modified"] = "1516348115"
  3143. data["uid"] = "e8b68df8711648deac67c3afed15a798"
  3144. data["commit_start"] = "114f1b468a5f05e635fcb6394273f3f907386eab"
  3145. data["commit_stop"] = "114f1b468a5f05e635fcb6394273f3f907386eab"
  3146. data["date_created"] = "1516348115"
  3147. data["last_updated"] = "1516348115"
  3148. data["updated_on"] = "1516348115"
  3149. data["comments"] = [] # Let's not check the comments
  3150. return data
  3151. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  3152. def setUp(self):
  3153. """ Set up the environment for the tests. """
  3154. super(PagureApiThresholdReachedTests, self).setUp()
  3155. tests.create_projects(self.session)
  3156. tests.create_projects_git(os.path.join(self.path, "repos"), bare=True)
  3157. tests.create_projects_git(
  3158. os.path.join(self.path, "requests"), bare=True
  3159. )
  3160. tests.add_readme_git_repo(os.path.join(self.path, "repos", "test.git"))
  3161. tests.add_commit_git_repo(
  3162. os.path.join(self.path, "repos", "test.git"), branch="test"
  3163. )
  3164. tests.create_tokens(self.session)
  3165. tests.create_tokens_acl(self.session)
  3166. # Add a token for user `foo`
  3167. item = pagure.lib.model.Token(
  3168. id="aaabbbcccddd_foo",
  3169. user_id=2,
  3170. project_id=1,
  3171. expiration=datetime.datetime.utcnow()
  3172. + datetime.timedelta(days=30),
  3173. )
  3174. self.session.add(item)
  3175. self.session.commit()
  3176. tests.create_tokens_acl(self.session, token_id="aaabbbcccddd_foo")
  3177. # Add a minimal required score:
  3178. repo = pagure.lib.query._get_project(self.session, "test")
  3179. settings = repo.settings
  3180. settings["Minimum_score_to_merge_pull-request"] = 2
  3181. repo.settings = settings
  3182. self.session.add(repo)
  3183. self.session.commit()
  3184. headers = {"Authorization": "token aaabbbcccddd"}
  3185. data = {
  3186. "title": "Test PR",
  3187. "initial_comment": "Nothing much, the changes speak for themselves",
  3188. "branch_to": "master",
  3189. "branch_from": "test",
  3190. }
  3191. output = self.app.post(
  3192. "/api/0/test/pull-request/new", headers=headers, data=data
  3193. )
  3194. self.assertEqual(output.status_code, 200)
  3195. self.expected_data = {
  3196. "assignee": None,
  3197. "branch": "master",
  3198. "branch_from": "test",
  3199. "cached_merge_status": "unknown",
  3200. "closed_at": None,
  3201. "closed_by": None,
  3202. "comments": [],
  3203. "commit_start": "114f1b468a5f05e635fcb6394273f3f907386eab",
  3204. "commit_stop": "114f1b468a5f05e635fcb6394273f3f907386eab",
  3205. "date_created": "1516348115",
  3206. "id": 1,
  3207. "initial_comment": "Nothing much, the changes speak for themselves",
  3208. "last_updated": "1516348115",
  3209. "project": {
  3210. "access_groups": {"admin": [], "commit": [], "ticket": []},
  3211. "access_users": {
  3212. "admin": [],
  3213. "commit": [],
  3214. "owner": ["pingou"],
  3215. "ticket": [],
  3216. },
  3217. "close_status": [
  3218. "Invalid",
  3219. "Insufficient data",
  3220. "Fixed",
  3221. "Duplicate",
  3222. ],
  3223. "custom_keys": [],
  3224. "date_created": "1516348115",
  3225. "date_modified": "1516348115",
  3226. "description": "test project #1",
  3227. "fullname": "test",
  3228. "id": 1,
  3229. "milestones": {},
  3230. "name": "test",
  3231. "namespace": None,
  3232. "parent": None,
  3233. "priorities": {},
  3234. "tags": [],
  3235. "url_path": "test",
  3236. "user": {
  3237. "fullname": "PY C",
  3238. "name": "pingou",
  3239. "url_path": "user/pingou",
  3240. },
  3241. },
  3242. "remote_git": None,
  3243. "repo_from": {
  3244. "access_groups": {"admin": [], "commit": [], "ticket": []},
  3245. "access_users": {
  3246. "admin": [],
  3247. "commit": [],
  3248. "owner": ["pingou"],
  3249. "ticket": [],
  3250. },
  3251. "close_status": [
  3252. "Invalid",
  3253. "Insufficient data",
  3254. "Fixed",
  3255. "Duplicate",
  3256. ],
  3257. "custom_keys": [],
  3258. "date_created": "1516348115",
  3259. "date_modified": "1516348115",
  3260. "description": "test project #1",
  3261. "fullname": "test",
  3262. "id": 1,
  3263. "milestones": {},
  3264. "name": "test",
  3265. "namespace": None,
  3266. "parent": None,
  3267. "priorities": {},
  3268. "tags": [],
  3269. "url_path": "test",
  3270. "user": {
  3271. "fullname": "PY C",
  3272. "name": "pingou",
  3273. "url_path": "user/pingou",
  3274. },
  3275. },
  3276. "status": "Open",
  3277. "tags": [],
  3278. "threshold_reached": None,
  3279. "title": "Test PR",
  3280. "uid": "e8b68df8711648deac67c3afed15a798",
  3281. "updated_on": "1516348115",
  3282. "user": {
  3283. "fullname": "PY C",
  3284. "name": "pingou",
  3285. "url_path": "user/pingou",
  3286. },
  3287. }
  3288. def test_api_pull_request_no_comments(self):
  3289. """ Check the value of threshold_reach when the PR has no comments.
  3290. """
  3291. # Check the PR with 0 comment:
  3292. output = self.app.get("/api/0/test/pull-request/1")
  3293. self.assertEqual(output.status_code, 200)
  3294. data = json.loads(output.get_data(as_text=True))
  3295. data = self._clean_data(data)
  3296. self.expected_data["threshold_reached"] = False
  3297. self.assertDictEqual(data, self.expected_data)
  3298. def test_api_pull_request_one_comments(self):
  3299. """ Check the value of threshold_reach when the PR has one comment.
  3300. """
  3301. # Check the PR with 1 comment:
  3302. headers = {"Authorization": "token aaabbbcccddd"}
  3303. data = {"comment": "This is a very interesting solution :thumbsup:"}
  3304. output = self.app.post(
  3305. "/api/0/test/pull-request/1/comment", data=data, headers=headers
  3306. )
  3307. self.assertEqual(output.status_code, 200)
  3308. data = json.loads(output.get_data(as_text=True))
  3309. self.assertDictEqual(data, {"message": "Comment added"})
  3310. output = self.app.get("/api/0/test/pull-request/1")
  3311. self.assertEqual(output.status_code, 200)
  3312. data = json.loads(output.get_data(as_text=True))
  3313. data = self._clean_data(data)
  3314. self.expected_data["threshold_reached"] = False
  3315. self.assertDictEqual(data, self.expected_data)
  3316. def test_api_pull_request_two_comments_one_person(self):
  3317. """ Check the value of threshold_reach when the PR has two comments
  3318. but from the same person.
  3319. """
  3320. # Add two comments from the same user:
  3321. headers = {"Authorization": "token aaabbbcccddd"}
  3322. data = {"comment": "This is a very interesting solution :thumbsup:"}
  3323. output = self.app.post(
  3324. "/api/0/test/pull-request/1/comment", data=data, headers=headers
  3325. )
  3326. self.assertEqual(output.status_code, 200)
  3327. data = json.loads(output.get_data(as_text=True))
  3328. self.assertDictEqual(data, {"message": "Comment added"})
  3329. headers = {"Authorization": "token aaabbbcccddd"}
  3330. data = {"comment": "Indeed it is :thumbsup:"}
  3331. output = self.app.post(
  3332. "/api/0/test/pull-request/1/comment", data=data, headers=headers
  3333. )
  3334. self.assertEqual(output.status_code, 200)
  3335. data = json.loads(output.get_data(as_text=True))
  3336. self.assertDictEqual(data, {"message": "Comment added"})
  3337. output = self.app.get("/api/0/test/pull-request/1")
  3338. self.assertEqual(output.status_code, 200)
  3339. data = json.loads(output.get_data(as_text=True))
  3340. data = self._clean_data(data)
  3341. self.expected_data["threshold_reached"] = False
  3342. self.assertDictEqual(data, self.expected_data)
  3343. def test_api_pull_request_two_comments_two_persons(self):
  3344. """ Check the value of threshold_reach when the PR has two comments
  3345. from two different persons.
  3346. """
  3347. # Add two comments from two users:
  3348. headers = {"Authorization": "token aaabbbcccddd"}
  3349. data = {"comment": "This is a very interesting solution :thumbsup:"}
  3350. output = self.app.post(
  3351. "/api/0/test/pull-request/1/comment", data=data, headers=headers
  3352. )
  3353. self.assertEqual(output.status_code, 200)
  3354. data = json.loads(output.get_data(as_text=True))
  3355. self.assertDictEqual(data, {"message": "Comment added"})
  3356. headers = {"Authorization": "token aaabbbcccddd_foo"}
  3357. data = {"comment": "Indeed it is :thumbsup:"}
  3358. output = self.app.post(
  3359. "/api/0/test/pull-request/1/comment", data=data, headers=headers
  3360. )
  3361. self.assertEqual(output.status_code, 200)
  3362. data = json.loads(output.get_data(as_text=True))
  3363. self.assertDictEqual(data, {"message": "Comment added"})
  3364. output = self.app.get("/api/0/test/pull-request/1")
  3365. self.assertEqual(output.status_code, 200)
  3366. data = json.loads(output.get_data(as_text=True))
  3367. data = self._clean_data(data)
  3368. data["comments"] = [] # Let's not check the comments
  3369. self.expected_data["threshold_reached"] = True
  3370. self.assertDictEqual(data, self.expected_data)
  3371. def test_api_pull_request_three_comments_two_persons_changed_to_no(self):
  3372. """ Check the value of threshold_reach when the PR has three
  3373. comments from two person among which one changed their mind from
  3374. +1 to -1.
  3375. """
  3376. # Add three comments from two users:
  3377. headers = {"Authorization": "token aaabbbcccddd"}
  3378. data = {"comment": "This is a very interesting solution :thumbsup:"}
  3379. output = self.app.post(
  3380. "/api/0/test/pull-request/1/comment", data=data, headers=headers
  3381. )
  3382. self.assertEqual(output.status_code, 200)
  3383. data = json.loads(output.get_data(as_text=True))
  3384. self.assertDictEqual(data, {"message": "Comment added"})
  3385. headers = {"Authorization": "token aaabbbcccddd_foo"}
  3386. data = {"comment": "Indeed it is :thumbsup:"}
  3387. output = self.app.post(
  3388. "/api/0/test/pull-request/1/comment", data=data, headers=headers
  3389. )
  3390. self.assertEqual(output.status_code, 200)
  3391. data = json.loads(output.get_data(as_text=True))
  3392. self.assertDictEqual(data, {"message": "Comment added"})
  3393. data = {
  3394. "comment": "Nevermind the bug is elsewhere in fact :thumbsdown:"
  3395. }
  3396. output = self.app.post(
  3397. "/api/0/test/pull-request/1/comment", data=data, headers=headers
  3398. )
  3399. self.assertEqual(output.status_code, 200)
  3400. data = json.loads(output.get_data(as_text=True))
  3401. self.assertDictEqual(data, {"message": "Comment added"})
  3402. output = self.app.get("/api/0/test/pull-request/1")
  3403. self.assertEqual(output.status_code, 200)
  3404. data = json.loads(output.get_data(as_text=True))
  3405. data = self._clean_data(data)
  3406. data["comments"] = [] # Let's not check the comments
  3407. self.expected_data["threshold_reached"] = False
  3408. self.assertDictEqual(data, self.expected_data)
  3409. def test_api_pull_request_three_comments_two_persons_changed_to_yes(self):
  3410. """ Check the value of threshold_reach when the PR has three
  3411. comments from two person among which one changed their mind from
  3412. -1 to +1
  3413. """
  3414. # Add three comments from two users:
  3415. headers = {"Authorization": "token aaabbbcccddd"}
  3416. data = {"comment": "This is a very interesting solution :thumbsup:"}
  3417. output = self.app.post(
  3418. "/api/0/test/pull-request/1/comment", data=data, headers=headers
  3419. )
  3420. self.assertEqual(output.status_code, 200)
  3421. data = json.loads(output.get_data(as_text=True))
  3422. self.assertDictEqual(data, {"message": "Comment added"})
  3423. headers = {"Authorization": "token aaabbbcccddd_foo"}
  3424. data = {"comment": "I think the bug is elsewhere :thumbsdown:"}
  3425. output = self.app.post(
  3426. "/api/0/test/pull-request/1/comment", data=data, headers=headers
  3427. )
  3428. self.assertEqual(output.status_code, 200)
  3429. data = json.loads(output.get_data(as_text=True))
  3430. self.assertDictEqual(data, {"message": "Comment added"})
  3431. data = {"comment": "Nevermind it is here :thumbsup:"}
  3432. output = self.app.post(
  3433. "/api/0/test/pull-request/1/comment", data=data, headers=headers
  3434. )
  3435. self.assertEqual(output.status_code, 200)
  3436. data = json.loads(output.get_data(as_text=True))
  3437. self.assertDictEqual(data, {"message": "Comment added"})
  3438. output = self.app.get("/api/0/test/pull-request/1")
  3439. self.assertEqual(output.status_code, 200)
  3440. data = json.loads(output.get_data(as_text=True))
  3441. data = self._clean_data(data)
  3442. data["comments"] = [] # Let's not check the comments
  3443. self.expected_data["threshold_reached"] = True
  3444. self.assertDictEqual(data, self.expected_data)
  3445. if __name__ == "__main__":
  3446. unittest.main(verbosity=2)