test_pagure_flask_ui_fork.py 153 KB

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