test_pagure_flask_ui_issues.py 185 KB

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