test_pagure_flask_ui_fork.py 137 KB

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