test_pagure_flask_ui_fork.py 187 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258
  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, absolute_import
  8. import json
  9. import unittest
  10. import shutil
  11. import sys
  12. import tempfile
  13. import time
  14. import os
  15. import re
  16. import pygit2
  17. import six
  18. from mock import patch, MagicMock
  19. from bs4 import BeautifulSoup
  20. from datetime import datetime, timedelta
  21. sys.path.insert(
  22. 0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..")
  23. )
  24. import pagure.lib.query
  25. import pagure.lib.tasks
  26. import tests
  27. from pagure.lib.repo import PagureRepo
  28. def _get_commits(output):
  29. """ Returns the commits message in the output. All commits must have
  30. been made by `Alice Author` or `PY C` to be found.
  31. """
  32. commits = []
  33. save = False
  34. cnt = 0
  35. for row in output.split("\n"):
  36. if row.strip() in ["Alice Author", "Alice Äuthòr", "PY C"]:
  37. save = True
  38. if save:
  39. cnt += 1
  40. if cnt == 7:
  41. commits.append(row.strip())
  42. save = False
  43. cnt = 0
  44. return commits
  45. MERGED_PATTERN = (
  46. re.escape('<span class="text-info font-weight-bold">Merged</span> ')
  47. + "(just now|seconds ago)\n"
  48. + re.escape(
  49. " </span>\n by\n"
  50. ' <span title="PY C (pingou)">pingou.</span>\n'
  51. )
  52. )
  53. def set_up_git_repo(
  54. session,
  55. path,
  56. new_project=None,
  57. branch_from="feature",
  58. mtype="FF",
  59. prid=1,
  60. name_from="test",
  61. ):
  62. """ Set up the git repo and create the corresponding PullRequest
  63. object.
  64. """
  65. # Create a git repo to play with
  66. gitrepo = os.path.join(path, "repos", "%s.git" % name_from)
  67. repo = pygit2.init_repository(gitrepo, bare=True)
  68. newpath = tempfile.mkdtemp(prefix="pagure-fork-test")
  69. repopath = os.path.join(newpath, "test")
  70. clone_repo = pygit2.clone_repository(gitrepo, repopath)
  71. # Create a file in that git repo
  72. with open(os.path.join(repopath, "sources"), "w") as stream:
  73. stream.write("foo\n bar")
  74. clone_repo.index.add("sources")
  75. clone_repo.index.write()
  76. try:
  77. com = repo.revparse_single("HEAD")
  78. prev_commit = [com.oid.hex]
  79. except:
  80. prev_commit = []
  81. # Commits the files added
  82. tree = clone_repo.index.write_tree()
  83. author = pygit2.Signature("Alice Author", "alice@authors.tld")
  84. committer = pygit2.Signature("Cecil Committer", "cecil@committers.tld")
  85. clone_repo.create_commit(
  86. "refs/heads/master", # the name of the reference to update
  87. author,
  88. committer,
  89. "Add sources file for testing",
  90. # binary string representing the tree object ID
  91. tree,
  92. # list of binary strings representing parents of the new commit
  93. prev_commit,
  94. )
  95. refname = "refs/heads/master:refs/heads/master"
  96. ori_remote = clone_repo.remotes[0]
  97. PagureRepo.push(ori_remote, refname)
  98. first_commit = repo.revparse_single("HEAD")
  99. def compatible_signature(name, email):
  100. if six.PY2:
  101. name = name.encode("utf-8")
  102. email = email.encode("utf-8")
  103. return pygit2.Signature(name, email)
  104. if mtype == "merge":
  105. with open(os.path.join(repopath, ".gitignore"), "w") as stream:
  106. stream.write("*~")
  107. clone_repo.index.add(".gitignore")
  108. clone_repo.index.write()
  109. # Commits the files added
  110. tree = clone_repo.index.write_tree()
  111. author = compatible_signature("Alice Äuthòr", "alice@äuthòrs.tld")
  112. comitter = compatible_signature(
  113. "Cecil Cõmmîttër", "cecil@cõmmîttërs.tld"
  114. )
  115. clone_repo.create_commit(
  116. "refs/heads/master",
  117. author,
  118. committer,
  119. "Add .gitignore file for testing",
  120. # binary string representing the tree object ID
  121. tree,
  122. # list of binary strings representing parents of the new commit
  123. [first_commit.oid.hex],
  124. )
  125. refname = "refs/heads/master:refs/heads/master"
  126. ori_remote = clone_repo.remotes[0]
  127. PagureRepo.push(ori_remote, refname)
  128. if mtype == "conflicts":
  129. with open(os.path.join(repopath, "sources"), "w") as stream:
  130. stream.write("foo\n bar\nbaz")
  131. clone_repo.index.add("sources")
  132. clone_repo.index.write()
  133. # Commits the files added
  134. tree = clone_repo.index.write_tree()
  135. author = pygit2.Signature("Alice Author", "alice@authors.tld")
  136. committer = pygit2.Signature("Cecil Committer", "cecil@committers.tld")
  137. clone_repo.create_commit(
  138. "refs/heads/master",
  139. author,
  140. committer,
  141. "Add sources conflicting",
  142. # binary string representing the tree object ID
  143. tree,
  144. # list of binary strings representing parents of the new commit
  145. [first_commit.oid.hex],
  146. )
  147. refname = "refs/heads/master:refs/heads/master"
  148. ori_remote = clone_repo.remotes[0]
  149. PagureRepo.push(ori_remote, refname)
  150. # Set the second repo
  151. new_gitrepo = repopath
  152. if new_project:
  153. # Create a new git repo to play with
  154. new_gitrepo = os.path.join(newpath, new_project.fullname)
  155. if not os.path.exists(new_gitrepo):
  156. os.makedirs(new_gitrepo)
  157. new_repo = pygit2.clone_repository(gitrepo, new_gitrepo)
  158. repo = pygit2.Repository(new_gitrepo)
  159. if mtype != "nochanges":
  160. # Edit the sources file again
  161. with open(os.path.join(new_gitrepo, "sources"), "w") as stream:
  162. stream.write("foo\n bar\nbaz\n boose")
  163. repo.index.add("sources")
  164. repo.index.write()
  165. # Commits the files added
  166. tree = repo.index.write_tree()
  167. author = pygit2.Signature("Alice Author", "alice@authors.tld")
  168. committer = pygit2.Signature("Cecil Committer", "cecil@committers.tld")
  169. repo.create_commit(
  170. "refs/heads/%s" % branch_from,
  171. author,
  172. committer,
  173. "A commit on branch %s\n\nMore information" % branch_from,
  174. tree,
  175. [first_commit.oid.hex],
  176. )
  177. refname = "refs/heads/%s" % (branch_from)
  178. ori_remote = repo.remotes[0]
  179. PagureRepo.push(ori_remote, refname)
  180. # Create a PR for these changes
  181. project = pagure.lib.query.get_authorized_project(session, "test")
  182. req = pagure.lib.query.new_pull_request(
  183. session=session,
  184. repo_from=project,
  185. branch_from=branch_from,
  186. repo_to=project,
  187. branch_to="master",
  188. title="PR from the %s branch" % branch_from,
  189. user="pingou",
  190. )
  191. session.commit()
  192. assert req.id == prid
  193. assert req.title == "PR from the %s branch" % branch_from
  194. shutil.rmtree(newpath)
  195. class PagureFlaskForktests(tests.Modeltests):
  196. """ Tests for flask fork controller of pagure """
  197. def test_request_pull_reference(self):
  198. """ Test if there is a reference created for a new PR. """
  199. tests.create_projects(self.session)
  200. tests.create_projects_git(
  201. os.path.join(self.path, "requests"), bare=True
  202. )
  203. set_up_git_repo(
  204. self.session, self.path, new_project=None, branch_from="feature"
  205. )
  206. project = pagure.lib.query.get_authorized_project(self.session, "test")
  207. self.assertEqual(len(project.requests), 1)
  208. # View the pull-request
  209. output = self.app.get("/test/pull-request/1")
  210. self.assertEqual(output.status_code, 200)
  211. gitrepo = os.path.join(self.path, "repos", "test.git")
  212. repo = pygit2.Repository(gitrepo)
  213. self.assertEqual(
  214. list(repo.listall_references()),
  215. ["refs/heads/feature", "refs/heads/master", "refs/pull/1/head"],
  216. )
  217. @patch("pagure.lib.notify.send_email")
  218. def test_request_pull(self, send_email):
  219. """ Test the request_pull endpoint. """
  220. send_email.return_value = True
  221. tests.create_projects(self.session)
  222. tests.create_projects_git(
  223. os.path.join(self.path, "requests"), bare=True
  224. )
  225. # Non-existant project
  226. output = self.app.get("/foobar/pull-request/1")
  227. self.assertEqual(output.status_code, 404)
  228. # Project has no PR
  229. output = self.app.get("/test/pull-request/1")
  230. self.assertEqual(output.status_code, 404)
  231. set_up_git_repo(
  232. self.session, self.path, new_project=None, branch_from="feature"
  233. )
  234. project = pagure.lib.query.get_authorized_project(self.session, "test")
  235. self.assertEqual(len(project.requests), 1)
  236. # View the pull-request
  237. output = self.app.get("/test/pull-request/1")
  238. self.assertEqual(output.status_code, 200)
  239. output_text = output.get_data(as_text=True)
  240. # self.assertIn(
  241. #'<h3><span class="label label-default">PR#1</span>\n'
  242. #' PR from the feature branch\n</h3>',
  243. # output_text)
  244. self.assertIn(
  245. 'title="View file as of 2a552b">sources</a>', output_text
  246. )
  247. # Test if the `open changed file icon` is displayed.
  248. self.assertIn(
  249. 'class="open_changed_file_icon_wrap"><span '
  250. 'class="fa fa-file-code-o fa-fw" '
  251. 'alt="Open changed file" title="Open changed file"></span>'
  252. "</a>",
  253. output_text,
  254. )
  255. self.assertIn(
  256. '<span class="btn btn-success btn-sm font-weight-bold disabled'
  257. ' opacity-100">+3</span>',
  258. output_text,
  259. )
  260. self.assertIn(
  261. '<span class="btn btn-danger btn-sm font-weight-bold disabled '
  262. 'opacity-100">-1</span>',
  263. output_text,
  264. )
  265. # Test if hunk headline is rendered without line numbers
  266. self.assertIn(
  267. '<td class="cell1"></td><td class="prc border-right"></td>\n<td '
  268. 'class="cell2 stretch-table-column"> <pre class='
  269. '"text-muted"><code>@@ -1,2 +1,4 @@',
  270. output_text,
  271. )
  272. # Tests if line number 1 is displayed
  273. self.assertNotIn(
  274. '<td class="cell1"><a id="_1__1" href="#_1__1" data-line-number="1" data-file-number="1"></a></td>',
  275. output_text,
  276. )
  277. # Test if line number 2 is displayed
  278. self.assertIn(
  279. '<td class="cell1"><a id="_1__2" href="#_1__2" data-line-number="2" data-file-number="1"></a></td>',
  280. output_text,
  281. )
  282. @patch("pagure.lib.notify.send_email")
  283. def test_request_pull_delete_branch_button_no_auth(self, send_email):
  284. """ Test the request_pull endpoint. """
  285. send_email.return_value = True
  286. tests.create_projects(self.session)
  287. tests.create_projects_git(
  288. os.path.join(self.path, "requests"), bare=True
  289. )
  290. set_up_git_repo(
  291. self.session, self.path, new_project=None, branch_from="feature"
  292. )
  293. project = pagure.lib.query.get_authorized_project(self.session, "test")
  294. self.assertEqual(len(project.requests), 1)
  295. # View the pull-request
  296. output = self.app.get("/test/pull-request/1")
  297. self.assertEqual(output.status_code, 200)
  298. output_text = output.get_data(as_text=True)
  299. self.assertIn(
  300. "<title>PR#1: PR from the feature branch - test\n - "
  301. "Pagure</title>",
  302. output_text,
  303. )
  304. self.assertIn(
  305. 'title="View file as of 2a552b">sources</a>', output_text
  306. )
  307. # Un-authenticated user cannot see this checkbox
  308. self.assertNotIn(
  309. '<input id="delete_branch" name="delete_branch" type="checkbox" '
  310. 'value="y"> <label for="delete_branch">Delete branch after '
  311. "merging</label>",
  312. output_text,
  313. )
  314. @patch("pagure.lib.notify.send_email")
  315. def test_request_pull_delete_branch_button(self, send_email):
  316. """ Test the request_pull endpoint. """
  317. send_email.return_value = True
  318. tests.create_projects(self.session)
  319. tests.create_projects_git(
  320. os.path.join(self.path, "requests"), bare=True
  321. )
  322. set_up_git_repo(
  323. self.session, self.path, new_project=None, branch_from="feature"
  324. )
  325. project = pagure.lib.query.get_authorized_project(self.session, "test")
  326. self.assertEqual(len(project.requests), 1)
  327. # View the pull-request
  328. user = tests.FakeUser()
  329. user.username = "pingou"
  330. with tests.user_set(self.app.application, user):
  331. output = self.app.get("/test/pull-request/1")
  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>",
  337. output_text,
  338. )
  339. self.assertIn(
  340. 'title="View file as of 2a552b">sources</a>', output_text
  341. )
  342. self.assertIn(
  343. '<input id="delete_branch" name="delete_branch" type="checkbox" '
  344. 'value="y"> <label for="delete_branch">Delete branch after '
  345. "merging</label>",
  346. output_text,
  347. )
  348. @patch("pagure.lib.notify.send_email")
  349. def test_request_pull_delete_branch_button_no_project_from(
  350. self, send_email
  351. ):
  352. """ Test the request_pull endpoint. """
  353. send_email.return_value = True
  354. tests.create_projects(self.session)
  355. tests.create_projects_git(
  356. os.path.join(self.path, "requests"), bare=True
  357. )
  358. set_up_git_repo(
  359. self.session, self.path, new_project=None, branch_from="feature"
  360. )
  361. project = pagure.lib.query.get_authorized_project(self.session, "test")
  362. self.assertEqual(len(project.requests), 1)
  363. project.requests[0].project_from = None
  364. self.session.add(project.requests[0])
  365. self.session.commit()
  366. # View the pull-request
  367. user = tests.FakeUser()
  368. user.username = "pingou"
  369. with tests.user_set(self.app.application, user):
  370. output = self.app.get("/test/pull-request/1")
  371. self.assertEqual(output.status_code, 200)
  372. output_text = output.get_data(as_text=True)
  373. self.assertIn(
  374. "<title>PR#1: PR from the feature branch - test\n - "
  375. "Pagure</title>",
  376. output_text,
  377. )
  378. self.assertIn(
  379. 'title="View file as of 2a552b">sources</a>', output_text
  380. )
  381. self.assertIn(
  382. '<input id="delete_branch" name="delete_branch" type="checkbox" '
  383. 'value="y"> <label for="delete_branch">Delete branch after '
  384. "merging</label>",
  385. output_text,
  386. )
  387. @patch("pagure.lib.notify.send_email")
  388. def test_request_pull_delete_branch_button_no_project_from_no_acl(
  389. self, send_email
  390. ):
  391. """ Test the request_pull endpoint. """
  392. send_email.return_value = True
  393. tests.create_projects(self.session)
  394. tests.create_projects_git(
  395. os.path.join(self.path, "requests"), bare=True
  396. )
  397. set_up_git_repo(
  398. self.session, self.path, new_project=None, branch_from="feature"
  399. )
  400. project = pagure.lib.query.get_authorized_project(self.session, "test")
  401. self.assertEqual(len(project.requests), 1)
  402. project.requests[0].project_from = None
  403. self.session.add(project.requests[0])
  404. self.session.commit()
  405. # View the pull-request
  406. user = tests.FakeUser()
  407. user.username = "foo"
  408. with tests.user_set(self.app.application, user):
  409. output = self.app.get("/test/pull-request/1")
  410. self.assertEqual(output.status_code, 200)
  411. output_text = output.get_data(as_text=True)
  412. self.assertIn(
  413. "<title>PR#1: PR from the feature branch - test\n - "
  414. "Pagure</title>",
  415. output_text,
  416. )
  417. self.assertIn(
  418. 'title="View file as of 2a552b">sources</a>', output_text
  419. )
  420. self.assertNotIn(
  421. '<input id="delete_branch" name="delete_branch" type="checkbox" '
  422. 'value="y"> <label for="delete_branch">Delete branch after '
  423. "merging</label>",
  424. output_text,
  425. )
  426. @patch("pagure.lib.notify.send_email")
  427. def test_task_update_request_pull(self, send_email):
  428. """ Test the task update_pull_request endpoint. """
  429. send_email.return_value = True
  430. tests.create_projects(self.session)
  431. tests.create_projects_git(
  432. os.path.join(self.path, "requests"), bare=True
  433. )
  434. set_up_git_repo(
  435. self.session, self.path, new_project=None, branch_from="feature"
  436. )
  437. self.session = pagure.lib.query.create_session(self.dbpath)
  438. project = pagure.lib.query.get_authorized_project(self.session, "test")
  439. self.assertEqual(len(project.requests), 1)
  440. request = project.requests[0]
  441. self.assertEqual(len(request.comments), 0)
  442. start_commit = request.commit_start
  443. stop_commit = request.commit_stop
  444. # View the pull-request
  445. output = self.app.get("/test/pull-request/1")
  446. self.assertEqual(output.status_code, 200)
  447. output_text = output.get_data(as_text=True)
  448. self.assertIn(
  449. "<title>PR#1: PR from the feature branch - test\n - Pagure</title>",
  450. output_text,
  451. )
  452. self.assertIn(
  453. 'title="View file as of 2a552b">sources</a>', output_text
  454. )
  455. # Add a new commit on the repo from
  456. newpath = tempfile.mkdtemp(prefix="pagure-fork-test")
  457. gitrepo = os.path.join(self.path, "repos", "test.git")
  458. repopath = os.path.join(newpath, "test")
  459. clone_repo = pygit2.clone_repository(
  460. gitrepo, repopath, checkout_branch="feature"
  461. )
  462. def compatible_signature(name, email):
  463. if six.PY2:
  464. name = name.encode("utf-8")
  465. email = email.encode("utf-8")
  466. return pygit2.Signature(name, email)
  467. with open(os.path.join(repopath, ".gitignore"), "w") as stream:
  468. stream.write("*~")
  469. clone_repo.index.add(".gitignore")
  470. clone_repo.index.write()
  471. com = clone_repo.revparse_single("HEAD")
  472. prev_commit = [com.oid.hex]
  473. # Commits the files added
  474. tree = clone_repo.index.write_tree()
  475. author = compatible_signature("Alice Äuthòr", "alice@äuthòrs.tld")
  476. comitter = compatible_signature(
  477. "Cecil Cõmmîttër", "cecil@cõmmîttërs.tld"
  478. )
  479. clone_repo.create_commit(
  480. "refs/heads/feature",
  481. author,
  482. comitter,
  483. "Add .gitignore file for testing",
  484. # binary string representing the tree object ID
  485. tree,
  486. # list of binary strings representing parents of the new commit
  487. prev_commit,
  488. )
  489. refname = "refs/heads/feature:refs/heads/feature"
  490. ori_remote = clone_repo.remotes[0]
  491. PagureRepo.push(ori_remote, refname)
  492. shutil.rmtree(newpath)
  493. pagure.lib.tasks.update_pull_request(request.uid)
  494. self.session = pagure.lib.query.create_session(self.dbpath)
  495. project = pagure.lib.query.get_authorized_project(self.session, "test")
  496. self.assertEqual(len(project.requests), 1)
  497. request = project.requests[0]
  498. self.assertEqual(len(request.comments), 1)
  499. self.assertIsNotNone(request.commit_start)
  500. self.assertIsNotNone(request.commit_stop)
  501. self.assertNotEqual(start_commit, request.commit_start)
  502. self.assertNotEqual(stop_commit, request.commit_stop)
  503. @patch("pagure.lib.notify.send_email")
  504. def test_request_pull_ci_dropdown(self, send_email):
  505. """ Test presence of the "Rerun CI" dropdown with various settings. """
  506. send_email.return_value = True
  507. tests.create_projects(self.session)
  508. tests.create_projects_git(
  509. os.path.join(self.path, "requests"), bare=True
  510. )
  511. set_up_git_repo(
  512. self.session, self.path, new_project=None, branch_from="feature"
  513. )
  514. user = tests.FakeUser()
  515. user.username = "pingou"
  516. with tests.user_set(self.app.application, user):
  517. # old-style TRIGGER_CI list - test backwards compatibility
  518. with patch.dict(
  519. "pagure.config.config",
  520. {"TRIGGER_CI": ["old-style-trigger-ci"]},
  521. ):
  522. output = self.app.get("/test/pull-request/1")
  523. self.assertEqual(output.status_code, 200)
  524. output_text = output.get_data(as_text=True)
  525. self.assertNotIn("Rerun CI", output_text)
  526. # new-style TRIGGER_CI, but no button to show
  527. with patch.dict(
  528. "pagure.config.config", {"TRIGGER_CI": {"no-button": None}}
  529. ):
  530. output = self.app.get("/test/pull-request/1")
  531. self.assertEqual(output.status_code, 200)
  532. output_text = output.get_data(as_text=True)
  533. self.assertNotIn("Rerun CI", output_text)
  534. trigger_ci = {
  535. "foobar-ci": {
  536. "name": "foobar-ci-name",
  537. "description": "barfoo",
  538. },
  539. "spam-ci": {
  540. "name": "spam-ci-name",
  541. "description": "with beans and eggs",
  542. },
  543. "no-button-for-me-ci": None,
  544. }
  545. # new-style TRIGGER_CI, several buttons to show
  546. with patch.dict(
  547. "pagure.config.config", {"TRIGGER_CI": trigger_ci}
  548. ):
  549. output = self.app.get("/test/pull-request/1")
  550. self.assertEqual(output.status_code, 200)
  551. output_text = output.get_data(as_text=True)
  552. self.assertIn("Rerun CI", output_text)
  553. self.assertIn("foobar-ci-name", output_text)
  554. self.assertIn("spam-ci-name", output_text)
  555. self.assertNotIn("no-button-for-me-ci", output_text)
  556. trigger_ci = {
  557. "foobar-ci": {
  558. "name": "foobar-ci-name",
  559. "description": "barfoo",
  560. "requires_project_hook_attr": (
  561. "ci_hook",
  562. "active_pr",
  563. True,
  564. ),
  565. }
  566. }
  567. # new-style TRIGGER_CI with requires_project_hook_attr that is
  568. # not fulfilled by the project
  569. with patch.dict(
  570. "pagure.config.config", {"TRIGGER_CI": trigger_ci}
  571. ):
  572. output = self.app.get("/test/pull-request/1")
  573. self.assertEqual(output.status_code, 200)
  574. output_text = output.get_data(as_text=True)
  575. self.assertNotIn("Rerun CI", output_text)
  576. # now activate the hook and try again
  577. data = {
  578. "active_pr": "y",
  579. "ci_url": "https://jenkins.fedoraproject.org",
  580. "ci_job": "ci_job",
  581. "ci_type": "jenkins",
  582. "csrf_token": self.get_csrf(),
  583. }
  584. output = self.app.post(
  585. "/test/settings/Pagure CI", data=data, follow_redirects=True
  586. )
  587. self.assertEqual(output.status_code, 200)
  588. with patch.dict(
  589. "pagure.config.config", {"TRIGGER_CI": trigger_ci}
  590. ):
  591. output = self.app.get("/test/pull-request/1")
  592. self.assertEqual(output.status_code, 200)
  593. output_text = output.get_data(as_text=True)
  594. self.assertIn("Rerun CI", output_text)
  595. self.assertIn("foobar-ci-name", output_text)
  596. # shouldn't show up if user is not logged in
  597. with patch.dict("pagure.config.config", {"TRIGGER_CI": trigger_ci}):
  598. output = self.app.get("/test/pull-request/1")
  599. self.assertEqual(output.status_code, 200)
  600. output_text = output.get_data(as_text=True)
  601. self.assertNotIn("Rerun CI", output_text)
  602. @patch("pagure.lib.notify.send_email")
  603. @patch.dict(
  604. "pagure.config.config",
  605. {"TRIGGER_CI": {"CI1": {"name": "CI1", "description": "CI1!"}}},
  606. )
  607. def test_request_pull_ci_rerun(self, send_email):
  608. """ Test rerunning CI using button from the "Rerun CI" dropdown. """
  609. send_email.return_value = True
  610. tests.create_projects(self.session)
  611. tests.create_projects_git(
  612. os.path.join(self.path, "requests"), bare=True
  613. )
  614. set_up_git_repo(
  615. self.session, self.path, new_project=None, branch_from="feature"
  616. )
  617. user = tests.FakeUser()
  618. user.username = "pingou"
  619. project = pagure.lib.query.get_authorized_project(self.session, "test")
  620. request = project.requests[0]
  621. with tests.user_set(self.app.application, user):
  622. # no csrf token
  623. output = self.app.get("/test/pull-request/1")
  624. self.assertEqual(output.status_code, 200)
  625. output = self.app.post(
  626. "/test/pull-request/1/trigger-ci", follow_redirects=True
  627. )
  628. self.assertEqual(output.status_code, 200)
  629. self.assertIn("Invalid input", output.get_data(as_text=True))
  630. # no such PR
  631. output = self.app.get("/test/pull-request/1")
  632. self.assertEqual(output.status_code, 200)
  633. output = self.app.post(
  634. "/test/pull-request/2/trigger-ci", follow_redirects=True
  635. )
  636. self.assertEqual(output.status_code, 404)
  637. # wrong comment
  638. output = self.app.get("/test/pull-request/1")
  639. self.assertEqual(output.status_code, 200)
  640. csrf_token = self.get_csrf(output=output)
  641. data = {"csrf_token": csrf_token, "comment": "this doesnt exist"}
  642. output = self.app.post(
  643. "/test/pull-request/1/trigger-ci",
  644. data=data,
  645. follow_redirects=True,
  646. )
  647. self.assertEqual(output.status_code, 200)
  648. self.assertIn("Invalid input", output.get_data(as_text=True))
  649. # everything ok
  650. output = self.app.get("/test/pull-request/1")
  651. self.assertEqual(output.status_code, 200)
  652. csrf_token = self.get_csrf(output=output)
  653. data = {"csrf_token": csrf_token, "comment": "CI1"}
  654. output = self.app.post(
  655. "/test/pull-request/1/trigger-ci",
  656. data=data,
  657. follow_redirects=True,
  658. )
  659. output_text = output.get_data(as_text=True)
  660. self.assertEqual(output.status_code, 200)
  661. self.assertIn("<p>CI1</p>", output_text)
  662. comment = request.comments[0]
  663. self.assertTrue(comment.notification)
  664. self.assertEqual(comment.comment, "CI1")
  665. @patch("pagure.lib.notify.send_email")
  666. def test_merge_request_pull_FF(self, send_email):
  667. """ Test the merge_request_pull endpoint with a FF PR. """
  668. send_email.return_value = True
  669. self.test_request_pull()
  670. user = tests.FakeUser()
  671. with tests.user_set(self.app.application, user):
  672. output = self.app.get("/test/pull-request/1")
  673. self.assertEqual(output.status_code, 200)
  674. csrf_token = self.get_csrf(output=output)
  675. # No CSRF
  676. output = self.app.post(
  677. "/test/pull-request/1/merge", data={}, follow_redirects=True
  678. )
  679. self.assertEqual(output.status_code, 200)
  680. output_text = output.get_data(as_text=True)
  681. self.assertIn(
  682. "<title>PR#1: PR from the feature branch - test\n - "
  683. "Pagure</title>",
  684. output_text,
  685. )
  686. # self.assertIn(
  687. #'<h3><span class="label label-default">PR#1</span>\n'
  688. #' PR from the feature branch\n</h3>',
  689. # output_text)
  690. self.assertIn(
  691. 'title="View file as of 2a552b">sources</a>', output_text
  692. )
  693. # Wrong project
  694. data = {"csrf_token": csrf_token}
  695. output = self.app.post(
  696. "/foobar/pull-request/100/merge",
  697. data=data,
  698. follow_redirects=True,
  699. )
  700. self.assertEqual(output.status_code, 404)
  701. # Wrong project
  702. data = {"csrf_token": csrf_token}
  703. output = self.app.post(
  704. "/test/pull-request/1/merge", data=data, follow_redirects=True
  705. )
  706. self.assertEqual(output.status_code, 403)
  707. user.username = "pingou"
  708. with tests.user_set(self.app.application, user):
  709. # Wrong request id
  710. data = {"csrf_token": csrf_token}
  711. output = self.app.post(
  712. "/test/pull-request/100/merge",
  713. data=data,
  714. follow_redirects=True,
  715. )
  716. self.assertEqual(output.status_code, 404)
  717. # Project w/o pull-request
  718. self.session.commit()
  719. repo = pagure.lib.query.get_authorized_project(
  720. self.session, "test"
  721. )
  722. settings = repo.settings
  723. settings["pull_requests"] = False
  724. repo.settings = settings
  725. self.session.add(repo)
  726. self.session.commit()
  727. # Pull-request disabled
  728. output = self.app.post(
  729. "/test/pull-request/1/merge", data=data, follow_redirects=True
  730. )
  731. self.assertEqual(output.status_code, 404)
  732. # Project w pull-request but only assignee can merge
  733. self.session.commit()
  734. repo = pagure.lib.query.get_authorized_project(
  735. self.session, "test"
  736. )
  737. settings["pull_requests"] = True
  738. settings["Only_assignee_can_merge_pull-request"] = True
  739. repo.settings = settings
  740. self.session.add(repo)
  741. self.session.commit()
  742. output = self.app.post(
  743. "/test/pull-request/1/merge", data=data, follow_redirects=True
  744. )
  745. self.assertEqual(output.status_code, 200)
  746. output_text = output.get_data(as_text=True)
  747. self.assertIn(
  748. "<title>PR#1: PR from the feature branch - test\n - "
  749. "Pagure</title>",
  750. output_text,
  751. )
  752. self.assertIn(
  753. '<h4 class="ml-1">\n <div>\n '
  754. '<span class="fa fa-fw text-success fa-arrow-circle-down pt-1"></span>\n '
  755. '<span class="text-success '
  756. 'font-weight-bold">#1</span>\n '
  757. '<span class="font-weight-bold">\n '
  758. "PR from the feature branch\n",
  759. output_text,
  760. )
  761. self.assertIn(
  762. "This request must be " "assigned to be merged", output_text
  763. )
  764. # PR assigned but not to this user
  765. self.session.commit()
  766. repo = pagure.lib.query.get_authorized_project(
  767. self.session, "test"
  768. )
  769. req = repo.requests[0]
  770. req.assignee_id = 2
  771. self.session.add(req)
  772. self.session.commit()
  773. output = self.app.post(
  774. "/test/pull-request/1/merge", data=data, follow_redirects=True
  775. )
  776. self.assertEqual(output.status_code, 200)
  777. output_text = output.get_data(as_text=True)
  778. self.assertIn(
  779. '<h4 class="ml-1">\n <div>\n '
  780. '<span class="fa fa-fw text-success fa-arrow-circle-down pt-1"></span>\n '
  781. '<span class="text-success '
  782. 'font-weight-bold">#1</span>\n '
  783. '<span class="font-weight-bold">\n '
  784. "PR from the feature branch\n",
  785. output_text,
  786. )
  787. self.assertIn(
  788. "Only the assignee can merge this request", output_text
  789. )
  790. # Project w/ minimal PR score
  791. self.session.commit()
  792. repo = pagure.lib.query.get_authorized_project(
  793. self.session, "test"
  794. )
  795. settings["Only_assignee_can_merge_pull-request"] = False
  796. settings["Minimum_score_to_merge_pull-request"] = 2
  797. repo.settings = settings
  798. self.session.add(repo)
  799. self.session.commit()
  800. output = self.app.post(
  801. "/test/pull-request/1/merge", data=data, follow_redirects=True
  802. )
  803. self.assertEqual(output.status_code, 200)
  804. output_text = output.get_data(as_text=True)
  805. self.assertIn(
  806. '<h4 class="ml-1">\n <div>\n '
  807. '<span class="fa fa-fw text-success fa-arrow-circle-down pt-1"></span>\n '
  808. '<span class="text-success '
  809. 'font-weight-bold">#1</span>\n '
  810. '<span class="font-weight-bold">\n '
  811. "PR from the feature branch\n",
  812. output_text,
  813. )
  814. self.assertIn(
  815. "This request does not "
  816. "have the minimum review score necessary to be merged",
  817. output_text,
  818. )
  819. # Merge
  820. self.session.commit()
  821. repo = pagure.lib.query.get_authorized_project(
  822. self.session, "test"
  823. )
  824. settings["Minimum_score_to_merge_pull-request"] = -1
  825. repo.settings = settings
  826. self.session.add(repo)
  827. self.session.commit()
  828. output = self.app.post(
  829. "/test/pull-request/1/merge", data=data, follow_redirects=True
  830. )
  831. self.assertEqual(output.status_code, 200)
  832. output = self.app.get("/test/commits")
  833. output_text = output.get_data(as_text=True)
  834. self.assertIn(
  835. "<title>Commits - test - Pagure</title>", output_text
  836. )
  837. self.assertIn("A commit on branch feature", output_text)
  838. self.assertNotIn(
  839. "Merge #1 `PR from the feature branch`", output_text
  840. )
  841. # Check if the closing notification was added
  842. output = self.app.get("/test/pull-request/1")
  843. self.assertIsNotNone(
  844. re.search(MERGED_PATTERN, output.get_data(as_text=True))
  845. )
  846. @patch("pagure.lib.notify.send_email")
  847. def test_merge_request_pull_merge(self, send_email):
  848. """ Test the merge_request_pull endpoint with a merge PR. """
  849. send_email.return_value = True
  850. tests.create_projects(self.session)
  851. tests.create_projects_git(
  852. os.path.join(self.path, "requests"), bare=True
  853. )
  854. set_up_git_repo(
  855. self.session,
  856. self.path,
  857. new_project=None,
  858. branch_from="feature",
  859. mtype="merge",
  860. )
  861. user = tests.FakeUser()
  862. user.username = "pingou"
  863. with tests.user_set(self.app.application, user):
  864. output = self.app.get("/test/pull-request/1")
  865. self.assertEqual(output.status_code, 200)
  866. csrf_token = self.get_csrf(output=output)
  867. data = {"csrf_token": csrf_token}
  868. # Merge
  869. output = self.app.post(
  870. "/test/pull-request/1/merge", data=data, follow_redirects=True
  871. )
  872. self.assertEqual(output.status_code, 200)
  873. self.assertIn(
  874. "<title>PR#1: PR from the feature branch - test\n - Pagure</title>",
  875. output.get_data(as_text=True),
  876. )
  877. # Check if the closing notification was added
  878. output = self.app.get("/test/pull-request/1")
  879. self.assertIsNotNone(
  880. re.search(MERGED_PATTERN, output.get_data(as_text=True))
  881. )
  882. @patch("pagure.lib.notify.send_email")
  883. def test_merge_request_pull_merge_with_comment(self, send_email):
  884. """ Test the merge_request_pull endpoint with a merge PR. """
  885. send_email.return_value = True
  886. tests.create_projects(self.session)
  887. tests.create_projects_git(
  888. os.path.join(self.path, "requests"), bare=True
  889. )
  890. set_up_git_repo(
  891. self.session,
  892. self.path,
  893. new_project=None,
  894. branch_from="feature",
  895. mtype="merge",
  896. )
  897. self.session = pagure.lib.query.create_session(self.dbpath)
  898. request = pagure.lib.query.search_pull_requests(
  899. self.session, project_id=1, requestid=1
  900. )
  901. self.assertEqual(len(request.comments), 0)
  902. user = tests.FakeUser()
  903. user.username = "pingou"
  904. with tests.user_set(self.app.application, user):
  905. output = self.app.get("/test/pull-request/1")
  906. self.assertEqual(output.status_code, 200)
  907. csrf_token = self.get_csrf(output=output)
  908. data = {
  909. "csrf_token": csrf_token,
  910. "comment": "Thanks for the review and the suggestions!",
  911. }
  912. # Merge
  913. output = self.app.post(
  914. "/test/pull-request/1/merge", data=data, follow_redirects=True
  915. )
  916. self.assertEqual(output.status_code, 200)
  917. self.assertIn(
  918. "<title>PR#1: PR from the feature branch - test\n - Pagure</title>",
  919. output.get_data(as_text=True),
  920. )
  921. # Check if the closing notification was added
  922. output = self.app.get("/test/pull-request/1")
  923. output_text = output.get_data(as_text=True)
  924. self.assertIsNotNone(re.search(MERGED_PATTERN, output_text))
  925. self.assertIn(
  926. "Thanks for the review and the suggestions!", output_text
  927. )
  928. self.session = pagure.lib.query.create_session(self.dbpath)
  929. request = pagure.lib.query.search_pull_requests(
  930. self.session, project_id=1, requestid=1
  931. )
  932. self.assertEqual(len(request.comments), 2)
  933. @patch("pagure.lib.notify.send_email")
  934. def test_merge_request_pull_merge_with_delete_branch(self, send_email):
  935. """ Test the merge_request_pull endpoint with a merge PR and delete source branch. """
  936. send_email.return_value = True
  937. tests.create_projects(self.session)
  938. tests.create_projects_git(
  939. os.path.join(self.path, "requests"), bare=True
  940. )
  941. set_up_git_repo(
  942. self.session,
  943. self.path,
  944. new_project=None,
  945. branch_from="feature-branch",
  946. mtype="merge",
  947. )
  948. user = tests.FakeUser()
  949. user.username = "pingou"
  950. with tests.user_set(self.app.application, user):
  951. output = self.app.get("/test/pull-request/1")
  952. self.assertEqual(output.status_code, 200)
  953. data = {
  954. "csrf_token": self.get_csrf(output=output),
  955. "delete_branch": True,
  956. }
  957. # Merge
  958. output = self.app.post(
  959. "/test/pull-request/1/merge", data=data, follow_redirects=True
  960. )
  961. self.assertEqual(output.status_code, 200)
  962. output_text = output.get_data(as_text=True)
  963. self.assertIn(
  964. "<title>PR#1: PR from the feature-branch branch - test\n - Pagure</title>",
  965. output_text,
  966. )
  967. # Check the branch is not mentioned
  968. self.assertNotIn(
  969. '<a class="" href="/test/branch/feature-branch"', output_text
  970. )
  971. @patch("pagure.lib.notify.send_email")
  972. def test_merge_request_pull_conflicts(self, send_email):
  973. """ Test the merge_request_pull endpoint with a conflicting PR. """
  974. send_email.return_value = True
  975. tests.create_projects(self.session)
  976. tests.create_projects_git(
  977. os.path.join(self.path, "requests"), bare=True
  978. )
  979. set_up_git_repo(
  980. self.session,
  981. self.path,
  982. new_project=None,
  983. branch_from="feature",
  984. mtype="conflicts",
  985. )
  986. user = tests.FakeUser()
  987. user.username = "pingou"
  988. with tests.user_set(self.app.application, user):
  989. output = self.app.get("/test/pull-request/1")
  990. self.assertEqual(output.status_code, 200)
  991. csrf_token = self.get_csrf(output=output)
  992. data = {"csrf_token": csrf_token}
  993. # Merge conflicts
  994. output = self.app.post(
  995. "/test/pull-request/1/merge", data=data, follow_redirects=True
  996. )
  997. self.assertEqual(output.status_code, 200)
  998. output_text = output.get_data(as_text=True)
  999. self.assertIn(
  1000. '<h4 class="ml-1">\n <div>\n '
  1001. '<span class="fa fa-fw text-success fa-arrow-circle-down pt-1"></span>\n '
  1002. '<span class="text-success '
  1003. 'font-weight-bold">#1</span>\n '
  1004. '<span class="font-weight-bold">\n '
  1005. "PR from the feature branch\n",
  1006. output_text,
  1007. )
  1008. self.assertIn("Merge conflicts!", output_text)
  1009. @patch("pagure.lib.notify.send_email")
  1010. def test_merge_request_pull_conflicts_with_delete_branch(self, send_email):
  1011. """ Test the merge_request_pull endpoint with a conflicting PR and request deletion of branch. """
  1012. send_email.return_value = True
  1013. tests.create_projects(self.session)
  1014. tests.create_projects_git(
  1015. os.path.join(self.path, "requests"), bare=True
  1016. )
  1017. set_up_git_repo(
  1018. self.session,
  1019. self.path,
  1020. new_project=None,
  1021. branch_from="feature-branch",
  1022. mtype="conflicts",
  1023. )
  1024. user = tests.FakeUser()
  1025. user.username = "pingou"
  1026. with tests.user_set(self.app.application, user):
  1027. output = self.app.get("/test/pull-request/1")
  1028. self.assertEqual(output.status_code, 200)
  1029. data = {
  1030. "csrf_token": self.get_csrf(output=output),
  1031. "delete_branch": True,
  1032. }
  1033. # Merge conflicts
  1034. output = self.app.post(
  1035. "/test/pull-request/1/merge", data=data, follow_redirects=True
  1036. )
  1037. self.assertEqual(output.status_code, 200)
  1038. output_text = output.get_data(as_text=True)
  1039. self.assertIn(
  1040. '<span class="fa fa-fw text-success fa-arrow-circle-down pt-1"></span>\n'
  1041. ' <span class="text-success font-weight-bold">#1</span>\n'
  1042. ' <span class="font-weight-bold">\n'
  1043. " PR from the feature-branch branch\n",
  1044. output_text,
  1045. )
  1046. self.assertIn("Merge conflicts!", output_text)
  1047. # Check the branch still exists
  1048. output = self.app.get("/test/branches")
  1049. self.assertIn("feature-branch", output.get_data(as_text=True))
  1050. @patch("pagure.lib.notify.send_email")
  1051. def test_merge_request_pull_nochange(self, send_email):
  1052. """ Test the merge_request_pull endpoint. """
  1053. send_email.return_value = True
  1054. tests.create_projects(self.session)
  1055. tests.create_projects_git(
  1056. os.path.join(self.path, "requests"), bare=True
  1057. )
  1058. set_up_git_repo(
  1059. self.session,
  1060. self.path,
  1061. new_project=None,
  1062. branch_from="master",
  1063. mtype="nochanges",
  1064. )
  1065. user = tests.FakeUser()
  1066. user.username = "pingou"
  1067. with tests.user_set(self.app.application, user):
  1068. output = self.app.get("/test/pull-request/1")
  1069. self.assertEqual(output.status_code, 200)
  1070. csrf_token = self.get_csrf(output=output)
  1071. data = {"csrf_token": csrf_token}
  1072. # Nothing to merge
  1073. output = self.app.post(
  1074. "/test/pull-request/1/merge", data=data, follow_redirects=True
  1075. )
  1076. self.assertEqual(output.status_code, 200)
  1077. output_text = output.get_data(as_text=True)
  1078. self.assertIn(
  1079. "Nothing to do, changes were already merged", output_text
  1080. )
  1081. # Check if the closing notification was added
  1082. output = self.app.get("/test/pull-request/1")
  1083. output_text = output.get_data(as_text=True)
  1084. self.assertIsNotNone(re.search(MERGED_PATTERN, output_text))
  1085. @patch("pagure.lib.notify.send_email")
  1086. def test_request_pull_close(self, send_email):
  1087. """ Test the request_pull endpoint with a closed PR. """
  1088. send_email.return_value = True
  1089. self.test_merge_request_pull_FF()
  1090. output = self.app.get("/test/pull-request/1")
  1091. self.assertEqual(output.status_code, 200)
  1092. output_text = output.get_data(as_text=True)
  1093. self.assertIsNotNone(re.search(MERGED_PATTERN, output_text))
  1094. self.assertIn(
  1095. 'title="View file as of 2a552b">sources</a>', output_text
  1096. )
  1097. @patch("pagure.lib.notify.send_email")
  1098. def test_request_pull_disabled(self, send_email):
  1099. """ Test the request_pull endpoint with PR disabled. """
  1100. send_email.return_value = True
  1101. tests.create_projects(self.session)
  1102. tests.create_projects_git(
  1103. os.path.join(self.path, "requests"), bare=True
  1104. )
  1105. set_up_git_repo(
  1106. self.session, self.path, new_project=None, branch_from="feature"
  1107. )
  1108. # Project w/o pull-request
  1109. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  1110. settings = repo.settings
  1111. settings["pull_requests"] = False
  1112. repo.settings = settings
  1113. self.session.add(repo)
  1114. self.session.commit()
  1115. output = self.app.get("/test/pull-request/1")
  1116. self.assertEqual(output.status_code, 404)
  1117. @patch("pagure.lib.notify.send_email")
  1118. @patch("pagure.lib.git.update_pull_ref")
  1119. def test_request_pull_empty_repo(self, send_email, update_pull_ref):
  1120. """ Test the request_pull endpoint against an empty repo. """
  1121. # Mock update_pull_ref or the repo won't be empty anymore
  1122. # (the PR will have been pushed to refs/pull)
  1123. send_email.return_value = True
  1124. tests.create_projects(self.session)
  1125. item = pagure.lib.model.Project(
  1126. user_id=2, # foo
  1127. name="test",
  1128. description="test project #1",
  1129. hook_token="aaabbb",
  1130. is_fork=True,
  1131. parent_id=1,
  1132. )
  1133. self.session.add(item)
  1134. self.session.commit()
  1135. tests.create_projects_git(
  1136. os.path.join(self.path, "requests"), bare=True
  1137. )
  1138. tests.create_projects_git(
  1139. os.path.join(self.path, "repos", "forks", "foo"), bare=True
  1140. )
  1141. # Create a git repo to play with
  1142. gitrepo = os.path.join(self.path, "repos", "test.git")
  1143. self.assertFalse(os.path.exists(gitrepo))
  1144. os.makedirs(gitrepo)
  1145. repo = pygit2.init_repository(gitrepo, bare=True)
  1146. # Create a fork of this repo
  1147. newpath = tempfile.mkdtemp(prefix="pagure-fork-test")
  1148. gitrepo = os.path.join(self.path, "repos", "forks", "foo", "test.git")
  1149. new_repo = pygit2.clone_repository(gitrepo, newpath)
  1150. # Edit the sources file again
  1151. with open(os.path.join(newpath, "sources"), "w") as stream:
  1152. stream.write("foo\n bar\nbaz\n boose")
  1153. new_repo.index.add("sources")
  1154. new_repo.index.write()
  1155. # Commits the files added
  1156. tree = new_repo.index.write_tree()
  1157. author = pygit2.Signature("Alice Author", "alice@authors.tld")
  1158. committer = pygit2.Signature("Cecil Committer", "cecil@committers.tld")
  1159. new_repo.create_commit(
  1160. "refs/heads/feature",
  1161. author,
  1162. committer,
  1163. "A commit on branch feature",
  1164. tree,
  1165. [],
  1166. )
  1167. refname = "refs/heads/feature:refs/heads/feature"
  1168. ori_remote = new_repo.remotes[0]
  1169. PagureRepo.push(ori_remote, refname)
  1170. # Create a PR for these changes
  1171. project = pagure.lib.query.get_authorized_project(self.session, "test")
  1172. req = pagure.lib.query.new_pull_request(
  1173. session=self.session,
  1174. repo_from=item,
  1175. branch_from="feature",
  1176. repo_to=project,
  1177. branch_to="master",
  1178. title="PR from the feature branch",
  1179. user="pingou",
  1180. )
  1181. self.session.commit()
  1182. self.assertEqual(req.id, 1)
  1183. self.assertEqual(req.title, "PR from the feature branch")
  1184. output = self.app.get("/test/pull-request/1")
  1185. self.assertEqual(output.status_code, 200)
  1186. output_text = output.get_data(as_text=True)
  1187. self.assertIn(
  1188. '<h4 class="ml-1">\n <div>\n '
  1189. '<span class="fa fa-fw text-success fa-arrow-circle-down pt-1"></span>\n '
  1190. '<span class="text-success '
  1191. 'font-weight-bold">#1</span>\n '
  1192. '<span class="font-weight-bold">\n '
  1193. "PR from the feature branch\n",
  1194. output_text,
  1195. )
  1196. self.assertTrue(output_text.count('<span class="commitdate"'), 1)
  1197. self.assertTrue(update_pull_ref.called)
  1198. shutil.rmtree(newpath)
  1199. @patch("pagure.lib.notify.send_email")
  1200. def test_request_pull_empty_fork(self, send_email):
  1201. """ Test the request_pull endpoint from an empty fork. """
  1202. send_email.return_value = True
  1203. tests.create_projects(self.session)
  1204. item = pagure.lib.model.Project(
  1205. user_id=2, # foo
  1206. name="test",
  1207. description="test project #1",
  1208. hook_token="aaabbb",
  1209. is_fork=True,
  1210. parent_id=1,
  1211. )
  1212. self.session.add(item)
  1213. self.session.commit()
  1214. tests.create_projects_git(
  1215. os.path.join(self.path, "requests"), bare=True
  1216. )
  1217. tests.create_projects_git(
  1218. os.path.join(self.path, "repos", "forks", "foo"), bare=True
  1219. )
  1220. # Create a git repo to play with
  1221. gitrepo = os.path.join(self.path, "repos", "test.git")
  1222. self.assertFalse(os.path.exists(gitrepo))
  1223. os.makedirs(gitrepo)
  1224. repo = pygit2.init_repository(gitrepo, bare=True)
  1225. # Create a fork of this repo
  1226. newpath = tempfile.mkdtemp(prefix="pagure-fork-test")
  1227. gitrepo = os.path.join(self.path, "repos", "forks", "foo", "test.git")
  1228. new_repo = pygit2.clone_repository(gitrepo, newpath)
  1229. # Create a PR for these "changes" (there are none, both repos are
  1230. # empty)
  1231. project = pagure.lib.query.get_authorized_project(self.session, "test")
  1232. req = pagure.lib.query.new_pull_request(
  1233. session=self.session,
  1234. repo_from=item,
  1235. branch_from="feature",
  1236. repo_to=project,
  1237. branch_to="master",
  1238. title="PR from the feature branch",
  1239. user="pingou",
  1240. )
  1241. self.session.commit()
  1242. self.assertEqual(req.id, 1)
  1243. self.assertEqual(req.title, "PR from the feature branch")
  1244. output = self.app.get("/test/pull-request/1", follow_redirects=True)
  1245. self.assertEqual(output.status_code, 200)
  1246. output_text = output.get_data(as_text=True)
  1247. self.assertIn(
  1248. "<title>PR#1: PR from the feature branch - test\n - Pagure</title>",
  1249. output_text,
  1250. )
  1251. self.assertIn(
  1252. "Fork is empty, there are no "
  1253. "commits to create a pull request with",
  1254. output_text,
  1255. )
  1256. shutil.rmtree(newpath)
  1257. @patch("pagure.lib.notify.send_email")
  1258. def test_request_pulls_order(self, send_email):
  1259. """Test the request_pulls
  1260. i.e Make sure that the results are displayed
  1261. in the order required by the user"""
  1262. send_email.return_value = True
  1263. # Initially no project
  1264. output = self.app.get("/test/pull-requests")
  1265. self.assertEqual(output.status_code, 404)
  1266. tests.create_projects(self.session)
  1267. tests.create_projects_git(os.path.join(self.path, "repos"), bare=True)
  1268. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  1269. item = pagure.lib.model.Project(
  1270. user_id=2,
  1271. name="test",
  1272. description="test project #1",
  1273. hook_token="aaabbb",
  1274. is_fork=True,
  1275. parent_id=1,
  1276. )
  1277. self.session.add(item)
  1278. self.session.commit()
  1279. # create PR's to play with
  1280. # PR-1
  1281. req = pagure.lib.query.new_pull_request(
  1282. session=self.session,
  1283. repo_to=repo,
  1284. repo_from=item,
  1285. branch_from="feature",
  1286. branch_to="master",
  1287. title="PR from the feature branch",
  1288. user="pingou",
  1289. status="Open",
  1290. )
  1291. self.session.commit()
  1292. self.assertEqual(req.id, 1)
  1293. self.assertEqual(req.title, "PR from the feature branch")
  1294. # PR-2
  1295. req = pagure.lib.query.new_pull_request(
  1296. session=self.session,
  1297. repo_to=repo,
  1298. branch_to="master",
  1299. branch_from="feature",
  1300. repo_from=item,
  1301. title="test PR",
  1302. user="pingou",
  1303. status="Open",
  1304. )
  1305. self.session.commit()
  1306. self.assertEqual(req.title, "test PR")
  1307. # PR-3
  1308. req = pagure.lib.query.new_pull_request(
  1309. session=self.session,
  1310. repo_to=repo,
  1311. branch_from="feature",
  1312. branch_to="master",
  1313. repo_from=item,
  1314. title="test Invalid PR",
  1315. user="pingou",
  1316. status="Closed",
  1317. )
  1318. self.session.commit()
  1319. self.assertEqual(req.title, "test Invalid PR")
  1320. # PR-4
  1321. req = pagure.lib.query.new_pull_request(
  1322. session=self.session,
  1323. repo_to=repo,
  1324. branch_from="feature",
  1325. title="test PR for sort",
  1326. repo_from=item,
  1327. user="pingou",
  1328. branch_to="master",
  1329. status="Open",
  1330. )
  1331. self.session.commit()
  1332. self.assertEqual(req.title, "test PR for sort")
  1333. # sort by last_updated
  1334. output = self.app.get("/test/pull-requests?order_key=last_updated")
  1335. output_text = output.get_data(as_text=True)
  1336. tr_elements = re.findall(
  1337. '<div class="request-row list-group-item list-group-item-action ">(.*?)</div><!--end request-row-->',
  1338. output_text,
  1339. re.M | re.S,
  1340. )
  1341. self.assertEqual(output.status_code, 200)
  1342. # Make sure that issue four is first since it was modified last
  1343. self.assertIn('href="/test/pull-request/4"', tr_elements[0])
  1344. self.assertIn('href="/test/pull-request/2"', tr_elements[1])
  1345. self.assertIn('href="/test/pull-request/1"', tr_elements[2])
  1346. pr_one = pagure.lib.query.search_pull_requests(
  1347. self.session, project_id=1, requestid=1
  1348. )
  1349. pr_one.updated_on = datetime.utcnow() + timedelta(seconds=2)
  1350. self.session.add(pr_one)
  1351. self.session.commit()
  1352. # sort by last_updated
  1353. output = self.app.get("/test/pull-requests?order_key=last_updated")
  1354. output_text = output.get_data(as_text=True)
  1355. tr_elements = re.findall(
  1356. '<div class="request-row list-group-item list-group-item-action ">(.*?)</div><!--end request-row-->',
  1357. output_text,
  1358. re.M | re.S,
  1359. )
  1360. self.assertEqual(output.status_code, 200)
  1361. # Make sure that PR four is first since it was modified last
  1362. self.assertIn('href="/test/pull-request/1"', tr_elements[0])
  1363. # Make sure that PR two is second since it was modified second
  1364. self.assertIn('href="/test/pull-request/4"', tr_elements[1])
  1365. # Make sure that PR one is last since it was modified first
  1366. self.assertIn('href="/test/pull-request/2"', tr_elements[2])
  1367. # Now query so that the results are ascending
  1368. output = self.app.get(
  1369. "/test/pull-requests?" "order_key=last_updated&order=asc"
  1370. )
  1371. output_text = output.get_data(as_text=True)
  1372. tr_elements = re.findall(
  1373. '<div class="request-row list-group-item list-group-item-action ">(.*?)</div><!--end request-row-->',
  1374. output_text,
  1375. re.M | re.S,
  1376. )
  1377. self.assertIn('href="/test/pull-request/2"', tr_elements[0])
  1378. self.assertIn('href="/test/pull-request/4"', tr_elements[1])
  1379. self.assertIn('href="/test/pull-request/1"', tr_elements[2])
  1380. # check that search_pattern argument works
  1381. output = self.app.get("/test/pull-requests?search_pattern=feature")
  1382. output_text = output.get_data(as_text=True)
  1383. tr_elements = re.findall(
  1384. '<div class="request-row list-group-item list-group-item-action ">(.*?)</div><!--end request-row-->',
  1385. output_text,
  1386. re.M | re.S,
  1387. )
  1388. self.assertIn('href="/test/pull-request/1"', tr_elements[0])
  1389. self.assertEqual(len(tr_elements), 1)
  1390. output = self.app.get("/test/pull-requests?search_pattern=PR")
  1391. output_text = output.get_data(as_text=True)
  1392. tr_elements = re.findall(
  1393. '<div class="request-row list-group-item list-group-item-action ">(.*?)</div><!--end request-row-->',
  1394. output_text,
  1395. re.M | re.S,
  1396. )
  1397. self.assertIn('href="/test/pull-request/4"', tr_elements[0])
  1398. self.assertIn('href="/test/pull-request/2"', tr_elements[1])
  1399. self.assertIn('href="/test/pull-request/1"', tr_elements[2])
  1400. self.assertEqual(len(tr_elements), 3)
  1401. output = self.app.get("/test/pull-requests?search_pattern=*PR")
  1402. output_text = output.get_data(as_text=True)
  1403. tr_elements = re.findall(
  1404. '<div class="request-row list-group-item list-group-item-action ">(.*?)</div><!--end request-row-->',
  1405. output_text,
  1406. re.M | re.S,
  1407. )
  1408. self.assertEqual(len(tr_elements), 1)
  1409. self.assertIn('href="/test/pull-request/2"', tr_elements[0])
  1410. @patch("pagure.lib.notify.send_email")
  1411. def test_request_pulls(self, send_email):
  1412. """ Test the request_pulls endpoint. """
  1413. send_email.return_value = True
  1414. # No such project
  1415. output = self.app.get("/test/pull-requests")
  1416. self.assertEqual(output.status_code, 404)
  1417. tests.create_projects(self.session)
  1418. tests.create_projects_git(os.path.join(self.path, "repos"), bare=True)
  1419. output = self.app.get("/test/pull-requests")
  1420. self.assertEqual(output.status_code, 200)
  1421. output_text = output.get_data(as_text=True)
  1422. self.assertIn(
  1423. '<span class="fa fa-fw fa-arrow-circle-down"></span> 0 Open PRs\n',
  1424. output_text,
  1425. )
  1426. set_up_git_repo(
  1427. self.session, self.path, new_project=None, branch_from="feature"
  1428. )
  1429. output = self.app.get("/test/pull-requests")
  1430. self.assertEqual(output.status_code, 200)
  1431. output_text = output.get_data(as_text=True)
  1432. self.assertIn(
  1433. '<span class="fa fa-fw fa-arrow-circle-down"></span> 1 Open PRs\n',
  1434. output_text,
  1435. )
  1436. output = self.app.get("/test/pull-requests?status=1")
  1437. self.assertEqual(output.status_code, 200)
  1438. output_text = output.get_data(as_text=True)
  1439. self.assertIn(
  1440. '<span class="fa fa-fw fa-arrow-circle-down"></span> 1 Open PRs\n',
  1441. output_text,
  1442. )
  1443. output = self.app.get("/test/pull-requests?status=true")
  1444. self.assertEqual(output.status_code, 200)
  1445. output_text = output.get_data(as_text=True)
  1446. self.assertIn(
  1447. '<span class="fa fa-fw fa-arrow-circle-down"></span> 1 Open PRs\n',
  1448. output_text,
  1449. )
  1450. output = self.app.get("/test/pull-requests?status=Merged")
  1451. self.assertEqual(output.status_code, 200)
  1452. output_text = output.get_data(as_text=True)
  1453. self.assertIn(
  1454. '<span class="fa fa-fw fa-arrow-circle-down"></span> 0 Merged PRs\n',
  1455. output_text,
  1456. )
  1457. output = self.app.get("/test/pull-requests?status=0")
  1458. self.assertEqual(output.status_code, 200)
  1459. output_text = output.get_data(as_text=True)
  1460. self.assertIn(
  1461. '<span class="fa fa-fw fa-arrow-circle-down"></span> 0 Merged PRs\n',
  1462. output_text,
  1463. )
  1464. output = self.app.get("/test/pull-requests?status=Closed")
  1465. self.assertEqual(output.status_code, 200)
  1466. output_text = output.get_data(as_text=True)
  1467. self.assertIn(
  1468. '<span class="fa fa-fw fa-arrow-circle-down"></span> 0 Cancelled PRs\n',
  1469. output_text,
  1470. )
  1471. # Project w/o pull-request
  1472. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  1473. settings = repo.settings
  1474. settings["pull_requests"] = False
  1475. repo.settings = settings
  1476. self.session.add(repo)
  1477. self.session.commit()
  1478. output = self.app.get("/test/pull-requests")
  1479. self.assertEqual(output.status_code, 404)
  1480. @patch("pagure.lib.notify.send_email")
  1481. def test_request_pulls_filters_tags(self, send_email):
  1482. """Test the requests_pull
  1483. i.e Make sure that the results are filtered properly"""
  1484. send_email.return_value = True
  1485. tests.create_projects(self.session)
  1486. tests.create_projects_git(os.path.join(self.path, "repos"), bare=True)
  1487. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  1488. # Create some tags to play with
  1489. pagure.lib.query.new_tag(
  1490. self.session, "tag-1", "tag-1 descripcion", "#ff0000", repo.id
  1491. )
  1492. pagure.lib.query.new_tag(
  1493. self.session, "tag-2", "tag-2 description", "#00ff00", repo.id
  1494. )
  1495. pagure.lib.query.new_tag(
  1496. self.session, "tag-3", "tag-3 description", "#0000ff", repo.id
  1497. )
  1498. fork = pagure.lib.model.Project(
  1499. user_id=2,
  1500. name="test",
  1501. description="test project #1",
  1502. hook_token="aaabbb",
  1503. is_fork=True,
  1504. parent_id=1,
  1505. )
  1506. self.session.add(fork)
  1507. self.session.commit()
  1508. # Create PR's to play with
  1509. # PR-1, tags: tag-1, tag-3
  1510. req = pagure.lib.query.new_pull_request(
  1511. session=self.session,
  1512. repo_to=repo,
  1513. repo_from=fork,
  1514. branch_from="feature",
  1515. branch_to="master",
  1516. title="First PR",
  1517. user="pingou",
  1518. status="Open",
  1519. )
  1520. pagure.lib.query.update_tags(
  1521. self.session, obj=req, tags=["tag-1", "tag-3"], username="pingou"
  1522. )
  1523. self.session.commit()
  1524. # PR-2, tags: tag-2, tag-3
  1525. req = pagure.lib.query.new_pull_request(
  1526. session=self.session,
  1527. repo_to=repo,
  1528. repo_from=fork,
  1529. branch_from="feature",
  1530. branch_to="master",
  1531. title="Second PR",
  1532. user="pingou",
  1533. status="Open",
  1534. )
  1535. pagure.lib.query.update_tags(
  1536. self.session, obj=req, tags=["tag-2", "tag-3"], username="pingou"
  1537. )
  1538. self.session.commit()
  1539. # PR-3 closed, tags: tag-1, tag-3
  1540. req = pagure.lib.query.new_pull_request(
  1541. session=self.session,
  1542. repo_to=repo,
  1543. repo_from=fork,
  1544. branch_from="feature",
  1545. branch_to="master",
  1546. title="Third PR",
  1547. user="pingou",
  1548. status="Closed",
  1549. )
  1550. pagure.lib.query.update_tags(
  1551. self.session, obj=req, tags=["tag-1", "tag-3"], username="pingou"
  1552. )
  1553. self.session.commit()
  1554. # PR-4 closed, tags: tag-1, tag-2
  1555. req = pagure.lib.query.new_pull_request(
  1556. session=self.session,
  1557. repo_to=repo,
  1558. repo_from=fork,
  1559. branch_from="feature",
  1560. branch_to="master",
  1561. title="Fourth PR",
  1562. user="pingou",
  1563. status="Closed",
  1564. )
  1565. pagure.lib.query.update_tags(
  1566. self.session, obj=req, tags=["tag-1", "tag-2"], username="pingou"
  1567. )
  1568. self.session.commit()
  1569. # filter by 'tag-1'
  1570. output = self.app.get("/test/pull-requests?tags=tag-1")
  1571. self.assertEqual(output.status_code, 200)
  1572. output_text = output.get_data(as_text=True)
  1573. tr_elements = re.findall(
  1574. '<div class="request-row list-group-item list-group-item-action ">(.*?)</div><!--end request-row-->',
  1575. output_text,
  1576. re.M | re.S,
  1577. )
  1578. self.assertEqual(1, len(tr_elements))
  1579. self.assertIn('href="/test/pull-request/1', tr_elements[0])
  1580. # filter by '!tag-1'
  1581. output = self.app.get("/test/pull-requests?tags=!tag-1")
  1582. self.assertEqual(output.status_code, 200)
  1583. output_text = output.get_data(as_text=True)
  1584. tr_elements = re.findall(
  1585. '<div class="request-row list-group-item list-group-item-action ">(.*?)</div><!--end request-row-->',
  1586. output_text,
  1587. re.M | re.S,
  1588. )
  1589. self.assertEqual(1, len(tr_elements))
  1590. self.assertIn('href="/test/pull-request/2', tr_elements[0])
  1591. # filter by 'tag-2' and 'tag-3'
  1592. output = self.app.get("/test/pull-requests?tags=tag2&tags=tag-3")
  1593. self.assertEqual(output.status_code, 200)
  1594. output_text = output.get_data(as_text=True)
  1595. tr_elements = re.findall(
  1596. '<div class="request-row list-group-item list-group-item-action ">(.*?)</div><!--end request-row-->',
  1597. output_text,
  1598. re.M | re.S,
  1599. )
  1600. self.assertEqual(2, len(tr_elements))
  1601. self.assertIn('href="/test/pull-request/2', tr_elements[0])
  1602. self.assertIn('href="/test/pull-request/1', tr_elements[1])
  1603. # filter by '!tag-3'
  1604. output = self.app.get("/test/pull-requests?tags=!tag-3")
  1605. self.assertEqual(output.status_code, 200)
  1606. output_text = output.get_data(as_text=True)
  1607. tr_elements = re.findall(
  1608. '<div class="request-row list-group-item list-group-item-action ">(.*?)</div><!--end request-row-->',
  1609. output_text,
  1610. re.M | re.S,
  1611. )
  1612. self.assertEqual(0, len(tr_elements))
  1613. # filter by tag-2 on Closed prs
  1614. output = self.app.get("/test/pull-requests?status=Closed&tags=tag-2")
  1615. self.assertEqual(output.status_code, 200)
  1616. output_text = output.get_data(as_text=True)
  1617. tr_elements = re.findall(
  1618. '<div class="request-row list-group-item list-group-item-action ">(.*?)</div><!--end request-row-->',
  1619. output_text,
  1620. re.M | re.S,
  1621. )
  1622. self.assertEqual(1, len(tr_elements))
  1623. self.assertIn('href="/test/pull-request/4', tr_elements[0])
  1624. # filter by !tag-2 on Closed prs
  1625. output = self.app.get("/test/pull-requests?status=Closed&tags=!tag-2")
  1626. self.assertEqual(output.status_code, 200)
  1627. output_text = output.get_data(as_text=True)
  1628. tr_elements = re.findall(
  1629. '<div class="request-row list-group-item list-group-item-action ">(.*?)</div><!--end request-row-->',
  1630. output_text,
  1631. re.M | re.S,
  1632. )
  1633. self.assertEqual(1, len(tr_elements))
  1634. self.assertIn('href="/test/pull-request/3', tr_elements[0])
  1635. # filter by tag-2 on all the prs
  1636. output = self.app.get("/test/pull-requests?status=all&tags=tag-2")
  1637. self.assertEqual(output.status_code, 200)
  1638. output_text = output.get_data(as_text=True)
  1639. tr_elements = re.findall(
  1640. '<div class="request-row list-group-item list-group-item-action ">(.*?)</div><!--end request-row-->',
  1641. output_text,
  1642. re.M | re.S,
  1643. )
  1644. self.assertEqual(2, len(tr_elements))
  1645. self.assertIn('href="/test/pull-request/4', tr_elements[0])
  1646. self.assertIn('href="/test/pull-request/2', tr_elements[1])
  1647. @patch("pagure.lib.notify.send_email")
  1648. def test_request_pull_patch(self, send_email):
  1649. """ Test the request_pull_patch endpoint. """
  1650. send_email.return_value = True
  1651. output = self.app.get("/test/pull-request/1.patch")
  1652. self.assertEqual(output.status_code, 404)
  1653. tests.create_projects(self.session)
  1654. tests.create_projects_git(
  1655. os.path.join(self.path, "requests"), bare=True
  1656. )
  1657. set_up_git_repo(
  1658. self.session,
  1659. self.path,
  1660. new_project=None,
  1661. branch_from="feature",
  1662. mtype="merge",
  1663. )
  1664. output = self.app.get("/test/pull-request/100.patch")
  1665. self.assertEqual(output.status_code, 404)
  1666. output = self.app.get("/test/pull-request/1.patch")
  1667. self.assertEqual(output.status_code, 200)
  1668. npatch = []
  1669. for row in output.get_data(as_text=True).split("\n"):
  1670. if row.startswith("Date:"):
  1671. continue
  1672. if row.startswith("From "):
  1673. row = row.split(" ", 2)[2]
  1674. npatch.append(row)
  1675. exp = r"""Mon Sep 17 00:00:00 2001
  1676. From: Alice Author <alice@authors.tld>
  1677. Subject: A commit on branch feature
  1678. More information
  1679. ---
  1680. diff --git a/.gitignore b/.gitignore
  1681. new file mode 100644
  1682. index 0000000..e4e5f6c
  1683. --- /dev/null
  1684. +++ b/.gitignore
  1685. @@ -0,0 +1 @@
  1686. +*~
  1687. \ No newline at end of file
  1688. diff --git a/sources b/sources
  1689. index 9f44358..2a552bb 100644
  1690. --- a/sources
  1691. +++ b/sources
  1692. @@ -1,2 +1,4 @@
  1693. foo
  1694. - bar
  1695. \ No newline at end of file
  1696. + bar
  1697. +baz
  1698. + boose
  1699. \ No newline at end of file
  1700. """
  1701. patch = "\n".join(npatch)
  1702. # print patch
  1703. self.assertEqual(patch, exp)
  1704. # Project w/o pull-request
  1705. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  1706. settings = repo.settings
  1707. settings["pull_requests"] = False
  1708. repo.settings = settings
  1709. self.session.add(repo)
  1710. self.session.commit()
  1711. output = self.app.get("/test/pull-request/1.patch")
  1712. self.assertEqual(output.status_code, 404)
  1713. @patch("pagure.lib.notify.send_email")
  1714. def test_request_pull_diff(self, send_email):
  1715. """ Test the request_pull_patch endpoint. """
  1716. send_email.return_value = True
  1717. output = self.app.get("/test/pull-request/1.diff")
  1718. self.assertEqual(output.status_code, 404)
  1719. tests.create_projects(self.session)
  1720. tests.create_projects_git(
  1721. os.path.join(self.path, "requests"), bare=True
  1722. )
  1723. set_up_git_repo(
  1724. self.session,
  1725. self.path,
  1726. new_project=None,
  1727. branch_from="feature",
  1728. mtype="merge",
  1729. )
  1730. output = self.app.get("/test/pull-request/100.diff")
  1731. self.assertEqual(output.status_code, 404)
  1732. output = self.app.get("/test/pull-request/1.diff")
  1733. self.assertEqual(output.status_code, 200)
  1734. exp = r"""diff --git a/.gitignore b/.gitignore
  1735. new file mode 100644
  1736. index 0000000..e4e5f6c
  1737. --- /dev/null
  1738. +++ b/.gitignore
  1739. @@ -0,0 +1 @@
  1740. +*~
  1741. \ No newline at end of file
  1742. diff --git a/sources b/sources
  1743. index 9f44358..2a552bb 100644
  1744. --- a/sources
  1745. +++ b/sources
  1746. @@ -1,2 +1,4 @@
  1747. foo
  1748. - bar
  1749. \ No newline at end of file
  1750. + bar
  1751. +baz
  1752. + boose
  1753. \ No newline at end of file
  1754. """
  1755. self.assertEqual(output.get_data(as_text=True), exp)
  1756. # Project w/o pull-request
  1757. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  1758. settings = repo.settings
  1759. settings["pull_requests"] = False
  1760. repo.settings = settings
  1761. self.session.add(repo)
  1762. self.session.commit()
  1763. output = self.app.get("/test/pull-request/1.diff")
  1764. self.assertEqual(output.status_code, 404)
  1765. @patch("pagure.lib.notify.send_email")
  1766. def test_request_pull_patch_close(self, send_email):
  1767. """ Test the request_pull_patch endpoint with a closed PR. """
  1768. send_email.return_value = True
  1769. self.test_merge_request_pull_FF()
  1770. output = self.app.get("/test/pull-request/1.patch")
  1771. self.assertEqual(output.status_code, 200)
  1772. npatch = []
  1773. for row in output.get_data(as_text=True).split("\n"):
  1774. if row.startswith("Date:"):
  1775. continue
  1776. if row.startswith("From "):
  1777. row = row.split(" ", 2)[2]
  1778. npatch.append(row)
  1779. exp = r"""Mon Sep 17 00:00:00 2001
  1780. From: Alice Author <alice@authors.tld>
  1781. Subject: A commit on branch feature
  1782. More information
  1783. ---
  1784. diff --git a/sources b/sources
  1785. index 9f44358..2a552bb 100644
  1786. --- a/sources
  1787. +++ b/sources
  1788. @@ -1,2 +1,4 @@
  1789. foo
  1790. - bar
  1791. \ No newline at end of file
  1792. + bar
  1793. +baz
  1794. + boose
  1795. \ No newline at end of file
  1796. """
  1797. patch = "\n".join(npatch)
  1798. # print patch
  1799. self.assertEqual(patch, exp)
  1800. @patch("pagure.lib.notify.send_email")
  1801. @patch("pagure.lib.git.update_pull_ref")
  1802. def test_request_pull_patch_empty_repo(self, send_email, update_pull_ref):
  1803. """ Test the request_pull_patch endpoint against an empty repo. """
  1804. # Mock update_pull_ref or the repo won't be empty anymore
  1805. # (the PR will have been pushed to refs/pull)
  1806. send_email.return_value = True
  1807. tests.create_projects(self.session)
  1808. item = pagure.lib.model.Project(
  1809. user_id=2, # foo
  1810. name="test",
  1811. description="test project #1",
  1812. hook_token="aaabbb",
  1813. is_fork=True,
  1814. parent_id=1,
  1815. )
  1816. self.session.add(item)
  1817. self.session.commit()
  1818. tests.create_projects_git(
  1819. os.path.join(self.path, "requests"), bare=True
  1820. )
  1821. tests.create_projects_git(
  1822. os.path.join(self.path, "repos", "forks", "foo"), bare=True
  1823. )
  1824. # Create a git repo to play with
  1825. gitrepo = os.path.join(self.path, "repos", "test.git")
  1826. self.assertFalse(os.path.exists(gitrepo))
  1827. os.makedirs(gitrepo)
  1828. repo = pygit2.init_repository(gitrepo, bare=True)
  1829. # Create a fork of this repo
  1830. newpath = tempfile.mkdtemp(prefix="pagure-fork-test")
  1831. gitrepo = os.path.join(self.path, "repos", "forks", "foo", "test.git")
  1832. new_repo = pygit2.clone_repository(gitrepo, newpath)
  1833. # Edit the sources file again
  1834. with open(os.path.join(newpath, "sources"), "w") as stream:
  1835. stream.write("foo\n bar\nbaz\n boose")
  1836. new_repo.index.add("sources")
  1837. new_repo.index.write()
  1838. # Commits the files added
  1839. tree = new_repo.index.write_tree()
  1840. author = pygit2.Signature("Alice Author", "alice@authors.tld")
  1841. committer = pygit2.Signature("Cecil Committer", "cecil@committers.tld")
  1842. new_repo.create_commit(
  1843. "refs/heads/feature",
  1844. author,
  1845. committer,
  1846. "A commit on branch feature",
  1847. tree,
  1848. [],
  1849. )
  1850. refname = "refs/heads/feature:refs/heads/feature"
  1851. ori_remote = new_repo.remotes[0]
  1852. PagureRepo.push(ori_remote, refname)
  1853. # Create a PR for these "changes" (there are none, both repos are
  1854. # empty)
  1855. project = pagure.lib.query.get_authorized_project(self.session, "test")
  1856. req = pagure.lib.query.new_pull_request(
  1857. session=self.session,
  1858. repo_from=item,
  1859. branch_from="feature",
  1860. repo_to=project,
  1861. branch_to="master",
  1862. title="PR from the feature branch",
  1863. user="pingou",
  1864. )
  1865. self.session.commit()
  1866. self.assertEqual(req.id, 1)
  1867. self.assertEqual(req.title, "PR from the feature branch")
  1868. output = self.app.get(
  1869. "/test/pull-request/1.patch", follow_redirects=True
  1870. )
  1871. self.assertEqual(output.status_code, 200)
  1872. npatch = []
  1873. for row in output.get_data(as_text=True).split("\n"):
  1874. if row.startswith("Date:"):
  1875. continue
  1876. if row.startswith("From "):
  1877. row = row.split(" ", 2)[2]
  1878. npatch.append(row)
  1879. exp = r"""Mon Sep 17 00:00:00 2001
  1880. From: Alice Author <alice@authors.tld>
  1881. Subject: A commit on branch feature
  1882. ---
  1883. diff --git a/sources b/sources
  1884. new file mode 100644
  1885. index 0000000..2a552bb
  1886. --- /dev/null
  1887. +++ b/sources
  1888. @@ -0,0 +1,4 @@
  1889. +foo
  1890. + bar
  1891. +baz
  1892. + boose
  1893. \ No newline at end of file
  1894. """
  1895. patch = "\n".join(npatch)
  1896. # print patch
  1897. self.assertEqual(patch, exp)
  1898. shutil.rmtree(newpath)
  1899. @patch("pagure.lib.notify.send_email")
  1900. def test_request_pull_patch_empty_fork(self, send_email):
  1901. """ Test the request_pull_patch endpoint from an empty fork. """
  1902. send_email.return_value = True
  1903. tests.create_projects(self.session)
  1904. item = pagure.lib.model.Project(
  1905. user_id=2, # foo
  1906. name="test",
  1907. description="test project #1",
  1908. hook_token="aaabbb",
  1909. is_fork=True,
  1910. parent_id=1,
  1911. )
  1912. self.session.add(item)
  1913. self.session.commit()
  1914. tests.create_projects_git(
  1915. os.path.join(self.path, "requests"), bare=True
  1916. )
  1917. tests.create_projects_git(
  1918. os.path.join(self.path, "repos", "forks", "foo"), bare=True
  1919. )
  1920. # Create a git repo to play with
  1921. gitrepo = os.path.join(self.path, "repos", "test.git")
  1922. self.assertFalse(os.path.exists(gitrepo))
  1923. os.makedirs(gitrepo)
  1924. repo = pygit2.init_repository(gitrepo, bare=True)
  1925. # Create a fork of this repo
  1926. newpath = tempfile.mkdtemp(prefix="pagure-fork-test")
  1927. gitrepo = os.path.join(self.path, "repos", "forks", "foo", "test.git")
  1928. new_repo = pygit2.clone_repository(gitrepo, newpath)
  1929. # Create a PR for these "changes" (there are none, both repos are
  1930. # empty)
  1931. project = pagure.lib.query.get_authorized_project(self.session, "test")
  1932. req = pagure.lib.query.new_pull_request(
  1933. session=self.session,
  1934. repo_from=item,
  1935. branch_from="feature",
  1936. repo_to=project,
  1937. branch_to="master",
  1938. title="PR from the feature branch",
  1939. user="pingou",
  1940. )
  1941. self.session.commit()
  1942. self.assertEqual(req.id, 1)
  1943. self.assertEqual(req.title, "PR from the feature branch")
  1944. output = self.app.get(
  1945. "/test/pull-request/1.patch", follow_redirects=True
  1946. )
  1947. self.assertEqual(output.status_code, 200)
  1948. output_text = output.get_data(as_text=True)
  1949. self.assertIn("<title>Overview - test - Pagure</title>", output_text)
  1950. self.assertIn(
  1951. "Fork is empty, there are no "
  1952. "commits to create a pull request with",
  1953. output_text,
  1954. )
  1955. shutil.rmtree(newpath)
  1956. @patch("pagure.lib.notify.send_email")
  1957. def test_close_request_pull(self, send_email):
  1958. """ Test the close_request_pull endpoint. """
  1959. send_email.return_value = True
  1960. tests.create_projects(self.session)
  1961. tests.create_projects_git(
  1962. os.path.join(self.path, "requests"), bare=True
  1963. )
  1964. set_up_git_repo(
  1965. self.session,
  1966. self.path,
  1967. new_project=None,
  1968. branch_from="feature",
  1969. mtype="merge",
  1970. )
  1971. user = tests.FakeUser()
  1972. with tests.user_set(self.app.application, user):
  1973. output = self.app.post("/test/pull-request/close/1")
  1974. self.assertEqual(output.status_code, 302)
  1975. output = self.app.post(
  1976. "/test/pull-request/close/1", follow_redirects=True
  1977. )
  1978. self.assertEqual(output.status_code, 200)
  1979. output_text = output.get_data(as_text=True)
  1980. self.assertIn(
  1981. "<title>Overview - test - Pagure</title>", output_text
  1982. )
  1983. self.assertIn("Invalid input submitted", output_text)
  1984. output = self.app.get("/test/pull-request/1")
  1985. self.assertEqual(output.status_code, 200)
  1986. csrf_token = self.get_csrf(output=output)
  1987. data = {"csrf_token": csrf_token}
  1988. # Invalid project
  1989. output = self.app.post(
  1990. "/foo/pull-request/close/1", data=data, follow_redirects=True
  1991. )
  1992. self.assertEqual(output.status_code, 404)
  1993. # Invalid PR id
  1994. output = self.app.post(
  1995. "/test/pull-request/close/100",
  1996. data=data,
  1997. follow_redirects=True,
  1998. )
  1999. self.assertEqual(output.status_code, 404)
  2000. # Invalid user for this project
  2001. output = self.app.post(
  2002. "/test/pull-request/close/1", data=data, follow_redirects=True
  2003. )
  2004. self.assertEqual(output.status_code, 403)
  2005. user.username = "pingou"
  2006. with tests.user_set(self.app.application, user):
  2007. # Project w/o pull-request
  2008. repo = pagure.lib.query.get_authorized_project(
  2009. self.session, "test"
  2010. )
  2011. settings = repo.settings
  2012. settings["pull_requests"] = False
  2013. repo.settings = settings
  2014. self.session.add(repo)
  2015. self.session.commit()
  2016. output = self.app.post(
  2017. "/test/pull-request/close/1", data=data, follow_redirects=True
  2018. )
  2019. self.assertEqual(output.status_code, 404)
  2020. # Project w/ pull-request
  2021. repo = pagure.lib.query.get_authorized_project(
  2022. self.session, "test"
  2023. )
  2024. settings = repo.settings
  2025. settings["pull_requests"] = True
  2026. repo.settings = settings
  2027. self.session.add(repo)
  2028. self.session.commit()
  2029. output = self.app.post(
  2030. "/test/pull-request/close/1", data=data, follow_redirects=True
  2031. )
  2032. self.assertEqual(output.status_code, 200)
  2033. output_text = output.get_data(as_text=True)
  2034. self.assertIn(
  2035. "<title>Overview - test - Pagure</title>", output_text
  2036. )
  2037. self.assertIn("Pull request closed!", output_text)
  2038. @patch("pagure.lib.notify.send_email")
  2039. def test_reopen_request_pull(self, send_email):
  2040. """ Test the reopen_request_pull endpoint. """
  2041. send_email.return_value = True
  2042. tests.create_projects(self.session)
  2043. tests.create_projects_git(
  2044. os.path.join(self.path, "requests"), bare=True
  2045. )
  2046. set_up_git_repo(
  2047. self.session,
  2048. self.path,
  2049. new_project=None,
  2050. branch_from="feature",
  2051. mtype="merge",
  2052. )
  2053. user = tests.FakeUser()
  2054. with tests.user_set(self.app.application, user):
  2055. output = self.app.post("/test/pull-request/1/reopen")
  2056. self.assertEqual(output.status_code, 302)
  2057. output = self.app.post(
  2058. "/test/pull-request/1/reopen", follow_redirects=True
  2059. )
  2060. self.assertEqual(output.status_code, 200)
  2061. output_text = output.get_data(as_text=True)
  2062. self.assertIn(
  2063. "<title>PR#1: PR from the feature branch - test\n - Pagure</title>",
  2064. output_text,
  2065. )
  2066. self.assertIn(
  2067. #'Pull request reopened!',
  2068. 'return window.confirm("Are you sure you want to reopen this requested pull?")',
  2069. output_text,
  2070. )
  2071. output = self.app.get("/test/pull-request/1")
  2072. self.assertEqual(output.status_code, 200)
  2073. csrf_token = self.get_csrf(output=output)
  2074. data = {"csrf_token": csrf_token}
  2075. # Invalid project
  2076. output = self.app.post(
  2077. "/foo/pull-request/1/reopen", data=data, follow_redirects=True
  2078. )
  2079. self.assertEqual(output.status_code, 404)
  2080. # Invalid PR id
  2081. output = self.app.post(
  2082. "/test/pull-request/100/reopen",
  2083. data=data,
  2084. follow_redirects=True,
  2085. )
  2086. self.assertEqual(output.status_code, 404)
  2087. # Invalid user for this project
  2088. output = self.app.post(
  2089. "/test/pull-request/1/reopen", data=data, follow_redirects=True
  2090. )
  2091. self.assertEqual(output.status_code, 403)
  2092. user.username = "pingou"
  2093. with tests.user_set(self.app.application, user):
  2094. # Project w/o pull-request
  2095. repo = pagure.lib.query.get_authorized_project(
  2096. self.session, "test"
  2097. )
  2098. settings = repo.settings
  2099. settings["pull_requests"] = False
  2100. repo.settings = settings
  2101. self.session.add(repo)
  2102. self.session.commit()
  2103. output = self.app.post(
  2104. "/test/pull-request/1/reopen", data=data, follow_redirects=True
  2105. )
  2106. self.assertEqual(output.status_code, 404)
  2107. # Project w/ pull-request
  2108. repo = pagure.lib.query.get_authorized_project(
  2109. self.session, "test"
  2110. )
  2111. settings = repo.settings
  2112. settings["pull_requests"] = True
  2113. repo.settings = settings
  2114. self.session.add(repo)
  2115. self.session.commit()
  2116. output = self.app.post(
  2117. "/test/pull-request/cancel/1", data=data, follow_redirects=True
  2118. )
  2119. output = self.app.post(
  2120. "/test/pull-request/1/reopen", data=data, follow_redirects=True
  2121. )
  2122. self.assertEqual(output.status_code, 200)
  2123. output_text = output.get_data(as_text=True)
  2124. self.assertIn(
  2125. "<title>PR#1: PR from the feature branch - test\n - "
  2126. "Pagure</title>",
  2127. output_text,
  2128. )
  2129. self.assertIn(
  2130. 'return window.confirm("Are you sure you want to reopen this requested pull?")',
  2131. output_text,
  2132. )
  2133. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  2134. def test_update_pull_requests_assign(self):
  2135. """ Test the update_pull_requests endpoint when assigning a PR.
  2136. """
  2137. tests.create_projects(self.session)
  2138. tests.create_projects_git(
  2139. os.path.join(self.path, "requests"), bare=True
  2140. )
  2141. set_up_git_repo(
  2142. self.session, self.path, new_project=None, branch_from="feature"
  2143. )
  2144. user = tests.FakeUser()
  2145. user.username = "pingou"
  2146. with tests.user_set(self.app.application, user):
  2147. # No such project
  2148. output = self.app.post("/foo/pull-request/1/update")
  2149. self.assertEqual(output.status_code, 404)
  2150. output = self.app.post("/test/pull-request/100/update")
  2151. self.assertEqual(output.status_code, 404)
  2152. # Invalid input
  2153. output = self.app.post(
  2154. "/test/pull-request/1/update", follow_redirects=True
  2155. )
  2156. self.assertEqual(output.status_code, 200)
  2157. output_text = output.get_data(as_text=True)
  2158. self.assertIn(
  2159. "<title>PR#1: PR from the feature branch - test\n - "
  2160. "Pagure</title>",
  2161. output_text,
  2162. )
  2163. self.assertIn(
  2164. '<h4 class="ml-1">\n <div>\n '
  2165. '<span class="fa fa-fw text-success fa-arrow-circle-down pt-1"></span>\n '
  2166. '<span class="text-success '
  2167. 'font-weight-bold">#1</span>\n '
  2168. '<span class="font-weight-bold">\n '
  2169. "PR from the feature branch\n",
  2170. output_text,
  2171. )
  2172. self.assertNotIn("Request assigned", output_text)
  2173. output = self.app.get("/test/pull-request/1")
  2174. self.assertEqual(output.status_code, 200)
  2175. csrf_token = self.get_csrf(output=output)
  2176. data = {"user": "pingou"}
  2177. # No CSRF
  2178. output = self.app.post(
  2179. "/test/pull-request/1/update", data=data, follow_redirects=True
  2180. )
  2181. self.assertEqual(output.status_code, 200)
  2182. output_text = output.get_data(as_text=True)
  2183. self.assertIn(
  2184. "<title>PR#1: PR from the feature branch - test\n - "
  2185. "Pagure</title>",
  2186. output_text,
  2187. )
  2188. self.assertIn(
  2189. '<h4 class="ml-1">\n <div>\n '
  2190. '<span class="fa fa-fw text-success fa-arrow-circle-down pt-1"></span>\n '
  2191. '<span class="text-success '
  2192. 'font-weight-bold">#1</span>\n '
  2193. '<span class="font-weight-bold">\n '
  2194. "PR from the feature branch\n",
  2195. output_text,
  2196. )
  2197. self.assertNotIn("Request assigned", output_text)
  2198. # Invalid assignee
  2199. data = {"csrf_token": csrf_token, "user": "bar"}
  2200. output = self.app.post(
  2201. "/test/pull-request/1/update", data=data, follow_redirects=True
  2202. )
  2203. self.assertEqual(output.status_code, 200)
  2204. output_text = output.get_data(as_text=True)
  2205. self.assertIn(
  2206. "<title>PR#1: PR from the feature branch - test\n - "
  2207. "Pagure</title>",
  2208. output_text,
  2209. )
  2210. self.assertIn(
  2211. '<h4 class="ml-1">\n <div>\n '
  2212. '<span class="fa fa-fw text-success fa-arrow-circle-down pt-1"></span>\n '
  2213. '<span class="text-success '
  2214. 'font-weight-bold">#1</span>\n '
  2215. '<span class="font-weight-bold">\n '
  2216. "PR from the feature branch\n",
  2217. output_text,
  2218. )
  2219. self.assertIn("No user &#34;bar&#34; found", output_text)
  2220. # Assign the PR
  2221. data = {"csrf_token": csrf_token, "user": "pingou"}
  2222. user.username = "foo"
  2223. with tests.user_set(self.app.application, user):
  2224. output = self.app.post(
  2225. "/test/pull-request/1/update", data=data, follow_redirects=True
  2226. )
  2227. self.assertEqual(output.status_code, 403)
  2228. user.username = "pingou"
  2229. with tests.user_set(self.app.application, user):
  2230. output = self.app.post(
  2231. "/test/pull-request/1/update", data=data, follow_redirects=True
  2232. )
  2233. self.assertEqual(output.status_code, 200)
  2234. output_text = output.get_data(as_text=True)
  2235. self.assertIn(
  2236. "<title>PR#1: PR from the feature branch - test\n - "
  2237. "Pagure</title>",
  2238. output_text,
  2239. )
  2240. self.assertIn(
  2241. '<h4 class="ml-1">\n <div>\n '
  2242. '<span class="fa fa-fw text-success fa-arrow-circle-down pt-1"></span>\n '
  2243. '<span class="text-success '
  2244. 'font-weight-bold">#1</span>\n '
  2245. '<span class="font-weight-bold">\n '
  2246. "PR from the feature branch\n",
  2247. output_text,
  2248. )
  2249. self.assertIn("Request assigned", output_text)
  2250. # Pull-Request closed
  2251. repo = pagure.lib.query.get_authorized_project(
  2252. self.session, "test"
  2253. )
  2254. req = repo.requests[0]
  2255. req.status = "Closed"
  2256. req.closed_by_in = 1
  2257. self.session.add(req)
  2258. self.session.commit()
  2259. output = self.app.post(
  2260. "/test/pull-request/1/update", data=data, follow_redirects=True
  2261. )
  2262. self.assertEqual(output.status_code, 200)
  2263. # Project w/o pull-request
  2264. repo = pagure.lib.query.get_authorized_project(
  2265. self.session, "test"
  2266. )
  2267. settings = repo.settings
  2268. settings["pull_requests"] = False
  2269. repo.settings = settings
  2270. self.session.add(repo)
  2271. self.session.commit()
  2272. output = self.app.post(
  2273. "/test/pull-request/1/update", data=data, follow_redirects=True
  2274. )
  2275. self.assertEqual(output.status_code, 404)
  2276. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  2277. def test_update_pull_requests_tag(self):
  2278. """ Test the update_pull_requests endpoint when tagging a PR.
  2279. """
  2280. tests.create_projects(self.session)
  2281. tests.create_projects_git(
  2282. os.path.join(self.path, "requests"), bare=True
  2283. )
  2284. set_up_git_repo(
  2285. self.session, self.path, new_project=None, branch_from="feature"
  2286. )
  2287. user = tests.FakeUser()
  2288. user.username = "pingou"
  2289. with tests.user_set(self.app.application, user):
  2290. output = self.app.get("/test/pull-request/1")
  2291. self.assertEqual(output.status_code, 200)
  2292. csrf_token = self.get_csrf(output=output)
  2293. data = {"tag": "black"}
  2294. # No CSRF
  2295. output = self.app.post(
  2296. "/test/pull-request/1/update", data=data, follow_redirects=True
  2297. )
  2298. self.assertEqual(output.status_code, 200)
  2299. output_text = output.get_data(as_text=True)
  2300. self.assertIn(
  2301. "<title>PR#1: PR from the feature branch - test\n - "
  2302. "Pagure</title>",
  2303. output_text,
  2304. )
  2305. self.assertIn(
  2306. '<h4 class="ml-1">\n <div>\n '
  2307. '<span class="fa fa-fw text-success fa-arrow-circle-down pt-1"></span>\n '
  2308. '<span class="text-success '
  2309. 'font-weight-bold">#1</span>\n '
  2310. '<span class="font-weight-bold">\n '
  2311. "PR from the feature branch\n",
  2312. output_text,
  2313. )
  2314. self.assertNotIn("Request assigned", output_text)
  2315. # Tag the PR
  2316. data = {"csrf_token": csrf_token, "tag": "black"}
  2317. output = self.app.post(
  2318. "/test/pull-request/1/update", data=data, follow_redirects=True
  2319. )
  2320. self.assertEqual(output.status_code, 200)
  2321. output_text = output.get_data(as_text=True)
  2322. self.assertIn(
  2323. "<title>PR#1: PR from the feature branch - test\n - "
  2324. "Pagure</title>",
  2325. output_text,
  2326. )
  2327. self.assertIn(
  2328. '<h4 class="ml-1">\n <div>\n '
  2329. '<span class="fa fa-fw text-success fa-arrow-circle-down pt-1"></span>\n '
  2330. '<span class="text-success '
  2331. 'font-weight-bold">#1</span>\n '
  2332. '<span class="font-weight-bold">\n '
  2333. "PR from the feature branch\n",
  2334. output_text,
  2335. )
  2336. self.assertIn("Pull-request tagged with: black", output_text)
  2337. self.assertIn(
  2338. 'title="comma separated list of tags"\n '
  2339. 'value="black" />',
  2340. output_text,
  2341. )
  2342. # Try as another user
  2343. user.username = "foo"
  2344. with tests.user_set(self.app.application, user):
  2345. # Tag the PR
  2346. data = {"csrf_token": csrf_token, "tag": "blue, yellow"}
  2347. output = self.app.post(
  2348. "/test/pull-request/1/update", data=data, follow_redirects=True
  2349. )
  2350. self.assertEqual(output.status_code, 403)
  2351. # Make the PR be from foo
  2352. repo = pagure.lib.query.get_authorized_project(
  2353. self.session, "test"
  2354. )
  2355. req = repo.requests[0]
  2356. req.user_id = 2
  2357. self.session.add(req)
  2358. self.session.commit()
  2359. # Re-try to tag the PR
  2360. data = {"csrf_token": csrf_token, "tag": "blue, yellow"}
  2361. output = self.app.post(
  2362. "/test/pull-request/1/update", data=data, follow_redirects=True
  2363. )
  2364. self.assertEqual(output.status_code, 200)
  2365. soup = BeautifulSoup(output.get_data(as_text=True), "html.parser")
  2366. self.assertEqual(
  2367. soup.find("title").string,
  2368. "PR#1: PR from the feature branch - test\n - Pagure",
  2369. )
  2370. self.assertIn(
  2371. "Pull-request **un**tagged with: black",
  2372. output.get_data(as_text=True),
  2373. )
  2374. self.assertIn(
  2375. "Pull-request tagged with: blue, yellow",
  2376. output.get_data(as_text=True),
  2377. )
  2378. user.username = "pingou"
  2379. with tests.user_set(self.app.application, user):
  2380. # Pull-Request closed
  2381. repo = pagure.lib.query.get_authorized_project(
  2382. self.session, "test"
  2383. )
  2384. req = repo.requests[0]
  2385. req.status = "Closed"
  2386. req.closed_by_in = 1
  2387. self.session.add(req)
  2388. self.session.commit()
  2389. output = self.app.post(
  2390. "/test/pull-request/1/update", data=data, follow_redirects=True
  2391. )
  2392. self.assertEqual(output.status_code, 200)
  2393. # Project w/o pull-request
  2394. repo = pagure.lib.query.get_authorized_project(
  2395. self.session, "test"
  2396. )
  2397. settings = repo.settings
  2398. settings["pull_requests"] = False
  2399. repo.settings = settings
  2400. self.session.add(repo)
  2401. self.session.commit()
  2402. output = self.app.post(
  2403. "/test/pull-request/1/update", data=data, follow_redirects=True
  2404. )
  2405. self.assertEqual(output.status_code, 404)
  2406. @patch("pagure.lib.notify.send_email")
  2407. def test_fork_project(self, send_email):
  2408. """ Test the fork_project endpoint. """
  2409. send_email.return_value = True
  2410. tests.create_projects(self.session)
  2411. for folder in ["docs", "tickets", "requests", "repos"]:
  2412. tests.create_projects_git(
  2413. os.path.join(self.path, folder), bare=True
  2414. )
  2415. user = tests.FakeUser()
  2416. user.username = "pingou"
  2417. with tests.user_set(self.app.application, user):
  2418. output = self.app.post("/do_fork/test")
  2419. self.assertEqual(output.status_code, 400)
  2420. output = self.app.get("/new/")
  2421. self.assertEqual(output.status_code, 200)
  2422. self.assertIn(
  2423. "<strong>Create new Project</strong>",
  2424. output.get_data(as_text=True),
  2425. )
  2426. csrf_token = self.get_csrf(output=output)
  2427. data = {"csrf_token": csrf_token}
  2428. output = self.app.post(
  2429. "/do_fork/foo", data=data, follow_redirects=True
  2430. )
  2431. self.assertEqual(output.status_code, 404)
  2432. user.username = "foo"
  2433. with tests.user_set(self.app.application, user):
  2434. output = self.app.post("/do_fork/test")
  2435. self.assertEqual(output.status_code, 400)
  2436. data = {"csrf_token": csrf_token}
  2437. output = self.app.post(
  2438. "/do_fork/test", data=data, follow_redirects=True
  2439. )
  2440. self.assertEqual(output.status_code, 200)
  2441. @patch("pagure.lib.notify.send_email")
  2442. def test_new_request_pull_branch_space(self, send_email):
  2443. """ Test the new_request_pull endpoint. """
  2444. send_email.return_value = True
  2445. self.test_fork_project()
  2446. tests.create_projects_git(
  2447. os.path.join(self.path, "requests"), bare=True
  2448. )
  2449. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  2450. fork = pagure.lib.query.get_authorized_project(
  2451. self.session, "test", user="foo"
  2452. )
  2453. set_up_git_repo(
  2454. self.session,
  2455. self.path,
  2456. new_project=fork,
  2457. branch_from="feature",
  2458. mtype="FF",
  2459. )
  2460. user = tests.FakeUser(username="pingou")
  2461. with tests.user_set(self.app.application, user):
  2462. output = self.app.get("/test/diff/master..foo bar")
  2463. self.assertEqual(output.status_code, 400)
  2464. output_text = output.get_data(as_text=True)
  2465. self.assertIn("<p>Branch foo bar does not exist</p>", output_text)
  2466. @patch("pagure.lib.notify.send_email")
  2467. def test_new_request_pull(self, send_email):
  2468. """ Test the new_request_pull endpoint. """
  2469. send_email.return_value = True
  2470. self.test_fork_project()
  2471. tests.create_projects_git(
  2472. os.path.join(self.path, "requests"), bare=True
  2473. )
  2474. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  2475. fork = pagure.lib.query.get_authorized_project(
  2476. self.session, "test", user="foo"
  2477. )
  2478. set_up_git_repo(
  2479. self.session,
  2480. self.path,
  2481. new_project=fork,
  2482. branch_from="feature",
  2483. mtype="FF",
  2484. )
  2485. user = tests.FakeUser()
  2486. user.username = "foo"
  2487. with tests.user_set(self.app.application, user):
  2488. output = self.app.get("/foo/diff/master..feature")
  2489. self.assertEqual(output.status_code, 404)
  2490. output = self.app.get("/test/diff/master..foo")
  2491. self.assertEqual(output.status_code, 400)
  2492. output = self.app.get("/test/diff/foo..master")
  2493. self.assertEqual(output.status_code, 400)
  2494. output = self.app.get("/test/diff/feature..master")
  2495. self.assertEqual(output.status_code, 200)
  2496. output_text = output.get_data(as_text=True)
  2497. self.assertIn(
  2498. "<title>Diff from master to feature - test\n - "
  2499. "Pagure</title>",
  2500. output_text,
  2501. )
  2502. self.assertIn(
  2503. '<p class="error"> No commits found </p>', output_text
  2504. )
  2505. output = self.app.get("/test/diff/master..feature")
  2506. self.assertEqual(output.status_code, 200)
  2507. output_text = output.get_data(as_text=True)
  2508. self.assertIn(
  2509. "<title>Diff from feature to master - test\n - "
  2510. "Pagure</title>",
  2511. output_text,
  2512. )
  2513. self.assertNotIn(
  2514. '<input type="submit" class="submit positive button" '
  2515. 'value="Create">',
  2516. output_text,
  2517. )
  2518. user.username = "pingou"
  2519. with tests.user_set(self.app.application, user):
  2520. output = self.app.get("/test/diff/master..feature")
  2521. self.assertEqual(output.status_code, 200)
  2522. output_text = output.get_data(as_text=True)
  2523. self.assertIn(
  2524. "<title>Create new Pull Request for master - test\n - "
  2525. "Pagure</title>",
  2526. output_text,
  2527. )
  2528. self.assertIn(
  2529. '<input type="submit" class="btn btn-primary" value="Create Pull Request">\n',
  2530. output_text,
  2531. )
  2532. # Check that we prefilled the input fields as expected:
  2533. self.assertIn(
  2534. '<input class="form-control" id="title" name="title" '
  2535. 'placeholder="Pull Request Title" required="required" '
  2536. 'type="text" value="A commit on branch feature">',
  2537. output_text,
  2538. )
  2539. self.assertIn(
  2540. """<textarea class="form-control" rows=8 id="initial_comment" name="initial_comment"
  2541. placeholder="Describe your changes" tabindex=1>
  2542. More information</textarea>
  2543. <div id="preview" class="p-1">""",
  2544. output_text,
  2545. )
  2546. self.assertIn(
  2547. '<a class="dropdown-item branch_from_item pointer" '
  2548. 'data-value="master"><span class="fa fa-random">'
  2549. "</span> master</a>",
  2550. output_text,
  2551. )
  2552. csrf_token = self.get_csrf(output=output)
  2553. # Case 1 - Add an initial comment
  2554. data = {
  2555. "csrf_token": csrf_token,
  2556. "title": "foo bar PR",
  2557. "initial_comment": "Test Initial Comment",
  2558. }
  2559. output = self.app.post(
  2560. "/test/diff/master..feature", data=data, follow_redirects=True
  2561. )
  2562. self.assertEqual(output.status_code, 200)
  2563. output_text = output.get_data(as_text=True)
  2564. self.assertIn(
  2565. "<title>PR#2: foo bar PR - test\n - Pagure</title>",
  2566. output_text,
  2567. )
  2568. self.assertIn("<p>Test Initial Comment</p>", output_text)
  2569. self.assertEqual(output_text.count('title="PY C (pingou)"'), 2)
  2570. # Test if the `open changed file icon` is displayed.
  2571. self.assertIn(
  2572. 'class="open_changed_file_icon_wrap"><span '
  2573. 'class="fa fa-file-code-o fa-fw" '
  2574. 'alt="Open changed file" title="Open changed file"></span>'
  2575. "</a>",
  2576. output_text,
  2577. )
  2578. # Case 2 - Add an empty initial comment
  2579. data = {
  2580. "csrf_token": csrf_token,
  2581. "title": "foo bar PR",
  2582. "initial_comment": "",
  2583. }
  2584. output = self.app.post(
  2585. "/test/diff/master..feature", data=data, follow_redirects=True
  2586. )
  2587. self.assertEqual(output.status_code, 200)
  2588. output_text = output.get_data(as_text=True)
  2589. self.assertIn(
  2590. "<title>PR#3: foo bar PR - test\n - Pagure</title>",
  2591. output_text,
  2592. )
  2593. self.assertNotIn('<div id="comment-', output_text)
  2594. @patch("pagure.lib.notify.send_email")
  2595. def test_new_request_pull_filename_unicode(self, send_email):
  2596. """ Test the new_request_pull endpoint. """
  2597. send_email.return_value = True
  2598. # Create the main project in the DB
  2599. item = pagure.lib.model.Project(
  2600. user_id=1, # pingou
  2601. name="test",
  2602. description="test project #1",
  2603. hook_token="aaabbbccc",
  2604. )
  2605. item.close_status = [
  2606. "Invalid",
  2607. "Insufficient data",
  2608. "Fixed",
  2609. "Duplicate",
  2610. ]
  2611. self.session.add(item)
  2612. self.session.commit()
  2613. # Create the fork
  2614. item = pagure.lib.model.Project(
  2615. user_id=1, # pingou
  2616. name="test",
  2617. description="test project #1",
  2618. hook_token="aaabbbcccdd",
  2619. parent_id=1,
  2620. is_fork=True,
  2621. )
  2622. item.close_status = [
  2623. "Invalid",
  2624. "Insufficient data",
  2625. "Fixed",
  2626. "Duplicate",
  2627. ]
  2628. self.session.add(item)
  2629. self.session.commit()
  2630. # Create two git repos, one has 6 commits, the other 4 of which only
  2631. # 1 isn't present in the first repo
  2632. gitrepo = os.path.join(self.path, "repos", "test.git")
  2633. pygit2.init_repository(gitrepo, bare=True)
  2634. gitrepo2 = os.path.join(
  2635. self.path, "repos", "forks", "pingou", "test.git"
  2636. )
  2637. pygit2.init_repository(gitrepo2, bare=True)
  2638. newpath = tempfile.mkdtemp(prefix="pagure-fork-test")
  2639. repopath = os.path.join(newpath, "test")
  2640. clone_repo = pygit2.clone_repository(gitrepo, repopath)
  2641. # Do 2 commits to the main repo
  2642. for i in range(2):
  2643. with open(os.path.join(repopath, "sources"), "w") as stream:
  2644. stream.write("foo%s\n bar%s\n" % (i, i))
  2645. clone_repo.index.add("sources")
  2646. clone_repo.index.write()
  2647. parents = []
  2648. try:
  2649. last_commit = clone_repo.revparse_single("HEAD")
  2650. parents = [last_commit.oid.hex]
  2651. except KeyError:
  2652. pass
  2653. # Commits the files added
  2654. tree = clone_repo.index.write_tree()
  2655. author = pygit2.Signature("Alice Author", "alice@authors.tld")
  2656. committer = pygit2.Signature(
  2657. "Cecil Committer", "cecil@committers.tld"
  2658. )
  2659. clone_repo.create_commit(
  2660. "refs/heads/master", # the name of the reference to update
  2661. author,
  2662. committer,
  2663. "Editing the file sources for testing #%s" % i,
  2664. # binary string representing the tree object ID
  2665. tree,
  2666. # list of binary strings representing parents of the new commit
  2667. parents,
  2668. )
  2669. # Push to the main repo
  2670. refname = "refs/heads/master:refs/heads/master"
  2671. ori_remote = clone_repo.remotes[0]
  2672. PagureRepo.push(ori_remote, refname)
  2673. # Push to the fork repo
  2674. remote = clone_repo.create_remote("pingou_fork", gitrepo2)
  2675. PagureRepo.push(remote, refname)
  2676. # Add 1 commits to the fork repo
  2677. repopath = os.path.join(newpath, "pingou_test")
  2678. clone_repo = pygit2.clone_repository(gitrepo2, repopath)
  2679. with open(os.path.join(repopath, "soürces"), "w") as stream:
  2680. stream.write("foo\n bar\n")
  2681. clone_repo.index.add("soürces")
  2682. clone_repo.index.write()
  2683. with open(os.path.join(repopath, "fóß"), "w") as stream:
  2684. stream.write("foo\n bar\n")
  2685. clone_repo.index.add("fóß")
  2686. clone_repo.index.write()
  2687. last_commit = clone_repo.revparse_single("HEAD")
  2688. # Commits the files added
  2689. tree = clone_repo.index.write_tree()
  2690. author = pygit2.Signature("Alice Author", "alice@authors.tld")
  2691. committer = pygit2.Signature("Cecil Committer", "cecil@committers.tld")
  2692. last_commit = clone_repo.create_commit(
  2693. "refs/heads/feature_foo", # the name of the reference to update
  2694. author,
  2695. committer,
  2696. "New edition on side branch of the file sources for testing",
  2697. # binary string representing the tree object ID
  2698. tree,
  2699. # list of binary strings representing parents of the new commit
  2700. [last_commit.oid.hex],
  2701. )
  2702. # Push to the fork repo
  2703. ori_remote = clone_repo.remotes[0]
  2704. refname = "refs/heads/feature_foo:refs/heads/feature_foo"
  2705. PagureRepo.push(ori_remote, refname)
  2706. shutil.rmtree(newpath)
  2707. # Create the PR between the two repos
  2708. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  2709. forked_repo = pagure.lib.query.get_authorized_project(
  2710. self.session, "test", user="pingou"
  2711. )
  2712. req = pagure.lib.query.new_pull_request(
  2713. session=self.session,
  2714. repo_from=forked_repo,
  2715. branch_from="feature_foo",
  2716. repo_to=repo,
  2717. branch_to="master",
  2718. title="test pull-request",
  2719. user="pingou",
  2720. )
  2721. self.assertEqual(req.id, 1)
  2722. self.assertEqual(req.title, "test pull-request")
  2723. user = tests.FakeUser(username="pingou")
  2724. with tests.user_set(self.app.application, user):
  2725. output = self.app.get("/fork/pingou/test/diff/master..feature_foo")
  2726. self.assertEqual(output.status_code, 200)
  2727. output_text = output.get_data(as_text=True)
  2728. self.assertIn(
  2729. "<title>Create new Pull Request for master - fork/pingou/test\n - "
  2730. "Pagure</title>",
  2731. output_text,
  2732. )
  2733. self.assertIn(
  2734. '<input type="submit" class="btn btn-primary" value="Create Pull Request">\n',
  2735. output_text,
  2736. )
  2737. # Check that we prefilled the input fields as expected:
  2738. self.assertIn(
  2739. '<input class="form-control" id="title" name="title" '
  2740. 'placeholder="Pull Request Title" required="required" '
  2741. 'type="text" value="New edition on side branch of the file '
  2742. 'sources for testing">',
  2743. output_text,
  2744. )
  2745. self.assertIn(
  2746. '<a class="dropdown-item branch_from_item pointer" '
  2747. 'data-value="master"><span class="fa fa-random">'
  2748. "</span> master</a>",
  2749. output_text,
  2750. )
  2751. csrf_token = self.get_csrf(output=output)
  2752. # Case 1 - Add an initial comment
  2753. data = {
  2754. "csrf_token": csrf_token,
  2755. "title": "foo bar PR",
  2756. "initial_comment": "Test Initial Comment",
  2757. }
  2758. output = self.app.post(
  2759. "/fork/pingou/test/diff/master..feature_foo",
  2760. data=data,
  2761. follow_redirects=True,
  2762. )
  2763. self.assertEqual(output.status_code, 200)
  2764. output_text = output.get_data(as_text=True)
  2765. self.assertIn(
  2766. "<title>PR#2: foo bar PR - test\n - Pagure</title>",
  2767. output_text,
  2768. )
  2769. self.assertIn("<p>Test Initial Comment</p>", output_text)
  2770. self.assertEqual(output_text.count('title="PY C (pingou)"'), 2)
  2771. @patch("pagure.lib.notify.send_email")
  2772. def test_new_request_pull_req_sign_off_view(self, send_email):
  2773. """ Test the new_request_pull endpoint. """
  2774. send_email.return_value = True
  2775. self.test_fork_project()
  2776. tests.create_projects_git(
  2777. os.path.join(self.path, "requests"), bare=True
  2778. )
  2779. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  2780. fork = pagure.lib.query.get_authorized_project(
  2781. self.session, "test", user="foo"
  2782. )
  2783. # Enforce Signed-of-by in the repo
  2784. settings = repo.settings
  2785. settings["Enforce_signed-off_commits_in_pull-request"] = True
  2786. repo.settings = settings
  2787. self.session.add(repo)
  2788. self.session.commit()
  2789. set_up_git_repo(
  2790. self.session,
  2791. self.path,
  2792. new_project=fork,
  2793. branch_from="feature",
  2794. mtype="FF",
  2795. )
  2796. user = tests.FakeUser()
  2797. user.username = "foo"
  2798. with tests.user_set(self.app.application, user):
  2799. output = self.app.get("/test/diff/master..feature")
  2800. self.assertEqual(output.status_code, 200)
  2801. output_text = output.get_data(as_text=True)
  2802. self.assertIn(
  2803. "<title>Diff from feature to master - test\n - "
  2804. "Pagure</title>",
  2805. output_text,
  2806. )
  2807. self.assertIn(
  2808. "This project enforces the "
  2809. "Signed-off-by statement on all commits",
  2810. output_text,
  2811. )
  2812. self.assertNotIn(
  2813. '<input type="submit" class="btn btn-primary" value="Create Pull Request">\n',
  2814. output_text,
  2815. )
  2816. self.assertNotIn(
  2817. "This repo enforces that "
  2818. "all commits are signed off by their author.",
  2819. output_text,
  2820. )
  2821. @patch("pagure.lib.notify.send_email")
  2822. def test_new_request_pull_req_sign_off_submit(self, send_email):
  2823. """ Test the new_request_pull endpoint. """
  2824. send_email.return_value = True
  2825. self.test_fork_project()
  2826. tests.create_projects_git(
  2827. os.path.join(self.path, "requests"), bare=True
  2828. )
  2829. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  2830. fork = pagure.lib.query.get_authorized_project(
  2831. self.session, "test", user="foo"
  2832. )
  2833. # Enforce Signed-of-by in the repo
  2834. settings = repo.settings
  2835. settings["Enforce_signed-off_commits_in_pull-request"] = True
  2836. repo.settings = settings
  2837. self.session.add(repo)
  2838. self.session.commit()
  2839. set_up_git_repo(
  2840. self.session,
  2841. self.path,
  2842. new_project=fork,
  2843. branch_from="feature",
  2844. mtype="FF",
  2845. )
  2846. user = tests.FakeUser()
  2847. user.username = "pingou"
  2848. with tests.user_set(self.app.application, user):
  2849. output = self.app.get("/test/diff/master..feature")
  2850. self.assertEqual(output.status_code, 200)
  2851. output_text = output.get_data(as_text=True)
  2852. self.assertIn(
  2853. "<title>Create new Pull Request for master - test\n - "
  2854. "Pagure</title>",
  2855. output_text,
  2856. )
  2857. self.assertIn(
  2858. "This project enforces the "
  2859. "Signed-off-by statement on all commits",
  2860. output_text,
  2861. )
  2862. self.assertIn(
  2863. '<input type="submit" class="btn btn-primary" value="Create Pull Request">\n',
  2864. output_text,
  2865. )
  2866. csrf_token = self.get_csrf(output=output)
  2867. # Try to create the PR
  2868. data = {
  2869. "csrf_token": csrf_token,
  2870. "title": "foo bar PR",
  2871. "initial_comment": "Test Initial Comment",
  2872. }
  2873. output = self.app.post(
  2874. "/test/diff/master..feature", data=data, follow_redirects=True
  2875. )
  2876. self.assertEqual(output.status_code, 200)
  2877. output_text = output.get_data(as_text=True)
  2878. self.assertIn(
  2879. "<title>Create new Pull Request for master - test\n - "
  2880. "Pagure</title>",
  2881. output_text,
  2882. )
  2883. # Flashed information message
  2884. self.assertIn(
  2885. "This project enforces the "
  2886. "Signed-off-by statement on all commits",
  2887. output_text,
  2888. )
  2889. # Flashed error message
  2890. self.assertIn(
  2891. "This repo enforces that "
  2892. "all commits are signed off by their author.",
  2893. output_text,
  2894. )
  2895. self.assertIn(
  2896. '<input type="submit" class="btn btn-primary" value="Create Pull Request">\n',
  2897. output_text,
  2898. )
  2899. @patch("pagure.lib.notify.send_email")
  2900. def test_request_pull_commit_start_stop(self, send_email):
  2901. """ Test the the commit start and stop of brand new PR. """
  2902. send_email.return_value = True
  2903. self.test_fork_project()
  2904. tests.create_projects_git(
  2905. os.path.join(self.path, "requests"), bare=True
  2906. )
  2907. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  2908. fork = pagure.lib.query.get_authorized_project(
  2909. self.session, "test", user="foo"
  2910. )
  2911. set_up_git_repo(
  2912. self.session,
  2913. self.path,
  2914. new_project=fork,
  2915. branch_from="feature",
  2916. mtype="FF",
  2917. )
  2918. user = tests.FakeUser()
  2919. user.username = "pingou"
  2920. with tests.user_set(self.app.application, user):
  2921. output = self.app.get("/test/diff/master..feature")
  2922. self.assertEqual(output.status_code, 200)
  2923. output_text = output.get_data(as_text=True)
  2924. self.assertIn(
  2925. "<title>Create new Pull Request for master - test\n - "
  2926. "Pagure</title>",
  2927. output_text,
  2928. )
  2929. self.assertIn(
  2930. '<input type="submit" class="btn btn-primary" value="Create Pull Request">\n',
  2931. output_text,
  2932. )
  2933. csrf_token = self.get_csrf(output=output)
  2934. # Case 1 - Add an initial comment
  2935. data = {
  2936. "csrf_token": csrf_token,
  2937. "title": "foo bar PR",
  2938. "initial_comment": "Test Initial Comment",
  2939. }
  2940. output = self.app.post(
  2941. "/test/diff/master..feature", data=data, follow_redirects=True
  2942. )
  2943. self.assertEqual(output.status_code, 200)
  2944. output_text = output.get_data(as_text=True)
  2945. self.assertIn(
  2946. "<title>PR#2: foo bar PR - test\n - Pagure</title>",
  2947. output_text,
  2948. )
  2949. self.assertIn("<p>Test Initial Comment</p>", output_text)
  2950. # Check if commit start and stop have been set for PR#2
  2951. request = pagure.lib.query.search_pull_requests(
  2952. self.session, project_id=1, requestid=2
  2953. )
  2954. self.assertIsNotNone(request.commit_start)
  2955. self.assertIsNotNone(request.commit_stop)
  2956. @patch("pagure.lib.notify.send_email")
  2957. def test_new_request_pull_from_fork_branch(self, send_email):
  2958. """ Test creating a fork to fork PR. """
  2959. send_email.return_value = True
  2960. # Create main repo with some content
  2961. tests.create_projects(self.session)
  2962. tests.create_projects_git(os.path.join(self.path, "repos"), bare=True)
  2963. tests.add_content_git_repo(
  2964. os.path.join(self.path, "repos", "test.git")
  2965. )
  2966. # Create fork repo with more content
  2967. tests.create_projects(
  2968. self.session, is_fork=True, hook_token_suffix="fork"
  2969. )
  2970. tests.create_projects_git(
  2971. os.path.join(self.path, "repos", "forks", "pingou"), bare=True
  2972. )
  2973. tests.add_content_git_repo(
  2974. os.path.join(self.path, "repos", "forks", "pingou", "test.git")
  2975. )
  2976. tests.add_readme_git_repo(
  2977. os.path.join(self.path, "repos", "forks", "pingou", "test.git"),
  2978. branch="feature",
  2979. )
  2980. tests.add_readme_git_repo(
  2981. os.path.join(self.path, "repos", "forks", "pingou", "test.git"),
  2982. branch="random_branch",
  2983. )
  2984. user = tests.FakeUser(username="pingou")
  2985. with tests.user_set(self.app.application, user):
  2986. data = {"csrf_token": self.get_csrf()}
  2987. output = self.app.post(
  2988. "/do_fork/test", data=data, follow_redirects=True
  2989. )
  2990. self.assertEqual(output.status_code, 200)
  2991. # Check that Ralph's fork do exist
  2992. output = self.app.get("/fork/pingou/test")
  2993. self.assertEqual(output.status_code, 200)
  2994. tests.create_projects_git(
  2995. os.path.join(self.path, "requests"), bare=True
  2996. )
  2997. fork = pagure.lib.query.get_authorized_project(
  2998. self.session, "test", user="ralph"
  2999. )
  3000. set_up_git_repo(
  3001. self.session,
  3002. self.path,
  3003. new_project=fork,
  3004. branch_from="feature",
  3005. mtype="FF",
  3006. )
  3007. # Try opening a pull-request
  3008. output = self.app.get("/fork/pingou/test/diff/master..feature")
  3009. self.assertEqual(output.status_code, 200)
  3010. output_text = output.get_data(as_text=True)
  3011. self.assertIn(
  3012. "<title>Create new Pull Request for master - "
  3013. "fork/pingou/test\n - Pagure</title>",
  3014. output_text,
  3015. )
  3016. self.assertIn(
  3017. '<input type="submit" class="btn btn-primary" value="Create Pull Request">\n',
  3018. output_text,
  3019. )
  3020. self.assertIn(
  3021. '<a class="dropdown-item branch_from_item pointer" '
  3022. 'data-value="master"><span class="fa fa-random">'
  3023. "</span> master</a>",
  3024. output_text,
  3025. )
  3026. self.assertIn(
  3027. '<a class="dropdown-item branch_from_item pointer" '
  3028. 'data-value="random_branch"><span class="fa fa-random">'
  3029. "</span> random_branch</a>",
  3030. output_text,
  3031. )
  3032. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  3033. def test_new_request_pull_from_fork_fixing_ticket(self):
  3034. """ Test creating a fork to fork PR fixing a ticket. """
  3035. # Create main repo with some content
  3036. tests.create_projects(self.session)
  3037. tests.create_projects_git(os.path.join(self.path, "repos"), bare=True)
  3038. tests.add_content_git_repo(
  3039. os.path.join(self.path, "repos", "test.git")
  3040. )
  3041. # Create fork repo with more content
  3042. tests.create_projects(
  3043. self.session, is_fork=True, hook_token_suffix="fork"
  3044. )
  3045. tests.create_projects_git(
  3046. os.path.join(self.path, "repos", "forks", "pingou"), bare=True
  3047. )
  3048. tests.add_content_git_repo(
  3049. os.path.join(self.path, "repos", "forks", "pingou", "test.git")
  3050. )
  3051. tests.add_readme_git_repo(
  3052. os.path.join(self.path, "repos", "forks", "pingou", "test.git"),
  3053. branch="feature",
  3054. )
  3055. tests.add_readme_git_repo(
  3056. os.path.join(self.path, "repos", "forks", "pingou", "test.git"),
  3057. branch="random_branch",
  3058. )
  3059. # Check relations before we create the PR
  3060. project = pagure.lib.query.get_authorized_project(self.session, "test")
  3061. self.assertEqual(len(project.requests), 0)
  3062. self.assertEqual(len(project.issues), 0)
  3063. # Create issues to link to
  3064. msg = pagure.lib.query.new_issue(
  3065. session=self.session,
  3066. repo=project,
  3067. title="tést íssüé",
  3068. content="We should work on this",
  3069. user="pingou",
  3070. )
  3071. self.session.commit()
  3072. self.assertEqual(msg.title, "tést íssüé")
  3073. user = tests.FakeUser(username="pingou")
  3074. with tests.user_set(self.app.application, user):
  3075. csrf_token = self.get_csrf()
  3076. data = {"csrf_token": csrf_token}
  3077. output = self.app.post(
  3078. "/do_fork/test", data=data, follow_redirects=True
  3079. )
  3080. self.assertEqual(output.status_code, 200)
  3081. # Check that pingou's fork do exist
  3082. output = self.app.get("/fork/pingou/test")
  3083. self.assertEqual(output.status_code, 200)
  3084. tests.create_projects_git(
  3085. os.path.join(self.path, "requests"), bare=True
  3086. )
  3087. fork = pagure.lib.query.get_authorized_project(
  3088. self.session, "test", user="ralph"
  3089. )
  3090. set_up_git_repo(
  3091. self.session,
  3092. self.path,
  3093. new_project=fork,
  3094. branch_from="feature",
  3095. mtype="FF",
  3096. prid=2,
  3097. )
  3098. # Try opening a pull-request
  3099. output = self.app.get("/fork/pingou/test/diff/master..feature")
  3100. self.assertEqual(output.status_code, 200)
  3101. output_text = output.get_data(as_text=True)
  3102. self.assertIn(
  3103. "<title>Create new Pull Request for master - "
  3104. "fork/pingou/test\n - Pagure</title>",
  3105. output_text,
  3106. )
  3107. self.assertIn(
  3108. '<input type="submit" class="btn btn-primary" value="Create Pull Request">\n',
  3109. output_text,
  3110. )
  3111. self.assertIn(
  3112. '<a class="dropdown-item branch_from_item pointer" '
  3113. 'data-value="master"><span class="fa fa-random">'
  3114. "</span> master</a>",
  3115. output_text,
  3116. )
  3117. self.assertIn(
  3118. '<a class="dropdown-item branch_from_item pointer" '
  3119. 'data-value="random_branch"><span class="fa fa-random">'
  3120. "</span> random_branch</a>",
  3121. output_text,
  3122. )
  3123. data = {
  3124. "csrf_token": csrf_token,
  3125. "title": "foo bar PR",
  3126. "initial_comment": "Test Initial Comment\n\nFixes #1",
  3127. }
  3128. output = self.app.post(
  3129. "/fork/pingou/test/diff/master..feature",
  3130. data=data,
  3131. follow_redirects=True,
  3132. )
  3133. self.assertEqual(output.status_code, 200)
  3134. output_text = output.get_data(as_text=True)
  3135. self.assertIn(
  3136. "<title>PR#3: foo bar PR - test\n - Pagure</title>",
  3137. output_text,
  3138. )
  3139. self.assertIn(
  3140. "<p>Test Initial Comment</p>\n<p>Fixes <a href", output_text
  3141. )
  3142. project = pagure.lib.query.get_authorized_project(self.session, "test")
  3143. self.assertEqual(len(project.requests), 2)
  3144. self.assertEqual(len(project.requests[0].related_issues), 0)
  3145. self.assertEqual(len(project.requests[1].related_issues), 1)
  3146. self.assertEqual(len(project.issues), 1)
  3147. self.assertEqual(len(project.issues[0].related_prs), 1)
  3148. @patch("pagure.lib.notify.send_email")
  3149. def test_new_request_pull_fork_to_fork_pr_disabled(self, send_email):
  3150. """ Test creating a fork to fork PR. """
  3151. send_email.return_value = True
  3152. self.test_fork_project()
  3153. # Create a 3rd user
  3154. item = pagure.lib.model.User(
  3155. user="ralph",
  3156. fullname="Ralph bar",
  3157. password="ralph_foo",
  3158. default_email="ralph@bar.com",
  3159. )
  3160. self.session.add(item)
  3161. item = pagure.lib.model.UserEmail(user_id=3, email="ralph@bar.com")
  3162. self.session.add(item)
  3163. self.session.commit()
  3164. user = tests.FakeUser()
  3165. user.username = "ralph"
  3166. with tests.user_set(self.app.application, user):
  3167. # Have Ralph fork, foo's fork of test
  3168. output = self.app.get("/fork/foo/test")
  3169. self.assertEqual(output.status_code, 200)
  3170. output = self.app.post("/do_fork/fork/foo/test")
  3171. self.assertEqual(output.status_code, 400)
  3172. csrf_token = self.get_csrf()
  3173. data = {"csrf_token": csrf_token}
  3174. output = self.app.post(
  3175. "/do_fork/fork/foo/test", data=data, follow_redirects=True
  3176. )
  3177. self.assertEqual(output.status_code, 200)
  3178. # Check that Ralph's fork do exist
  3179. output = self.app.get("/fork/ralph/test")
  3180. self.assertEqual(output.status_code, 200)
  3181. tests.create_projects_git(
  3182. os.path.join(self.path, "requests"), bare=True
  3183. )
  3184. fork = pagure.lib.query.get_authorized_project(
  3185. self.session, "test", user="ralph"
  3186. )
  3187. set_up_git_repo(
  3188. self.session,
  3189. self.path,
  3190. new_project=fork,
  3191. branch_from="feature",
  3192. mtype="FF",
  3193. )
  3194. # Try opening a pull-request
  3195. output = self.app.get("/fork/ralph/test/diff/master..feature")
  3196. self.assertEqual(output.status_code, 404)
  3197. self.assertIn(
  3198. "<p>No pull-request allowed on this project</p>",
  3199. output.get_data(as_text=True),
  3200. )
  3201. @patch("pagure.lib.notify.send_email")
  3202. def test_new_request_pull_fork_to_fork(self, send_email):
  3203. """ Test creating a fork to fork PR. """
  3204. send_email.return_value = True
  3205. self.test_fork_project()
  3206. # Create a 3rd user
  3207. item = pagure.lib.model.User(
  3208. user="ralph",
  3209. fullname="Ralph bar",
  3210. password="ralph_foo",
  3211. default_email="ralph@bar.com",
  3212. )
  3213. self.session.add(item)
  3214. item = pagure.lib.model.UserEmail(user_id=3, email="ralph@bar.com")
  3215. self.session.add(item)
  3216. self.session.commit()
  3217. user = tests.FakeUser()
  3218. user.username = "ralph"
  3219. with tests.user_set(self.app.application, user):
  3220. # Have Ralph fork, foo's fork of test
  3221. output = self.app.get("/fork/foo/test")
  3222. self.assertEqual(output.status_code, 200)
  3223. output = self.app.post("/do_fork/fork/foo/test")
  3224. self.assertEqual(output.status_code, 400)
  3225. csrf_token = self.get_csrf()
  3226. data = {"csrf_token": csrf_token}
  3227. output = self.app.post(
  3228. "/do_fork/fork/foo/test", data=data, follow_redirects=True
  3229. )
  3230. self.assertEqual(output.status_code, 200)
  3231. # Check that Ralph's fork do exist
  3232. output = self.app.get("/fork/ralph/test")
  3233. self.assertEqual(output.status_code, 200)
  3234. tests.create_projects_git(
  3235. os.path.join(self.path, "requests"), bare=True
  3236. )
  3237. # Turn on pull-request on the fork
  3238. repo = pagure.lib.query.get_authorized_project(
  3239. self.session, "test", user="foo"
  3240. )
  3241. settings = repo.settings
  3242. settings["pull_requests"] = True
  3243. repo.settings = settings
  3244. self.session.add(repo)
  3245. self.session.commit()
  3246. # Add some content to the parent
  3247. set_up_git_repo(
  3248. self.session,
  3249. self.path,
  3250. new_project=repo,
  3251. branch_from="master",
  3252. mtype="FF",
  3253. name_from=repo.fullname,
  3254. )
  3255. fork = pagure.lib.query.get_authorized_project(
  3256. self.session, "test", user="ralph"
  3257. )
  3258. set_up_git_repo(
  3259. self.session,
  3260. self.path,
  3261. new_project=fork,
  3262. branch_from="feature",
  3263. mtype="FF",
  3264. prid=2,
  3265. name_from=fork.fullname,
  3266. )
  3267. # Try opening a pull-request
  3268. output = self.app.get("/fork/ralph/test/diff/master..feature")
  3269. self.assertEqual(output.status_code, 200)
  3270. output_text = output.get_data(as_text=True)
  3271. self.assertIn(
  3272. "<title>Create new Pull Request for master - fork/ralph/test\n - "
  3273. "Pagure</title>",
  3274. output_text,
  3275. )
  3276. self.assertIn(
  3277. '<input type="submit" class="btn btn-primary" value="Create Pull Request">\n',
  3278. output_text,
  3279. )
  3280. csrf_token = self.get_csrf(output=output)
  3281. # Case 1 - Add an initial comment
  3282. data = {
  3283. "csrf_token": csrf_token,
  3284. "title": "foo bar PR",
  3285. "initial_comment": "Test Initial Comment",
  3286. }
  3287. output = self.app.post(
  3288. "/fork/ralph/test/diff/master..feature",
  3289. data=data,
  3290. follow_redirects=True,
  3291. )
  3292. self.assertEqual(output.status_code, 200)
  3293. output_text = output.get_data(as_text=True)
  3294. self.assertIn(
  3295. "<title>PR#1: foo bar PR - fork/foo/test\n - Pagure</title>",
  3296. output_text,
  3297. )
  3298. self.assertIn("<p>Test Initial Comment</p>", output_text)
  3299. @patch("pagure.lib.notify.send_email")
  3300. def test_new_request_pull_fork_to_other_fork(self, send_email):
  3301. """ Test creating a PR from fork to a fork of the same family. """
  3302. send_email.return_value = True
  3303. self.test_fork_project()
  3304. # Create a 3rd user
  3305. item = pagure.lib.model.User(
  3306. user="ralph",
  3307. fullname="Ralph bar",
  3308. password="ralph_foo",
  3309. default_email="ralph@bar.com",
  3310. )
  3311. self.session.add(item)
  3312. item = pagure.lib.model.UserEmail(user_id=3, email="ralph@bar.com")
  3313. self.session.add(item)
  3314. self.session.commit()
  3315. user = tests.FakeUser()
  3316. user.username = "ralph"
  3317. with tests.user_set(self.app.application, user):
  3318. csrf_token = self.get_csrf()
  3319. data = {"csrf_token": csrf_token}
  3320. output = self.app.post(
  3321. "/do_fork/test", data=data, follow_redirects=True
  3322. )
  3323. self.assertEqual(output.status_code, 200)
  3324. # Check that Ralph's fork do exist
  3325. output = self.app.get("/fork/ralph/test")
  3326. self.assertEqual(output.status_code, 200)
  3327. tests.create_projects_git(
  3328. os.path.join(self.path, "requests"), bare=True
  3329. )
  3330. # Turn on pull-request on the fork
  3331. repo = pagure.lib.query.get_authorized_project(
  3332. self.session, "test", user="foo"
  3333. )
  3334. settings = repo.settings
  3335. settings["pull_requests"] = True
  3336. repo.settings = settings
  3337. self.session.add(repo)
  3338. self.session.commit()
  3339. # Add some content to the parents
  3340. set_up_git_repo(
  3341. self.session,
  3342. self.path,
  3343. new_project=repo,
  3344. branch_from="master",
  3345. mtype="FF",
  3346. )
  3347. set_up_git_repo(
  3348. self.session,
  3349. self.path,
  3350. new_project=repo,
  3351. branch_from="master",
  3352. mtype="FF",
  3353. name_from=repo.fullname,
  3354. prid=2,
  3355. )
  3356. fork = pagure.lib.query.get_authorized_project(
  3357. self.session, "test", user="ralph"
  3358. )
  3359. set_up_git_repo(
  3360. self.session,
  3361. self.path,
  3362. new_project=fork,
  3363. branch_from="feature",
  3364. mtype="FF",
  3365. prid=3,
  3366. name_from=fork.fullname,
  3367. )
  3368. # Try opening a pull-request
  3369. output = self.app.get(
  3370. "/fork/ralph/test/diff/master..feature?project_to=fork/foo/test"
  3371. )
  3372. self.assertEqual(output.status_code, 200)
  3373. output_text = output.get_data(as_text=True)
  3374. self.assertIn(
  3375. "<title>Create new Pull Request for master - fork/ralph/test\n - "
  3376. "Pagure</title>",
  3377. output_text,
  3378. )
  3379. self.assertIn(
  3380. '<input type="submit" class="btn btn-primary" value="Create Pull Request">\n',
  3381. output_text,
  3382. )
  3383. csrf_token = self.get_csrf(output=output)
  3384. # Case 1 - Opening PR to fork/foo/test
  3385. data = {
  3386. "csrf_token": csrf_token,
  3387. "title": "foo bar PR",
  3388. "initial_comment": "Test Initial Comment",
  3389. }
  3390. output = self.app.post(
  3391. "/fork/ralph/test/diff/master..feature?project_to=fork/foo/test",
  3392. data=data,
  3393. follow_redirects=True,
  3394. )
  3395. self.assertEqual(output.status_code, 200)
  3396. output_text = output.get_data(as_text=True)
  3397. self.assertIn(
  3398. "<title>PR#1: foo bar PR - fork/foo/test\n - Pagure</title>",
  3399. output_text,
  3400. )
  3401. self.assertIn("<p>Test Initial Comment</p>", output_text)
  3402. # Case 1 - Opening PR to parent repo, shows project_to works
  3403. output = self.app.post(
  3404. "/fork/ralph/test/diff/master..feature",
  3405. data=data,
  3406. follow_redirects=True,
  3407. )
  3408. self.assertEqual(output.status_code, 200)
  3409. output_text = output.get_data(as_text=True)
  3410. self.assertIn(
  3411. "<title>PR#4: foo bar PR - test\n - Pagure</title>",
  3412. output_text,
  3413. )
  3414. self.assertIn("<p>Test Initial Comment</p>", output_text)
  3415. @patch("pagure.lib.notify.send_email")
  3416. def test_new_request_pull_fork_to_other_unrelated_fork(self, send_email):
  3417. """ Test creating a PR from fork to fork that isn't from the same
  3418. family.
  3419. """
  3420. send_email.return_value = True
  3421. self.test_fork_project()
  3422. # Create a 3rd user
  3423. item = pagure.lib.model.User(
  3424. user="ralph",
  3425. fullname="Ralph bar",
  3426. password="ralph_foo",
  3427. default_email="ralph@bar.com",
  3428. )
  3429. self.session.add(item)
  3430. item = pagure.lib.model.UserEmail(user_id=3, email="ralph@bar.com")
  3431. self.session.add(item)
  3432. self.session.commit()
  3433. user = tests.FakeUser()
  3434. user.username = "ralph"
  3435. with tests.user_set(self.app.application, user):
  3436. csrf_token = self.get_csrf()
  3437. data = {"csrf_token": csrf_token}
  3438. output = self.app.post(
  3439. "/do_fork/test2", data=data, follow_redirects=True
  3440. )
  3441. self.assertEqual(output.status_code, 200)
  3442. # Check that Ralph's fork do exist
  3443. output = self.app.get("/fork/ralph/test2")
  3444. self.assertEqual(output.status_code, 200)
  3445. tests.create_projects_git(
  3446. os.path.join(self.path, "requests"), bare=True
  3447. )
  3448. # Turn on pull-request on the fork
  3449. repo = pagure.lib.query.get_authorized_project(
  3450. self.session, "test", user="foo"
  3451. )
  3452. settings = repo.settings
  3453. settings["pull_requests"] = True
  3454. repo.settings = settings
  3455. self.session.add(repo)
  3456. self.session.commit()
  3457. # Add some content to the parent
  3458. set_up_git_repo(
  3459. self.session,
  3460. self.path,
  3461. new_project=repo,
  3462. branch_from="master",
  3463. mtype="FF",
  3464. name_from=repo.fullname,
  3465. )
  3466. fork = pagure.lib.query.get_authorized_project(
  3467. self.session, "test2", user="ralph"
  3468. )
  3469. set_up_git_repo(
  3470. self.session,
  3471. self.path,
  3472. new_project=fork,
  3473. branch_from="feature",
  3474. mtype="FF",
  3475. prid=2,
  3476. name_from=fork.fullname,
  3477. )
  3478. # Case 1 - Opening PR to fork/foo/test
  3479. data = {
  3480. "csrf_token": csrf_token,
  3481. "title": "foo bar PR",
  3482. "initial_comment": "Test Initial Comment",
  3483. }
  3484. output = self.app.post(
  3485. "/fork/ralph/test2/diff/master..feature?project_to=fork/foo/test",
  3486. data=data,
  3487. follow_redirects=True,
  3488. )
  3489. self.assertEqual(output.status_code, 400)
  3490. self.assertIn(
  3491. "<p>fork/foo/test is not part of fork/ralph/test2's "
  3492. "family</p>",
  3493. output.get_data(as_text=True),
  3494. )
  3495. @patch("pagure.lib.notify.send_email")
  3496. def test_new_request_pull_empty_repo(self, send_email):
  3497. """ Test the new_request_pull endpoint against an empty repo. """
  3498. send_email.return_value = True
  3499. self.test_fork_project()
  3500. tests.create_projects_git(
  3501. os.path.join(self.path, "requests"), bare=True
  3502. )
  3503. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  3504. fork = pagure.lib.query.get_authorized_project(
  3505. self.session, "test", user="foo"
  3506. )
  3507. # Create a git repo to play with
  3508. gitrepo = os.path.join(self.path, "repos", "test.git")
  3509. repo = pygit2.init_repository(gitrepo, bare=True)
  3510. # Create a fork of this repo
  3511. newpath = tempfile.mkdtemp(prefix="pagure-fork-test")
  3512. gitrepo = os.path.join(self.path, "repos", "forks", "foo", "test.git")
  3513. new_repo = pygit2.clone_repository(gitrepo, newpath)
  3514. user = tests.FakeUser()
  3515. user.username = "foo"
  3516. with tests.user_set(self.app.application, user):
  3517. output = self.app.get(
  3518. "/fork/foo/test/diff/master..feature", follow_redirects=True
  3519. )
  3520. self.assertEqual(output.status_code, 400)
  3521. self.assertIn(
  3522. "<p>Fork is empty, there are no commits to create a pull "
  3523. "request with</p>",
  3524. output.get_data(as_text=True),
  3525. )
  3526. output = self.app.get("/test/new_issue")
  3527. csrf_token = self.get_csrf(output=output)
  3528. data = {"csrf_token": csrf_token, "title": "foo bar PR"}
  3529. output = self.app.post(
  3530. "/test/diff/master..feature", data=data, follow_redirects=True
  3531. )
  3532. self.assertEqual(output.status_code, 400)
  3533. self.assertIn(
  3534. "<p>Fork is empty, there are no commits to create a pull "
  3535. "request with</p>",
  3536. output.get_data(as_text=True),
  3537. )
  3538. shutil.rmtree(newpath)
  3539. @patch("pagure.lib.notify.send_email")
  3540. def test_new_request_pull_empty_fork(self, send_email):
  3541. """ Test the new_request_pull endpoint against an empty repo. """
  3542. send_email.return_value = True
  3543. self.test_fork_project()
  3544. tests.create_projects_git(
  3545. os.path.join(self.path, "requests"), bare=True
  3546. )
  3547. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  3548. fork = pagure.lib.query.get_authorized_project(
  3549. self.session, "test", user="foo"
  3550. )
  3551. # Create a git repo to play with
  3552. gitrepo = os.path.join(self.path, "repos", "test.git")
  3553. repo = pygit2.init_repository(gitrepo, bare=True)
  3554. # Create a fork of this repo
  3555. newpath = tempfile.mkdtemp(prefix="pagure-fork-test")
  3556. gitrepo = os.path.join(self.path, "repos", "forks", "foo", "test.git")
  3557. new_repo = pygit2.clone_repository(gitrepo, newpath)
  3558. user = tests.FakeUser()
  3559. user.username = "foo"
  3560. with tests.user_set(self.app.application, user):
  3561. output = self.app.get(
  3562. "/fork/foo/test/diff/master..master", follow_redirects=True
  3563. )
  3564. self.assertEqual(output.status_code, 400)
  3565. self.assertIn(
  3566. "<p>Fork is empty, there are no commits to create a pull "
  3567. "request with</p>",
  3568. output.get_data(as_text=True),
  3569. )
  3570. shutil.rmtree(newpath)
  3571. @patch("pagure.lib.notify.send_email")
  3572. def test_pull_request_add_comment(self, send_email):
  3573. """ Test the pull_request_add_comment endpoint. """
  3574. send_email.return_value = True
  3575. self.test_request_pull()
  3576. user = tests.FakeUser()
  3577. user.username = "pingou"
  3578. with tests.user_set(self.app.application, user):
  3579. output = self.app.post("/foo/pull-request/1/comment")
  3580. self.assertEqual(output.status_code, 404)
  3581. output = self.app.post("/test/pull-request/100/comment")
  3582. self.assertEqual(output.status_code, 404)
  3583. output = self.app.post("/test/pull-request/1/comment")
  3584. self.assertEqual(output.status_code, 200)
  3585. self.assertTrue(
  3586. output.get_data(as_text=True).startswith(
  3587. '\n<section class="add_comment">'
  3588. )
  3589. )
  3590. csrf_token = self.get_csrf(output=output)
  3591. data = {
  3592. "csrf_token": csrf_token,
  3593. "comment": "This look alright but we can do better",
  3594. }
  3595. output = self.app.post(
  3596. "/test/pull-request/1/comment",
  3597. data=data,
  3598. follow_redirects=True,
  3599. )
  3600. self.assertEqual(output.status_code, 200)
  3601. output_text = output.get_data(as_text=True)
  3602. self.assertIn(
  3603. "<title>PR#1: PR from the feature branch - test\n - "
  3604. "Pagure</title>",
  3605. output_text,
  3606. )
  3607. self.assertIn("Comment added", output_text)
  3608. self.assertEqual(output_text.count('title="PY C (pingou)"'), 2)
  3609. # Project w/o pull-request
  3610. repo = pagure.lib.query.get_authorized_project(
  3611. self.session, "test"
  3612. )
  3613. settings = repo.settings
  3614. settings["pull_requests"] = False
  3615. repo.settings = settings
  3616. self.session.add(repo)
  3617. self.session.commit()
  3618. output = self.app.post(
  3619. "/test/pull-request/1/comment",
  3620. data=data,
  3621. follow_redirects=True,
  3622. )
  3623. self.assertEqual(output.status_code, 404)
  3624. @patch("pagure.lib.notify.send_email")
  3625. def test_pull_request_drop_comment(self, send_email):
  3626. """ Test the pull_request_drop_comment endpoint. """
  3627. send_email.return_value = True
  3628. self.test_pull_request_add_comment()
  3629. # Project w/ pull-request
  3630. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  3631. settings = repo.settings
  3632. settings["pull_requests"] = True
  3633. repo.settings = settings
  3634. self.session.add(repo)
  3635. self.session.commit()
  3636. user = tests.FakeUser()
  3637. user.username = "foo"
  3638. with tests.user_set(self.app.application, user):
  3639. output = self.app.post("/foo/pull-request/1/comment/drop")
  3640. self.assertEqual(output.status_code, 404)
  3641. output = self.app.post("/test/pull-request/100/comment/drop")
  3642. self.assertEqual(output.status_code, 404)
  3643. output = self.app.post(
  3644. "/test/pull-request/1/comment/drop", follow_redirects=True
  3645. )
  3646. self.assertEqual(output.status_code, 200)
  3647. output_text = output.get_data(as_text=True)
  3648. self.assertIn(
  3649. '<h4 class="ml-1">\n <div>\n '
  3650. '<span class="fa fa-fw text-success fa-arrow-circle-down pt-1"></span>\n '
  3651. '<span class="text-success '
  3652. 'font-weight-bold">#1</span>\n '
  3653. '<span class="font-weight-bold">\n '
  3654. "PR from the feature branch\n",
  3655. output_text,
  3656. )
  3657. # self.assertIn('href="#comment-1">¶</a>', output_text)
  3658. self.assertIn(
  3659. "<p>This look alright but we can do better</p>", output_text
  3660. )
  3661. csrf_token = self.get_csrf(output=output)
  3662. # Invalid comment id
  3663. data = {"csrf_token": csrf_token, "drop_comment": "10"}
  3664. output = self.app.post(
  3665. "/test/pull-request/1/comment/drop",
  3666. data=data,
  3667. follow_redirects=True,
  3668. )
  3669. self.assertEqual(output.status_code, 404)
  3670. data["drop_comment"] = "1"
  3671. output = self.app.post(
  3672. "/test/pull-request/1/comment/drop",
  3673. data=data,
  3674. follow_redirects=True,
  3675. )
  3676. self.assertEqual(output.status_code, 403)
  3677. user.username = "pingou"
  3678. with tests.user_set(self.app.application, user):
  3679. # Drop comment
  3680. output = self.app.post(
  3681. "/test/pull-request/1/comment/drop",
  3682. data=data,
  3683. follow_redirects=True,
  3684. )
  3685. self.assertEqual(output.status_code, 200)
  3686. output_text = output.get_data(as_text=True)
  3687. self.assertIn(
  3688. '<h4 class="ml-1">\n <div>\n '
  3689. '<span class="fa fa-fw text-success fa-arrow-circle-down pt-1"></span>\n '
  3690. '<span class="text-success '
  3691. 'font-weight-bold">#1</span>\n '
  3692. '<span class="font-weight-bold">\n '
  3693. "PR from the feature branch\n",
  3694. output_text,
  3695. )
  3696. self.assertIn("Comment removed", output_text)
  3697. # Project w/o pull-request
  3698. repo = pagure.lib.query.get_authorized_project(
  3699. self.session, "test"
  3700. )
  3701. settings = repo.settings
  3702. settings["pull_requests"] = False
  3703. repo.settings = settings
  3704. self.session.add(repo)
  3705. self.session.commit()
  3706. output = self.app.post(
  3707. "/test/pull-request/1/comment/drop",
  3708. data=data,
  3709. follow_redirects=True,
  3710. )
  3711. self.assertEqual(output.status_code, 404)
  3712. @patch("pagure.lib.notify.send_email")
  3713. def test_pull_request_edit_comment(self, send_email):
  3714. """ Test the pull request edit comment endpoint """
  3715. send_email.return_value = True
  3716. self.test_request_pull()
  3717. user = tests.FakeUser()
  3718. user.username = "pingou"
  3719. with tests.user_set(self.app.application, user):
  3720. # Repo 'foo' does not exist so it is verifying that condition
  3721. output = self.app.post("/foo/pull-request/1/comment/1/edit")
  3722. self.assertEqual(output.status_code, 404)
  3723. # Here no comment is present in the PR so its verifying that condition
  3724. output = self.app.post("/test/pull-request/100/comment/100/edit")
  3725. self.assertEqual(output.status_code, 404)
  3726. output = self.app.post("/test/pull-request/1/comment")
  3727. self.assertEqual(output.status_code, 200)
  3728. # Creating comment to play with
  3729. self.assertTrue(
  3730. output.get_data(as_text=True).startswith(
  3731. '\n<section class="add_comment">'
  3732. )
  3733. )
  3734. csrf_token = self.get_csrf(output=output)
  3735. data = {
  3736. "csrf_token": csrf_token,
  3737. "comment": "This look alright but we can do better",
  3738. }
  3739. output = self.app.post(
  3740. "/test/pull-request/1/comment",
  3741. data=data,
  3742. follow_redirects=True,
  3743. )
  3744. self.assertEqual(output.status_code, 200)
  3745. output_text = output.get_data(as_text=True)
  3746. self.assertIn(
  3747. '<h4 class="ml-1">\n <div>\n '
  3748. '<span class="fa fa-fw text-success fa-arrow-circle-down pt-1"></span>\n '
  3749. '<span class="text-success '
  3750. 'font-weight-bold">#1</span>\n '
  3751. '<span class="font-weight-bold">\n '
  3752. "PR from the feature branch\n",
  3753. output_text,
  3754. )
  3755. self.assertIn("Comment added", output_text)
  3756. # Check if the comment is there
  3757. self.assertIn(
  3758. "<p>This look alright but we can do better</p>", output_text
  3759. )
  3760. output = self.app.get("/test/pull-request/1/comment/1/edit")
  3761. self.assertEqual(output.status_code, 200)
  3762. output_text = output.get_data(as_text=True)
  3763. self.assertIn('<section class="edit_comment">', output_text)
  3764. # Checking if the comment is there in the update page
  3765. self.assertIn(
  3766. "This look alright but we can do better</textarea>",
  3767. output_text,
  3768. )
  3769. csrf_token = self.get_csrf(output=output)
  3770. data = {
  3771. "csrf_token": csrf_token,
  3772. "update_comment": "This look alright but we can do better than this.",
  3773. }
  3774. output = self.app.post(
  3775. "/test/pull-request/1/comment/1/edit",
  3776. data=data,
  3777. follow_redirects=True,
  3778. )
  3779. output_text = output.get_data(as_text=True)
  3780. # Checking if the comment is updated in the main page
  3781. self.assertIn(
  3782. "<p>This look alright but we can do better than this.</p>",
  3783. output_text,
  3784. )
  3785. self.assertIn(
  3786. '<h4 class="ml-1">\n <div>\n '
  3787. '<span class="fa fa-fw text-success fa-arrow-circle-down pt-1"></span>\n '
  3788. '<span class="text-success '
  3789. 'font-weight-bold">#1</span>\n '
  3790. '<span class="font-weight-bold">\n '
  3791. "PR from the feature branch\n",
  3792. output_text,
  3793. )
  3794. # Checking if Edited by User is there or not
  3795. pattern = (
  3796. re.escape("<small>Edited ")
  3797. + '<span title="[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:'
  3798. + '[0-9]{2} UTC" data-toggle="tooltip">(just now|seconds ago)</span>'
  3799. + re.escape(" by pingou </small>")
  3800. )
  3801. self.assertIsNotNone(re.search(pattern, output_text))
  3802. self.assertIn("Comment updated", output_text)
  3803. # Project w/o pull-request
  3804. repo = pagure.lib.query.get_authorized_project(
  3805. self.session, "test"
  3806. )
  3807. settings = repo.settings
  3808. settings["pull_requests"] = False
  3809. repo.settings = settings
  3810. self.session.add(repo)
  3811. self.session.commit()
  3812. output = self.app.post(
  3813. "/test/pull-request/1/comment/edit/1",
  3814. data=data,
  3815. follow_redirects=True,
  3816. )
  3817. self.assertEqual(output.status_code, 404)
  3818. @patch("pagure.lib.notify.send_email")
  3819. def test_merge_request_pull_FF_w_merge_commit(self, send_email):
  3820. """ Test the merge_request_pull endpoint with a FF PR but with a
  3821. merge commit.
  3822. """
  3823. send_email.return_value = True
  3824. self.test_request_pull()
  3825. user = tests.FakeUser()
  3826. with tests.user_set(self.app.application, user):
  3827. output = self.app.get("/test/pull-request/1")
  3828. self.assertEqual(output.status_code, 200)
  3829. csrf_token = self.get_csrf(output=output)
  3830. # No CSRF
  3831. output = self.app.post(
  3832. "/test/pull-request/1/merge", data={}, follow_redirects=True
  3833. )
  3834. self.assertEqual(output.status_code, 200)
  3835. output_text = output.get_data(as_text=True)
  3836. self.assertIn(
  3837. "<title>PR#1: PR from the feature branch - test\n - "
  3838. "Pagure</title>",
  3839. output_text,
  3840. )
  3841. self.assertIn(
  3842. '<h4 class="ml-1">\n <div>\n '
  3843. '<span class="fa fa-fw text-success fa-arrow-circle-down pt-1"></span>\n '
  3844. '<span class="text-success '
  3845. 'font-weight-bold">#1</span>\n '
  3846. '<span class="font-weight-bold">\n '
  3847. "PR from the feature branch\n",
  3848. output_text,
  3849. )
  3850. self.assertIn(
  3851. 'title="View file as of 2a552b">sources</a>', output_text
  3852. )
  3853. # Wrong project
  3854. data = {"csrf_token": csrf_token}
  3855. output = self.app.post(
  3856. "/foobar/pull-request/100/merge",
  3857. data=data,
  3858. follow_redirects=True,
  3859. )
  3860. self.assertEqual(output.status_code, 404)
  3861. # Wrong project
  3862. data = {"csrf_token": csrf_token}
  3863. output = self.app.post(
  3864. "/test/pull-request/1/merge", data=data, follow_redirects=True
  3865. )
  3866. self.assertEqual(output.status_code, 403)
  3867. user.username = "pingou"
  3868. with tests.user_set(self.app.application, user):
  3869. # Wrong request id
  3870. data = {"csrf_token": csrf_token}
  3871. output = self.app.post(
  3872. "/test/pull-request/100/merge",
  3873. data=data,
  3874. follow_redirects=True,
  3875. )
  3876. self.assertEqual(output.status_code, 404)
  3877. # Project requiring a merge commit
  3878. repo = pagure.lib.query.get_authorized_project(
  3879. self.session, "test"
  3880. )
  3881. settings = repo.settings
  3882. settings["always_merge"] = True
  3883. repo.settings = settings
  3884. self.session.add(repo)
  3885. self.session.commit()
  3886. # Merge
  3887. output = self.app.post(
  3888. "/test/pull-request/1/merge", data=data, follow_redirects=True
  3889. )
  3890. self.assertEqual(output.status_code, 200)
  3891. output = self.app.get("/test/commits")
  3892. output_text = output.get_data(as_text=True)
  3893. self.assertIn(
  3894. "<title>Commits - test - Pagure</title>", output_text
  3895. )
  3896. self.assertIn("Merge #1 `PR from the feature branch`", output_text)
  3897. self.assertIn("A commit on branch feature", output_text)
  3898. # Check if the closing notification was added
  3899. output = self.app.get("/test/pull-request/1")
  3900. output_text = output.get_data(as_text=True)
  3901. self.assertIsNotNone(re.search(MERGED_PATTERN, output_text))
  3902. @patch("pagure.lib.notify.send_email")
  3903. def test_internal_endpoint_main_ahead(self, send_email):
  3904. """ Test the new_request_pull endpoint when the main repo is ahead
  3905. of the fork.
  3906. """
  3907. send_email.return_value = True
  3908. tests.create_projects(self.session)
  3909. tests.create_projects_git(
  3910. os.path.join(self.path, "requests"), bare=True
  3911. )
  3912. set_up_git_repo(
  3913. self.session, self.path, new_project=None, branch_from="feature"
  3914. )
  3915. gitrepo = os.path.join(self.path, "repos", "test.git")
  3916. repo = pygit2.init_repository(gitrepo, bare=True)
  3917. # Make the main repo be ahead of the fork
  3918. # First commit
  3919. newpath = tempfile.mkdtemp(prefix="pagure-test")
  3920. repopath = os.path.join(newpath, "test")
  3921. clone_repo = pygit2.clone_repository(gitrepo, repopath)
  3922. # Create a file in that git repo
  3923. with open(os.path.join(repopath, "testfile"), "w") as stream:
  3924. stream.write("foo\n bar")
  3925. clone_repo.index.add("testfile")
  3926. clone_repo.index.write()
  3927. # Commits the files added
  3928. last_commit = clone_repo.revparse_single("HEAD")
  3929. tree = clone_repo.index.write_tree()
  3930. author = pygit2.Signature("Alice Author", "alice@authors.tld")
  3931. committer = pygit2.Signature("Cecil Committer", "cecil@committers.tld")
  3932. clone_repo.create_commit(
  3933. "refs/heads/master", # the name of the reference to update
  3934. author,
  3935. committer,
  3936. "Add testfile file for testing",
  3937. # binary string representing the tree object ID
  3938. tree,
  3939. # list of binary strings representing parents of the new commit
  3940. [last_commit.oid.hex],
  3941. )
  3942. # Second commit
  3943. with open(os.path.join(repopath, "testfile"), "a") as stream:
  3944. stream.write("\nfoo2\n bar2")
  3945. clone_repo.index.add("testfile")
  3946. clone_repo.index.write()
  3947. # Commits the files added
  3948. last_commit = clone_repo.revparse_single("HEAD")
  3949. tree = clone_repo.index.write_tree()
  3950. author = pygit2.Signature("Alice Author", "alice@authors.tld")
  3951. committer = pygit2.Signature("Cecil Committer", "cecil@committers.tld")
  3952. clone_repo.create_commit(
  3953. "refs/heads/master", # the name of the reference to update
  3954. author,
  3955. committer,
  3956. "Add a second commit to testfile for testing",
  3957. # binary string representing the tree object ID
  3958. tree,
  3959. # list of binary strings representing parents of the new commit
  3960. [last_commit.oid.hex],
  3961. )
  3962. # Third commit
  3963. with open(os.path.join(repopath, "testfile"), "a") as stream:
  3964. stream.write("\nfoo3\n bar3")
  3965. clone_repo.index.add("testfile")
  3966. clone_repo.index.write()
  3967. # Commits the files added
  3968. last_commit = clone_repo.revparse_single("HEAD")
  3969. tree = clone_repo.index.write_tree()
  3970. author = pygit2.Signature("Alice Author", "alice@authors.tld")
  3971. committer = pygit2.Signature("Cecil Committer", "cecil@committers.tld")
  3972. clone_repo.create_commit(
  3973. "refs/heads/master", # the name of the reference to update
  3974. author,
  3975. committer,
  3976. "Add a third commit to testfile for testing",
  3977. # binary string representing the tree object ID
  3978. tree,
  3979. # list of binary strings representing parents of the new commit
  3980. [last_commit.oid.hex],
  3981. )
  3982. refname = "refs/heads/master:refs/heads/master"
  3983. ori_remote = clone_repo.remotes[0]
  3984. PagureRepo.push(ori_remote, refname)
  3985. shutil.rmtree(newpath)
  3986. user = tests.FakeUser()
  3987. user.username = "foo"
  3988. with tests.user_set(self.app.application, user):
  3989. csrf_token = self.get_csrf()
  3990. output = self.app.post(
  3991. "/pv/pull-request/ready",
  3992. data={"repo": "test", "csrf_token": csrf_token},
  3993. )
  3994. self.assertEqual(output.status_code, 200)
  3995. data = json.loads(output.get_data(as_text=True))
  3996. self.assertEqual(sorted(data.keys()), ["code", "task"])
  3997. self.assertEqual(data["code"], "OK")
  3998. @patch("pagure.lib.notify.send_email")
  3999. def test_fork_edit_file(self, send_email):
  4000. """ Test the fork_edit file endpoint. """
  4001. send_email.return_value = True
  4002. # Git repo not found
  4003. output = self.app.post("fork_edit/test/edit/master/f/sources")
  4004. self.assertEqual(output.status_code, 404)
  4005. tests.create_projects(self.session)
  4006. for folder in ["docs", "tickets", "requests", "repos"]:
  4007. tests.create_projects_git(
  4008. os.path.join(self.path, folder), bare=True
  4009. )
  4010. # User not logged in
  4011. output = self.app.post("fork_edit/test/edit/master/f/sources")
  4012. self.assertEqual(output.status_code, 302)
  4013. user = tests.FakeUser()
  4014. user.username = "pingou"
  4015. with tests.user_set(self.app.application, user):
  4016. # Invalid request
  4017. output = self.app.post("fork_edit/test/edit/master/f/source")
  4018. self.assertEqual(output.status_code, 400)
  4019. output = self.app.get("/new/")
  4020. self.assertEqual(output.status_code, 200)
  4021. self.assertIn(
  4022. "<strong>Create new Project</strong>",
  4023. output.get_data(as_text=True),
  4024. )
  4025. csrf_token = self.get_csrf(output=output)
  4026. data = {"csrf_token": csrf_token}
  4027. # No files can be found since they are not added
  4028. output = self.app.post(
  4029. "fork_edit/test/edit/master/f/sources",
  4030. data=data,
  4031. follow_redirects=True,
  4032. )
  4033. self.assertEqual(output.status_code, 404)
  4034. user = tests.FakeUser()
  4035. user.username = "foo"
  4036. with tests.user_set(self.app.application, user):
  4037. data = {"csrf_token": csrf_token}
  4038. # Invalid request
  4039. output = self.app.post(
  4040. "fork_edit/test/edit/master/f/sources", follow_redirects=True
  4041. )
  4042. self.assertEqual(output.status_code, 400)
  4043. # Add content to the repo
  4044. tests.add_content_git_repo(
  4045. os.path.join(pagure.config.config["GIT_FOLDER"], "test.git")
  4046. )
  4047. tests.add_readme_git_repo(
  4048. os.path.join(pagure.config.config["GIT_FOLDER"], "test.git")
  4049. )
  4050. tests.add_binary_git_repo(
  4051. os.path.join(pagure.config.config["GIT_FOLDER"], "test.git"),
  4052. "test.jpg",
  4053. )
  4054. # Check if button exists
  4055. output = self.app.get("/test/blob/master/f/sources")
  4056. self.assertEqual(output.status_code, 200)
  4057. self.assertIn(
  4058. "Fork and Edit\n </button>\n",
  4059. output.get_data(as_text=True),
  4060. )
  4061. # Check fork-edit doesn't show for binary files
  4062. output = self.app.get("/test/blob/master/f/test.jpg")
  4063. self.assertEqual(output.status_code, 200)
  4064. self.assertNotIn(b"<html", output.data)
  4065. # Check for edit panel
  4066. output = self.app.post(
  4067. "fork_edit/test/edit/master/f/sources",
  4068. data=data,
  4069. follow_redirects=True,
  4070. )
  4071. self.assertEqual(output.status_code, 200)
  4072. output_text = output.get_data(as_text=True)
  4073. self.assertIn(
  4074. '<li><a href="/fork/foo/test/tree/master">'
  4075. '<span class="fa fa-random"></span>&nbsp; master</a>'
  4076. '</li><li class="active"><span class="fa fa-file">'
  4077. "</span>&nbsp; sources</li>",
  4078. output_text,
  4079. )
  4080. self.assertIn(
  4081. '<textarea id="textareaCode" name="content">foo\n bar</textarea>',
  4082. output_text,
  4083. )
  4084. # Check for edit panel- Fork already done
  4085. output = self.app.post(
  4086. "fork_edit/test/edit/master/f/sources",
  4087. data=data,
  4088. follow_redirects=True,
  4089. )
  4090. self.assertEqual(output.status_code, 200)
  4091. output_text = output.get_data(as_text=True)
  4092. self.assertIn("<title>Edit - test - Pagure</title>", output_text)
  4093. self.assertIn(
  4094. "You had already forked " "this project", output_text
  4095. )
  4096. self.assertIn(
  4097. '<i class="fa fa-code-fork fa-fw"></i> View Upstream',
  4098. output_text,
  4099. )
  4100. self.assertIn(
  4101. '<li><a href="/fork/foo/test/tree/master">'
  4102. '<span class="fa fa-random"></span>&nbsp; master</a>'
  4103. '</li><li class="active"><span class="fa fa-file">'
  4104. "</span>&nbsp; sources</li>",
  4105. output_text,
  4106. )
  4107. self.assertIn(
  4108. '<textarea id="textareaCode" name="content">foo\n bar</textarea>',
  4109. output_text,
  4110. )
  4111. # View what's supposed to be an image
  4112. output = self.app.post(
  4113. "fork_edit/test/edit/master/f/test.jpg",
  4114. data=data,
  4115. follow_redirects=True,
  4116. )
  4117. self.assertEqual(output.status_code, 400)
  4118. self.assertIn(
  4119. b"<p>Cannot edit binary files</p>", output.data,
  4120. )
  4121. # Check fork-edit shows when user is not logged in
  4122. output = self.app.get("/test/blob/master/f/sources")
  4123. self.assertEqual(output.status_code, 200)
  4124. self.assertIn(
  4125. "Fork and Edit\n </button>\n",
  4126. output.get_data(as_text=True),
  4127. )
  4128. # Check if fork-edit shows for different user
  4129. user.username = "pingou"
  4130. with tests.user_set(self.app.application, user):
  4131. # Check if button exists
  4132. output = self.app.get("/test/blob/master/f/sources")
  4133. self.assertEqual(output.status_code, 200)
  4134. self.assertIn(
  4135. "Edit in your fork\n </button>\n",
  4136. output.get_data(as_text=True),
  4137. )
  4138. # Check fork-edit doesn't show for binary
  4139. output = self.app.get("/test/blob/master/f/test.jpg")
  4140. self.assertEqual(output.status_code, 200)
  4141. self.assertNotIn(b"<html", output.data)
  4142. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  4143. def test_fork_edit_file_namespace(self):
  4144. """ Test the fork_edit file endpoint on a namespaced project. """
  4145. tests.create_projects(self.session)
  4146. for folder in ["docs", "tickets", "requests", "repos"]:
  4147. tests.create_projects_git(
  4148. os.path.join(self.path, folder), bare=True
  4149. )
  4150. # User not logged in
  4151. output = self.app.post(
  4152. "fork_edit/somenamespace/test3/edit/master/f/sources"
  4153. )
  4154. self.assertEqual(output.status_code, 302)
  4155. user = tests.FakeUser()
  4156. user.username = "pingou"
  4157. with tests.user_set(self.app.application, user):
  4158. # Invalid request
  4159. output = self.app.post(
  4160. "fork_edit/somenamespace/test3/edit/master/f/sources"
  4161. )
  4162. self.assertEqual(output.status_code, 400)
  4163. output = self.app.get("/new/")
  4164. self.assertEqual(output.status_code, 200)
  4165. self.assertIn(
  4166. "<strong>Create new Project</strong>",
  4167. output.get_data(as_text=True),
  4168. )
  4169. csrf_token = self.get_csrf(output=output)
  4170. data = {"csrf_token": csrf_token}
  4171. # No files can be found since they are not added
  4172. output = self.app.post(
  4173. "fork_edit/somenamespace/test3/edit/master/f/sources",
  4174. data=data,
  4175. follow_redirects=True,
  4176. )
  4177. self.assertEqual(output.status_code, 404)
  4178. user = tests.FakeUser()
  4179. user.username = "foo"
  4180. with tests.user_set(self.app.application, user):
  4181. data = {"csrf_token": csrf_token}
  4182. # Invalid request
  4183. output = self.app.post(
  4184. "fork_edit/somenamespace/test3/edit/master/f/sources",
  4185. follow_redirects=True,
  4186. )
  4187. self.assertEqual(output.status_code, 400)
  4188. # Add content to the repo
  4189. tests.add_content_git_repo(
  4190. os.path.join(
  4191. pagure.config.config["GIT_FOLDER"],
  4192. "somenamespace",
  4193. "test3.git",
  4194. )
  4195. )
  4196. tests.add_readme_git_repo(
  4197. os.path.join(
  4198. pagure.config.config["GIT_FOLDER"],
  4199. "somenamespace",
  4200. "test3.git",
  4201. )
  4202. )
  4203. tests.add_binary_git_repo(
  4204. os.path.join(
  4205. pagure.config.config["GIT_FOLDER"],
  4206. "somenamespace",
  4207. "test3.git",
  4208. ),
  4209. "test.jpg",
  4210. )
  4211. # Check if button exists
  4212. output = self.app.get("/somenamespace/test3/blob/master/f/sources")
  4213. self.assertEqual(output.status_code, 200)
  4214. self.assertIn(
  4215. "Fork and Edit\n </button>\n",
  4216. output.get_data(as_text=True),
  4217. )
  4218. # Check fork-edit doesn't show for binary files
  4219. output = self.app.get(
  4220. "/somenamespace/test3/blob/master/f/test.jpg"
  4221. )
  4222. self.assertEqual(output.status_code, 200)
  4223. self.assertNotIn(b"<html", output.data)
  4224. # Check for edit panel
  4225. output = self.app.post(
  4226. "fork_edit/somenamespace/test3/edit/master/f/sources",
  4227. data=data,
  4228. follow_redirects=True,
  4229. )
  4230. self.assertEqual(output.status_code, 200)
  4231. output_text = output.get_data(as_text=True)
  4232. self.assertIn(
  4233. "<title>Edit - somenamespace/test3 - Pagure</title>",
  4234. output_text,
  4235. )
  4236. self.assertIn(
  4237. '<i class="fa fa-code-fork fa-fw"></i> View Upstream',
  4238. output_text,
  4239. )
  4240. self.assertIn(
  4241. '<li><a href="/fork/foo/somenamespace/test3/tree/master">'
  4242. '<span class="fa fa-random"></span>&nbsp; master</a>'
  4243. '</li><li class="active"><span class="fa fa-file">'
  4244. "</span>&nbsp; sources</li>",
  4245. output_text,
  4246. )
  4247. self.assertIn(
  4248. '<textarea id="textareaCode" name="content">foo\n bar</textarea>',
  4249. output_text,
  4250. )
  4251. # Check for edit panel - while the project was already forked
  4252. output = self.app.post(
  4253. "fork_edit/somenamespace/test3/edit/master/f/sources",
  4254. data=data,
  4255. follow_redirects=True,
  4256. )
  4257. self.assertEqual(output.status_code, 200)
  4258. output_text = output.get_data(as_text=True)
  4259. self.assertIn(
  4260. "<title>Edit - somenamespace/test3 - Pagure</title>",
  4261. output_text,
  4262. )
  4263. self.assertIn(
  4264. "You had already forked " "this project", output_text
  4265. )
  4266. self.assertIn(
  4267. '<i class="fa fa-code-fork fa-fw"></i> View Upstream',
  4268. output_text,
  4269. )
  4270. self.assertIn(
  4271. '<li><a href="/fork/foo/somenamespace/test3/tree/master">'
  4272. '<span class="fa fa-random"></span>&nbsp; master</a>'
  4273. '</li><li class="active"><span class="fa fa-file">'
  4274. "</span>&nbsp; sources</li>",
  4275. output_text,
  4276. )
  4277. self.assertIn(
  4278. '<textarea id="textareaCode" name="content">foo\n bar</textarea>',
  4279. output_text,
  4280. )
  4281. @patch("pagure.lib.notify.send_email")
  4282. def test_fork_without_main_repo(self, send_email):
  4283. """ Test the fork without the main repo. """
  4284. send_email.return_value = True
  4285. tests.create_projects(self.session)
  4286. # Create a fork with no parent i.e parent_id = None
  4287. item = pagure.lib.model.Project(
  4288. user_id=2, # foo
  4289. name="test",
  4290. description="test project #1",
  4291. hook_token="aaabbb",
  4292. is_fork=True,
  4293. parent_id=None,
  4294. )
  4295. self.session.add(item)
  4296. self.session.commit()
  4297. # Get fork project
  4298. project = pagure.lib.query._get_project(self.session, "test", "foo")
  4299. # Pull-requests and issue-trackers are off for forks
  4300. # lib function is not used here so mannually turning them off
  4301. project_settings = project.settings
  4302. project_settings["pull_requests"] = False
  4303. project_settings["issue_tracker"] = False
  4304. project.settings = project_settings
  4305. self.session.add(project)
  4306. self.session.commit()
  4307. tests.create_projects_git(
  4308. os.path.join(self.path, "repos", "forks", "foo"), bare=True
  4309. )
  4310. # Create a git repo to play with
  4311. gitrepo = os.path.join(self.path, "repos", "test.git")
  4312. self.assertFalse(os.path.exists(gitrepo))
  4313. os.makedirs(gitrepo)
  4314. repo = pygit2.init_repository(gitrepo, bare=True)
  4315. # Create a fork of this repo
  4316. newpath = tempfile.mkdtemp(prefix="pagure-fork-test")
  4317. gitrepo = os.path.join(self.path, "repos", "forks", "foo", "test.git")
  4318. new_repo = pygit2.clone_repository(gitrepo, newpath)
  4319. tests.add_content_git_repo(gitrepo)
  4320. # UI test for deleted main
  4321. output = self.app.get("/fork/foo/test")
  4322. self.assertEqual(output.status_code, 200)
  4323. self.assertIn(
  4324. "Forked from a deleted repository", output.get_data(as_text=True)
  4325. )
  4326. # Testing commit endpoint
  4327. output = self.app.get("/fork/foo/test/commits/master")
  4328. self.assertEqual(output.status_code, 200)
  4329. self.assertIn(
  4330. 'Commits <span class="badge badge-secondary"> 2</span>\n',
  4331. output.get_data(as_text=True),
  4332. )
  4333. # Test pull-request endpoint
  4334. output = self.app.get("/fork/foo/test/pull-requests")
  4335. self.assertEqual(output.status_code, 404)
  4336. # Test issue-tracker endpoint
  4337. output = self.app.get("/fork/foo/test/issues")
  4338. self.assertEqual(output.status_code, 404)
  4339. shutil.rmtree(newpath)
  4340. def _set_up_for_reaction_test(self):
  4341. self.session.add(
  4342. pagure.lib.model.User(
  4343. user="jdoe",
  4344. fullname="John Doe",
  4345. password=b"password",
  4346. default_email="jdoe@example.com",
  4347. )
  4348. )
  4349. self.session.commit()
  4350. tests.create_projects(self.session)
  4351. tests.create_projects_git(
  4352. os.path.join(self.path, "requests"), bare=True
  4353. )
  4354. set_up_git_repo(
  4355. self.session, self.path, new_project=None, branch_from="feature"
  4356. )
  4357. pagure.lib.query.get_authorized_project(self.session, "test")
  4358. request = pagure.lib.query.search_pull_requests(
  4359. self.session, requestid=1, project_id=1
  4360. )
  4361. pagure.lib.query.add_pull_request_comment(
  4362. self.session,
  4363. request=request,
  4364. commit=None,
  4365. tree_id=None,
  4366. filename=None,
  4367. row=None,
  4368. comment="Hello",
  4369. user="jdoe",
  4370. )
  4371. self.session.commit()
  4372. @patch("pagure.lib.notify.send_email")
  4373. def test_add_reaction(self, send_email):
  4374. """ Test the request_pull endpoint. """
  4375. send_email.return_value = True
  4376. self._set_up_for_reaction_test()
  4377. user = tests.FakeUser()
  4378. user.username = "pingou"
  4379. with tests.user_set(self.app.application, user):
  4380. output = self.app.get("/test/pull-request/1")
  4381. self.assertEqual(output.status_code, 200)
  4382. data = {
  4383. "csrf_token": self.get_csrf(output=output),
  4384. "reaction": "Thumbs up",
  4385. }
  4386. output = self.app.post(
  4387. "/test/pull-request/1/comment/1/react",
  4388. data=data,
  4389. follow_redirects=True,
  4390. )
  4391. self.assertEqual(output.status_code, 200)
  4392. # Load the page and check reaction is added.
  4393. output = self.app.get("/test/pull-request/1")
  4394. self.assertEqual(output.status_code, 200)
  4395. self.assertIn(
  4396. "Thumbs up sent by pingou", output.get_data(as_text=True)
  4397. )
  4398. @patch("pagure.lib.notify.send_email")
  4399. def test_add_reaction_unauthenticated(self, send_email):
  4400. """ Test the request_pull endpoint. """
  4401. send_email.return_value = True
  4402. self._set_up_for_reaction_test()
  4403. output = self.app.get("/test/pull-request/1")
  4404. self.assertEqual(output.status_code, 200)
  4405. data = {
  4406. "csrf_token": self.get_csrf(output=output),
  4407. "reaction": "Thumbs down",
  4408. }
  4409. output = self.app.post(
  4410. "/test/pull-request/1/comment/1/react",
  4411. data=data,
  4412. follow_redirects=False,
  4413. )
  4414. # Redirect to login page
  4415. self.assertEqual(output.status_code, 302)
  4416. self.assertIn("/login/", output.headers["Location"])
  4417. class TestTicketAccessEditPRMetadata(tests.Modeltests):
  4418. """ Tests that people with ticket access on a project can edit the
  4419. meta-data of a PR """
  4420. def setUp(self):
  4421. """ Set up the environnment, ran before every tests. """
  4422. super(TestTicketAccessEditPRMetadata, self).setUp()
  4423. tests.create_projects(self.session)
  4424. tests.create_projects_git(
  4425. os.path.join(self.path, "requests"), bare=True
  4426. )
  4427. set_up_git_repo(
  4428. self.session, self.path, new_project=None, branch_from="feature"
  4429. )
  4430. # Add user "foo" to the project "test"
  4431. repo = pagure.lib.query._get_project(self.session, "test")
  4432. msg = pagure.lib.query.add_user_to_project(
  4433. session=self.session,
  4434. project=repo,
  4435. new_user="foo",
  4436. user="pingou",
  4437. access="ticket",
  4438. )
  4439. self.session.commit()
  4440. self.assertEqual(msg, "User added")
  4441. def test_unauth_cannot_view_edit_metadata_ui(self):
  4442. """ Test that unauthenticated users cannot view the edit the
  4443. metadata fields in the UI. """
  4444. output = self.app.get("/test/pull-request/1")
  4445. self.assertEqual(output.status_code, 200)
  4446. output_text = output.get_data(as_text=True)
  4447. self.assertIn(
  4448. "<title>PR#1: PR from the feature branch - test\n"
  4449. " - Pagure</title>",
  4450. output_text,
  4451. )
  4452. self.assertIn(
  4453. '<i class="fa fa-fw fa-pencil"></i></a>',
  4454. '<a class="btn btn-outline-primary border-0 btn-sm '
  4455. "issue-metadata-display editmetadatatoggle pointer inline-block"
  4456. '"><i class="fa fa-fw fa-pencil"></i></a>',
  4457. output_text,
  4458. )
  4459. self.assertNotIn(
  4460. '<form method="POST" action="/test/pull-request/1/update">',
  4461. output_text,
  4462. )
  4463. def test_admin_can_view_edit_metadata_ui(self):
  4464. """ Test that admin users can view the edit the metadata fields in
  4465. the UI. """
  4466. user = tests.FakeUser(username="pingou")
  4467. with tests.user_set(self.app.application, user):
  4468. output = self.app.get("/test/pull-request/1")
  4469. self.assertEqual(output.status_code, 200)
  4470. output_text = output.get_data(as_text=True)
  4471. self.assertIn(
  4472. "<title>PR#1: PR from the feature branch - test\n"
  4473. " - Pagure</title>",
  4474. output_text,
  4475. )
  4476. self.assertIn(
  4477. '<i class="fa fa-fw fa-pencil"></i></a>',
  4478. '<a class="btn btn-outline-primary border-0 btn-sm '
  4479. "issue-metadata-display editmetadatatoggle pointer inline-block"
  4480. '"><i class="fa fa-fw fa-pencil"></i></a>',
  4481. output_text,
  4482. )
  4483. self.assertIn(
  4484. '<form method="POST" action="/test/pull-request/1/update">',
  4485. output_text,
  4486. )
  4487. def test_admin_can_edit_metadata_ui(self):
  4488. """ Test that admin users can edit the metadata in the UI. """
  4489. user = tests.FakeUser(username="pingou")
  4490. with tests.user_set(self.app.application, user):
  4491. data = {"csrf_token": self.get_csrf(), "user": "foo"}
  4492. output = self.app.post(
  4493. "/test/pull-request/1/update", data=data, follow_redirects=True
  4494. )
  4495. self.assertEqual(output.status_code, 200)
  4496. output_text = output.get_data(as_text=True)
  4497. self.assertIn(
  4498. "<title>PR#1: PR from the feature branch - test\n"
  4499. " - Pagure</title>",
  4500. output_text,
  4501. )
  4502. self.assertIn(
  4503. '<i class="fa fa-fw fa-pencil"></i></a>',
  4504. '<a class="btn btn-outline-primary border-0 btn-sm '
  4505. "issue-metadata-display editmetadatatoggle pointer inline-block"
  4506. '"><i class="fa fa-fw fa-pencil"></i></a>',
  4507. output_text,
  4508. )
  4509. self.assertIn(
  4510. '<form method="POST" action="/test/pull-request/1/update">',
  4511. output_text,
  4512. )
  4513. self.assertIn(
  4514. '<input value="foo"\n name="user" '
  4515. 'id="assignee" placeholder="username" >',
  4516. output_text,
  4517. )
  4518. def test_ticket_can_view_edit_metadata_ui(self):
  4519. """ Test that users with ticket access can view the edit the
  4520. metadata fields in the UI. """
  4521. user = tests.FakeUser(username="foo")
  4522. with tests.user_set(self.app.application, user):
  4523. output = self.app.get("/test/pull-request/1")
  4524. self.assertEqual(output.status_code, 200)
  4525. output_text = output.get_data(as_text=True)
  4526. self.assertIn(
  4527. "<title>PR#1: PR from the feature branch - test\n"
  4528. " - Pagure</title>",
  4529. output_text,
  4530. )
  4531. self.assertIn(
  4532. '<i class="fa fa-fw fa-pencil"></i></a>',
  4533. '<a class="btn btn-outline-primary border-0 btn-sm '
  4534. "issue-metadata-display editmetadatatoggle pointer inline-block"
  4535. '"><i class="fa fa-fw fa-pencil"></i></a>',
  4536. output_text,
  4537. )
  4538. self.assertIn(
  4539. '<form method="POST" action="/test/pull-request/1/update">',
  4540. output_text,
  4541. )
  4542. def test_ticket_can_edit_metadata_ui(self):
  4543. """ Test that users with ticket access can edit the metadata in the
  4544. UI. """
  4545. user = tests.FakeUser(username="foo")
  4546. with tests.user_set(self.app.application, user):
  4547. data = {"csrf_token": self.get_csrf(), "user": "pingou"}
  4548. output = self.app.post(
  4549. "/test/pull-request/1/update", data=data, follow_redirects=True
  4550. )
  4551. self.assertEqual(output.status_code, 200)
  4552. output_text = output.get_data(as_text=True)
  4553. self.assertIn(
  4554. "<title>PR#1: PR from the feature branch - test\n"
  4555. " - Pagure</title>",
  4556. output_text,
  4557. )
  4558. self.assertIn(
  4559. '<i class="fa fa-fw fa-pencil"></i></a>',
  4560. '<a class="btn btn-outline-primary border-0 btn-sm '
  4561. "issue-metadata-display editmetadatatoggle pointer inline-block"
  4562. '"><i class="fa fa-fw fa-pencil"></i></a>',
  4563. output_text,
  4564. )
  4565. self.assertIn(
  4566. '<form method="POST" action="/test/pull-request/1/update">',
  4567. output_text,
  4568. )
  4569. self.assertIn(
  4570. '<input value="pingou"\n name="user" '
  4571. 'id="assignee" placeholder="username" >',
  4572. output_text,
  4573. )
  4574. if __name__ == "__main__":
  4575. unittest.main(verbosity=2)