test_pagure_flask_ui_fork.py 187 KB

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