test_pagure_flask_ui_fork.py 156 KB

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